Skip to content

Commit cce0862

Browse files
mfasDaBarthelemy
authored andcommitted
[EMCAL-524] Prototype QC component for EMCAL digits (#198)
Digits component monitoring digit amplitude and time for each tower separately. Creating also the EMCAL module. In order to run the Digits QC task a separate workflow (qcRunEmcalDigit) is used. The data source is an EMCAL publisher implemented in the O2 EMCAL reco workflow supporting only digits for the moment. The QC task are initialized using the standard method via a configuration file.
1 parent 89dd9a0 commit cce0862

8 files changed

Lines changed: 379 additions & 0 deletions

File tree

Modules/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@ add_subdirectory(Daq)
55
add_subdirectory(Example)
66
add_subdirectory(Skeleton)
77
add_subdirectory(TOF)
8+
add_subdirectory(EMCAL)

Modules/EMCAL/CMakeLists.txt

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
# ---- Library ----
2+
3+
add_library(QcEMCAL src/DigitsQcTask.cxx)
4+
5+
target_include_directories(
6+
QcEMCAL
7+
PUBLIC $<INSTALL_INTERFACE:include> $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
8+
PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src
9+
)
10+
11+
target_link_libraries(QcEMCAL PUBLIC QualityControl O2::EMCALBase)
12+
13+
add_root_dictionary(QcEMCAL
14+
HEADERS include/EMCAL/DigitsQcTask.h
15+
LINKDEF include/EMCAL/LinkDef.h
16+
BASENAME QcEMCAL)
17+
18+
install(TARGETS QcEMCAL
19+
LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
20+
ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
21+
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
22+
23+
install (
24+
DIRECTORY etc DESTINATION Modules/EMCAL
25+
)
26+
27+
# ---- Executables ----
28+
29+
add_executable(qcRunEmcalDigit src/runQCEMCALDigits.cxx)
30+
target_link_libraries(qcRunEmcalDigit PUBLIC QualityControl QcEMCAL O2::DataFormatsEMCAL O2::EMCALBase O2::EMCALWorkflow)
31+
install(
32+
TARGETS qcRunEmcalDigit
33+
RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}
34+
)
35+
36+
# ---- Tests ----
37+
38+
set(
39+
TEST_SRCS
40+
)
41+
42+
foreach(test ${TEST_SRCS})
43+
get_filename_component(test_name ${test} NAME)
44+
string(REGEX REPLACE ".cxx" "" test_name ${test_name})
45+
46+
add_executable(${test_name} ${test})
47+
target_link_libraries(${test_name} PRIVATE ${MODULE_NAME} Boost::unit_test_framework)
48+
add_test(NAME ${test_name} COMMAND ${test_name})
49+
set_tests_properties(${test_name} PROPERTIES TIMEOUT 60)
50+
endforeach()

Modules/EMCAL/etc/digits.json

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
{
2+
"qc": {
3+
"config": {
4+
"database": {
5+
"implementation": "CCDB",
6+
"host": "emcccdb-test.cern.ch:8080",
7+
"username": "not_applicable",
8+
"password": "not_applicable",
9+
"name": "not_applicable"
10+
},
11+
"Activity": {
12+
"number": "42",
13+
"type": "2"
14+
},
15+
"monitoring": {
16+
"url": "infologger:///debug?qc"
17+
},
18+
"consul": {
19+
"url": "http://consul-test.cern.ch:8500"
20+
}
21+
},
22+
"tasks": {
23+
"QcTask": {
24+
"active": "true",
25+
"className": "o2::quality_control_modules::emcal::DigitsQcTask",
26+
"moduleName": "QcEMCAL",
27+
"cycleDurationSeconds": "10",
28+
"maxNumberCycles": "-1",
29+
"dataSource": {
30+
"type": "direct",
31+
"binding": "emcal-digits",
32+
"dataOrigin": "EMC",
33+
"dataDescription": "DIGITS",
34+
"subSpec": "0"
35+
},
36+
"taskParameters": {
37+
"nothing": "rien"
38+
},
39+
"location": "remote"
40+
}
41+
}
42+
},
43+
"dataSamplingPolicies": [
44+
45+
]
46+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
///
2+
/// \file DigitsQcTask.h
3+
/// \author Markus Fasel
4+
///
5+
6+
#ifndef QC_MODULE_EMCAL_DIGITSQCTASK_H
7+
#define QC_MODULE_EMCAL_DIGITSQCTASK_H
8+
9+
#include "QualityControl/TaskInterface.h"
10+
11+
class TH2F;
12+
13+
using namespace o2::quality_control::core;
14+
15+
namespace o2
16+
{
17+
namespace quality_control_modules
18+
{
19+
namespace emcal
20+
{
21+
22+
/// \brief QC Task for EMCAL digits
23+
/// \author Markus Fasel
24+
///
25+
/// The main monitoring component for EMCAL digits (energy and time measurement in tower).
26+
/// Monitoring observables:
27+
/// - Digit amplitude for different towers
28+
/// - Digit time for different towers
29+
class DigitsQcTask /*final*/ : public TaskInterface // todo add back the "final" when doxygen is fixed
30+
{
31+
public:
32+
/// \brief Constructor
33+
DigitsQcTask() = default;
34+
/// Destructor
35+
~DigitsQcTask() override;
36+
37+
// Definition of the methods for the template method pattern
38+
void initialize(o2::framework::InitContext& ctx) override;
39+
void startOfActivity(Activity& activity) override;
40+
void startOfCycle() override;
41+
void monitorData(o2::framework::ProcessingContext& ctx) override;
42+
void endOfCycle() override;
43+
void endOfActivity(Activity& activity) override;
44+
void reset() override;
45+
46+
private:
47+
TH2F* mDigitAmplitude; ///< Digit amplitude
48+
TH2F* mDigitTime; ///< Digit time
49+
};
50+
51+
} // namespace emcal
52+
} // namespace quality_control_modules
53+
} // namespace o2
54+
55+
#endif // QC_MODULE_EMCAL_DIGITSQCTASK_H
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#ifdef __CLING__
2+
#pragma link off all globals;
3+
#pragma link off all classes;
4+
#pragma link off all functions;
5+
6+
#pragma link C++ class o2::quality_control_modules::emcal::DigitsQcTask+;
7+
#endif

Modules/EMCAL/src/DigitsQcTask.cxx

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
///
2+
/// \file DigitsQcTask.cxx
3+
/// \author Markus Fasel
4+
///
5+
6+
#include <TCanvas.h>
7+
#include <TH2.h>
8+
9+
#include "QualityControl/QcInfoLogger.h"
10+
#include "DataFormatsEMCAL/EMCALBlockHeader.h"
11+
#include "EMCAL/DigitsQcTask.h"
12+
#include "DataFormatsEMCAL/Digit.h"
13+
14+
namespace o2
15+
{
16+
namespace quality_control_modules
17+
{
18+
namespace emcal
19+
{
20+
21+
DigitsQcTask::~DigitsQcTask()
22+
{
23+
if (mDigitAmplitude) {
24+
delete mDigitAmplitude;
25+
}
26+
if (mDigitTime) {
27+
delete mDigitTime;
28+
}
29+
}
30+
31+
void DigitsQcTask::initialize(o2::framework::InitContext& /*ctx*/)
32+
{
33+
QcInfoLogger::GetInstance() << "initialize DigitsQcTask" << AliceO2::InfoLogger::InfoLogger::endm;
34+
35+
mDigitAmplitude = new TH2F("digitAmplitude", "Digit Amplitude", 100, 0, 100, 20000, 0., 20000.);
36+
mDigitTime = new TH2F("digitTime", "Digit Time", 1000, 0, 1000, 20000, 0., 20000.);
37+
getObjectsManager()->startPublishing(mDigitAmplitude);
38+
getObjectsManager()->startPublishing(mDigitTime);
39+
//getObjectsManager()->addCheck(mDigitAmplitude, "checkFromEMCAL", "o2::quality_control_modules::emcal::EMCALCheck",
40+
// "QcEMCAL");
41+
}
42+
43+
void DigitsQcTask::startOfActivity(Activity& /*activity*/)
44+
{
45+
QcInfoLogger::GetInstance() << "startOfActivity" << AliceO2::InfoLogger::InfoLogger::endm;
46+
mDigitAmplitude->Reset();
47+
mDigitTime->Reset();
48+
}
49+
50+
void DigitsQcTask::startOfCycle()
51+
{
52+
QcInfoLogger::GetInstance() << "startOfCycle" << AliceO2::InfoLogger::InfoLogger::endm;
53+
}
54+
55+
void DigitsQcTask::monitorData(o2::framework::ProcessingContext& ctx)
56+
{
57+
QcInfoLogger::GetInstance() << "Start monitor data" << AliceO2::InfoLogger::InfoLogger::endm;
58+
59+
// check if we have payoad
60+
auto dataref = ctx.inputs().get("emcal-digits");
61+
auto const* emcheader = o2::framework::DataRefUtils::getHeader<o2::emcal::EMCALBlockHeader*>(dataref);
62+
if (!emcheader->mHasPayload) {
63+
QcInfoLogger::GetInstance() << "No more digits" << AliceO2::InfoLogger::InfoLogger::endm;
64+
//ctx.services().get<o2::framework::ControlService>().readyToQuit(false);
65+
return;
66+
}
67+
// Get payload and loop over digits
68+
auto digitcontainer = ctx.inputs().get<std::vector<o2::emcal::Digit>>("emcal-digits");
69+
QcInfoLogger::GetInstance() << "Received " << digitcontainer.size() << " digits " << AliceO2::InfoLogger::InfoLogger::endm;
70+
for (auto digit : digitcontainer) {
71+
mDigitAmplitude->Fill(digit.getEnergy(), digit.getTower());
72+
mDigitTime->Fill(digit.getTimeStamp(), digit.getTower());
73+
}
74+
}
75+
76+
void DigitsQcTask::endOfCycle()
77+
{
78+
QcInfoLogger::GetInstance() << "endOfCycle" << AliceO2::InfoLogger::InfoLogger::endm;
79+
}
80+
81+
void DigitsQcTask::endOfActivity(Activity& /*activity*/)
82+
{
83+
QcInfoLogger::GetInstance() << "endOfActivity" << AliceO2::InfoLogger::InfoLogger::endm;
84+
}
85+
86+
void DigitsQcTask::reset()
87+
{
88+
// clean all the monitor objects here
89+
90+
QcInfoLogger::GetInstance() << "Resetting the histogram" << AliceO2::InfoLogger::InfoLogger::endm;
91+
mDigitAmplitude->Reset();
92+
mDigitTime->Reset();
93+
}
94+
95+
} // namespace emcal
96+
} // namespace quality_control_modules
97+
} // namespace o2
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
#include <string>
2+
#include <TH1.h>
3+
4+
#include "Framework/DataSampling.h"
5+
#include "Framework/DataSamplingReadoutAdapter.h"
6+
#include "EMCALWorkflow/PublisherSpec.h"
7+
#include "QualityControl/InfrastructureGenerator.h"
8+
#include "QualityControl/Checker.h"
9+
#include "QualityControl/CheckerFactory.h"
10+
11+
void customize(std::vector<o2::framework::CompletionPolicy>& policies)
12+
{
13+
o2::framework::DataSampling::CustomizeInfrastructure(policies);
14+
o2::quality_control::customizeInfrastructure(policies);
15+
}
16+
17+
void customize(std::vector<o2::framework::ChannelConfigurationPolicy>& policies)
18+
{
19+
o2::framework::DataSampling::CustomizeInfrastructure(policies);
20+
}
21+
22+
void customize(std::vector<o2::framework::ConfigParamSpec>& workflowOptions)
23+
{
24+
workflowOptions.push_back(
25+
o2::framework::ConfigParamSpec{ "config-path", o2::framework::VariantType::String, "", { "Path to the config file. Overwrite the default paths. Do not use with no-data-sampling." } });
26+
workflowOptions.push_back(
27+
o2::framework::ConfigParamSpec{ "no-data-sampling", o2::framework::VariantType::Bool, false, { "Skips data sampling, connects directly the task to the producer." } });
28+
}
29+
30+
#include "Framework/runDataProcessing.h"
31+
32+
std::string getConfigPath(const o2::framework::ConfigContext& config);
33+
34+
o2::framework::WorkflowSpec defineDataProcessing(o2::framework::ConfigContext const& config)
35+
{
36+
o2::framework::WorkflowSpec specs;
37+
specs.push_back(o2::emcal::getPublisherSpec(o2::emcal::PublisherConf{
38+
"emcal-digit-reader",
39+
"o2sim",
40+
{ "digitbranch", "EMCALDigit", "Digit branch" },
41+
{ "mcbranch", "EMCALDigitMCTruth", "MC label branch" },
42+
o2::framework::OutputSpec{ "EMC", "DIGITS" },
43+
o2::framework::OutputSpec{ "EMC", "DIGITSMCTR" } },
44+
false));
45+
46+
// Path to the config file
47+
std::string qcConfigurationSource = getConfigPath(config);
48+
49+
// Generation of the QC topology
50+
o2::quality_control::generateRemoteInfrastructure(specs, qcConfigurationSource);
51+
52+
/*
53+
o2::framework::DataProcessorSpec printer{
54+
"printer",
55+
o2::framework::Inputs{
56+
{"checked-mo", "QC", o2::quality_control::checker::Checker::createCheckerDataDescription("DigitsQcTask"), 0}
57+
},
58+
o2::framework::Outputs{},
59+
o2::framework::AlgorithmSpec{
60+
(o2::framework::AlgorithmSpec::InitCallback) [](o2::framework::InitContext& initContext) {
61+
62+
return (o2::framework::AlgorithmSpec::ProcessCallback) [](o2::framework::ProcessingContext& processingContext) mutable {
63+
std::shared_ptr<TObjArray> moArray{
64+
std::move(o2::framework::DataRefUtils::as<TObjArray>(*processingContext.inputs().begin()))
65+
};
66+
67+
for (const auto& to : *moArray) {
68+
MonitorObject* mo = dynamic_cast<MonitorObject*>(to);
69+
70+
if (mo->getName() == "example") {
71+
auto* g = dynamic_cast<TH1F*>(mo->getObject());
72+
std::string bins = "BINS:";
73+
for (int i = 0; i < g->GetNbinsX(); i++) {
74+
bins += " " + std::to_string((int) g->GetBinContent(i));
75+
}
76+
LOG(INFO) << bins;
77+
}
78+
}
79+
};
80+
}
81+
}
82+
};
83+
specs.push_back(printer);
84+
*/
85+
LOG(INFO) << "Using config file '" << qcConfigurationSource << "'";
86+
o2::framework::DataSampling::GenerateInfrastructure(specs, qcConfigurationSource);
87+
88+
return specs;
89+
}
90+
91+
std::string getConfigPath(const o2::framework::ConfigContext& config)
92+
{
93+
std::string userConfigPath = config.options().get<std::string>("config-path");
94+
std::string defaultConfigPath = getenv("QUALITYCONTROL_ROOT") != nullptr ? std::string(getenv("QUALITYCONTROL_ROOT")) + "/Modules/EMCAL/etc/digits.json" : "$QUALITYCONTROL_ROOT undefined";
95+
std::string path = userConfigPath == "" ? defaultConfigPath : userConfigPath;
96+
const std::string qcConfigurationSource = std::string("json:/") + path;
97+
return qcConfigurationSource;
98+
}

Modules/EMCAL/test/testEMCAL.cxx

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
///
2+
/// \file testEMCAL.cxx
3+
/// \author
4+
///
5+
6+
#include "QualityControl/TaskFactory.h"
7+
8+
#define BOOST_TEST_MODULE Publisher test
9+
#define BOOST_TEST_MAIN
10+
#define BOOST_TEST_DYN_LINK
11+
12+
#include <boost/test/unit_test.hpp>
13+
14+
namespace o2
15+
{
16+
namespace quality_control_modules
17+
{
18+
namespace emcal
19+
{
20+
21+
BOOST_AUTO_TEST_CASE(instantiate_task) { BOOST_CHECK(true); }
22+
23+
} // namespace emcal
24+
} // namespace quality_control_modules
25+
} // namespace o2

0 commit comments

Comments
 (0)