Skip to content

Commit 787a076

Browse files
Implementation of parsing of LHC-IF file (#7148)
* Implementation of parsing of LHC-IF file Parser Workflow and data type space checker clang-format remove file added by mistake * Possibility to have GRP as data origin for dcs-config-proxy (for LHIF) remove logging clang-format changing schema --> scheme * Comments to PR clang-format leftover fixed * FUrther comments
1 parent 5a3a97b commit 787a076

15 files changed

Lines changed: 652 additions & 9 deletions

File tree

DataFormats/Parameters/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,17 @@
1111

1212
o2_add_library(DataFormatsParameters
1313
SOURCES src/GRPObject.cxx
14+
src/LHCIFData.cxx
1415
PUBLIC_LINK_LIBRARIES FairRoot::Base O2::CommonConstants
1516
O2::CommonTypes
1617
O2::DetectorsCommonDataFormats)
1718

1819
o2_target_root_dictionary(DataFormatsParameters
1920
HEADERS include/DataFormatsParameters/GRPObject.h
21+
include/DataFormatsParameters/LHCIFData.h
2022
LINKDEF src/ParametersDataLinkDef.h)
23+
24+
2125
# note we are explicitely giving the LINKDEF parameter as the LinkDef does not
2226
# follow the usual naming scheme [module]LinkDef.h
2327
#
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2+
// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3+
// All rights not expressly granted are reserved.
4+
//
5+
// This software is distributed under the terms of the GNU General Public
6+
// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7+
//
8+
// In applying this license CERN does not waive the privileges and immunities
9+
// granted to it by virtue of its status as an Intergovernmental Organization
10+
// or submit itself to any jurisdiction.
11+
12+
/// \file LHCIFData.h
13+
/// \brief container for the LHC InterFace data
14+
15+
#ifndef O2_GRP_LHCIFDATA_H
16+
#define O2_GRP_LHCIFDATA_H
17+
18+
#include <Rtypes.h>
19+
#include <string>
20+
#include <cstdint>
21+
22+
namespace o2
23+
{
24+
namespace parameters
25+
{
26+
27+
class LHCIFData
28+
{
29+
public:
30+
LHCIFData() = default;
31+
~LHCIFData() = default;
32+
33+
std::pair<long, int32_t> getBeamEnergy() const { return mBeamEnergy; }
34+
std::pair<long, int32_t> getFillNumber() const { return mFillNumber; }
35+
std::pair<long, std::string> getInjectionScheme() const { return mInjectionScheme; }
36+
std::pair<long, int32_t> getAtomicNumberB1() const { return mAtomicNumberB1; }
37+
std::pair<long, int32_t> getAtomicNumberB2() const { return mAtomicNumberB2; }
38+
39+
int32_t getBeamEnergyVal() const { return mBeamEnergy.second; }
40+
int32_t getFillNumberVal() const { return mFillNumber.second; }
41+
std::string getInjectionSchemeVal() const { return mInjectionScheme.second; }
42+
int32_t getAtomicNumberB1Val() const { return mAtomicNumberB1.second; }
43+
int32_t getAtomicNumberB2Val() const { return mAtomicNumberB2.second; }
44+
45+
long getBeamEnergyTime() const { return mBeamEnergy.first; }
46+
long getFillNumberTime() const { return mFillNumber.first; }
47+
long getInjectionSchemeTime() const { return mInjectionScheme.first; }
48+
long getAtomicNumberB1Time() const { return mAtomicNumberB1.first; }
49+
long getAtomicNumberB2Time() const { return mAtomicNumberB2.first; }
50+
51+
void setBeamEnergy(std::pair<long, int32_t> p) { mBeamEnergy = p; }
52+
void setFillNumber(std::pair<long, int32_t> p) { mFillNumber = p; }
53+
void setInjectionScheme(std::pair<long, std::string> p) { mInjectionScheme = p; }
54+
void setAtomicNumberB1(std::pair<long, int32_t> p) { mAtomicNumberB1 = p; }
55+
void setAtomicNumberB2(std::pair<long, int32_t> p) { mAtomicNumberB2 = p; }
56+
57+
void setBeamEnergy(long t, int32_t v) { mBeamEnergy = std::make_pair(t, v); }
58+
void setFillNumber(long t, int32_t v) { mFillNumber = std::make_pair(t, v); }
59+
void setInjectionScheme(long t, std::string v) { mInjectionScheme = std::make_pair(t, v); }
60+
void setAtomicNumberB1(long t, int32_t v) { mAtomicNumberB1 = std::make_pair(t, v); }
61+
void setAtomicNumberB2(long t, int32_t v) { mAtomicNumberB2 = std::make_pair(t, v); }
62+
63+
private:
64+
std::pair<long, int32_t> mBeamEnergy;
65+
std::pair<long, int32_t> mFillNumber;
66+
std::pair<long, std::string> mInjectionScheme;
67+
std::pair<long, int32_t> mAtomicNumberB1;
68+
std::pair<long, int32_t> mAtomicNumberB2;
69+
70+
ClassDefNV(LHCIFData, 1);
71+
};
72+
} // namespace parameters
73+
} // namespace o2
74+
#endif
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2+
// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3+
// All rights not expressly granted are reserved.
4+
//
5+
// This software is distributed under the terms of the GNU General Public
6+
// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7+
//
8+
// In applying this license CERN does not waive the privileges and immunities
9+
// granted to it by virtue of its status as an Intergovernmental Organization
10+
// or submit itself to any jurisdiction.
11+
12+
/// \file LHCIFData.cxx
13+
/// \brief Implementation of the LHC InterFace data
14+
15+
#include "DataFormatsParameters/LHCIFData.h"

DataFormats/Parameters/src/ParametersDataLinkDef.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,7 @@
2424
#pragma link off all functions;
2525

2626
#pragma link C++ class o2::parameters::GRPObject + ;
27+
#pragma link C++ class o2::parameters::LHCIFData + ;
28+
#pragma link C++ class std::pair < long, std::string> + ;
2729

2830
#endif

Detectors/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,3 +55,5 @@ if(ENABLE_UPGRADES)
5555
else()
5656
message(STATUS "Not building detectors for upgrades")
5757
endif()
58+
59+
add_subdirectory(GRP)

Detectors/DCS/testWorkflow/src/dcs-config-proxy.cxx

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131
using namespace o2::framework;
3232
using DetID = o2::detectors::DetID;
3333

34+
std::array<o2::header::DataOrigin, 1> exceptionsDetID{"GRP"};
35+
3436
void sendAnswer(const std::string& what, const std::string& ack_chan, FairMQDevice& device)
3537
{
3638
if (!ack_chan.empty()) {
@@ -44,10 +46,21 @@ void sendAnswer(const std::string& what, const std::string& ack_chan, FairMQDevi
4446
}
4547
}
4648

47-
auto getDetID(const std::string& filename)
49+
auto getDataOriginFromFilename(const std::string& filename)
4850
{
4951
// assume the filename start with detector name
50-
return DetID::nameToID(filename.substr(0, 3).c_str(), DetID::First);
52+
auto dIDStr = filename.substr(0, 3);
53+
auto dID = DetID::nameToID(dIDStr.c_str(), DetID::First);
54+
o2::header::DataOrigin dataOrigin;
55+
if (dID < 0) {
56+
for (auto& el : exceptionsDetID) {
57+
if (el.as<std::string>() == dIDStr) {
58+
return el;
59+
}
60+
}
61+
return o2::header::gDataOriginInvalid;
62+
}
63+
return DetID(dID).getDataOrigin();
5164
}
5265

5366
InjectorFunction dcs2dpl(const std::string& acknowledge)
@@ -65,15 +78,15 @@ InjectorFunction dcs2dpl(const std::string& acknowledge)
6578
std::string filename{static_cast<const char*>(parts.At(0)->GetData()), parts.At(0)->GetSize()};
6679
size_t filesize = parts.At(1)->GetSize();
6780
LOG(INFO) << "received file " << filename << " of size " << filesize;
68-
int dID = getDetID(filename);
69-
if (dID < 0) {
81+
o2::header::DataOrigin dataOrigin = getDataOriginFromFilename(filename);
82+
if (dataOrigin == o2::header::gDataOriginInvalid) {
7083
LOG(ERROR) << "unknown detector for " << filename;
7184
sendAnswer("error1: unrecognized filename", acknowledge, device);
7285
return;
7386
}
7487

75-
o2::header::DataHeader hdrF("DCS_CONFIG_FILE", DetID(dID).getDataOrigin(), 0);
76-
o2::header::DataHeader hdrN("DCS_CONFIG_NAME", DetID(dID).getDataOrigin(), 0);
88+
o2::header::DataHeader hdrF("DCS_CONFIG_FILE", dataOrigin, 0);
89+
o2::header::DataHeader hdrN("DCS_CONFIG_NAME", dataOrigin, 0);
7790
OutputSpec outsp{hdrN.dataOrigin, hdrN.dataDescription, hdrN.subSpecification};
7891
auto channel = channelRetriever(outsp, *timesliceId);
7992
if (channel.empty()) {
@@ -84,14 +97,14 @@ InjectorFunction dcs2dpl(const std::string& acknowledge)
8497

8598
hdrN.tfCounter = *timesliceId; // this also
8699
hdrN.payloadSerializationMethod = o2::header::gSerializationMethodNone;
87-
hdrN.splitPayloadParts = 1;
88-
hdrN.splitPayloadIndex = 1;
100+
hdrN.splitPayloadParts = 2;
101+
hdrN.splitPayloadIndex = 0;
89102
hdrN.payloadSize = parts.At(0)->GetSize();
90103
hdrN.firstTForbit = 0; // this should be irrelevant for DCS
91104

92105
hdrF.tfCounter = *timesliceId; // this also
93106
hdrF.payloadSerializationMethod = o2::header::gSerializationMethodNone;
94-
hdrF.splitPayloadParts = 1;
107+
hdrF.splitPayloadParts = 2;
95108
hdrF.splitPayloadIndex = 1;
96109
hdrF.payloadSize = filesize;
97110
hdrF.firstTForbit = 0; // this should be irrelevant for DCS
@@ -164,6 +177,10 @@ WorkflowSpec defineDataProcessing(ConfigContext const& config)
164177
dcsOutputs.emplace_back(DetID(id).getDataOrigin(), "DCS_CONFIG_FILE", 0, Lifetime::Timeframe);
165178
dcsOutputs.emplace_back(DetID(id).getDataOrigin(), "DCS_CONFIG_NAME", 0, Lifetime::Timeframe);
166179
}
180+
for (auto& el : exceptionsDetID) {
181+
dcsOutputs.emplace_back(el, "DCS_CONFIG_FILE", 0, Lifetime::Timeframe);
182+
dcsOutputs.emplace_back(el, "DCS_CONFIG_NAME", 0, Lifetime::Timeframe);
183+
}
167184

168185
DataProcessorSpec dcsConfigProxy = specifyExternalFairMQDeviceProxy(
169186
devName.c_str(),

Detectors/GRP/CMakeLists.txt

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2+
# See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3+
# All rights not expressly granted are reserved.
4+
#
5+
# This software is distributed under the terms of the GNU General Public
6+
# License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7+
#
8+
# In applying this license CERN does not waive the privileges and immunities
9+
# granted to it by virtue of its status as an Intergovernmental Organization
10+
# or submit itself to any jurisdiction.
11+
12+
add_subdirectory(calibration)
13+
add_subdirectory(workflows)
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
# Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2+
# See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3+
# All rights not expressly granted are reserved.
4+
#
5+
# This software is distributed under the terms of the GNU General Public
6+
# License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7+
#
8+
# In applying this license CERN does not waive the privileges and immunities
9+
# granted to it by virtue of its status as an Intergovernmental Organization
10+
# or submit itself to any jurisdiction.
11+
12+
o2_add_library(GRPCalibration
13+
TARGETVARNAME targetName
14+
SOURCES src/LHCIFfileReader.cxx
15+
PUBLIC_LINK_LIBRARIES Microsoft.GSL::GSL
16+
O2::Framework)
17+
18+
o2_target_root_dictionary(GRPCalibration
19+
HEADERS include/GRPCalibration/LHCIFfileReader.h)
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2+
// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3+
// All rights not expressly granted are reserved.
4+
//
5+
// This software is distributed under the terms of the GNU General Public
6+
// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7+
//
8+
// In applying this license CERN does not waive the privileges and immunities
9+
// granted to it by virtue of its status as an Intergovernmental Organization
10+
// or submit itself to any jurisdiction.
11+
12+
#ifndef GRP_LHCIF_FILE_READER_H_
13+
#define GRP_LHCIF_FILE_READER_H_
14+
15+
#include "Rtypes.h"
16+
#include <gsl/span>
17+
#include "Framework/Logger.h"
18+
#include "CommonUtils/StringUtils.h"
19+
20+
/// @brief Class to read the LHC InterFace file coming from the DCS filepush service
21+
22+
namespace o2
23+
{
24+
namespace grp
25+
{
26+
class LHCIFfileReader
27+
{
28+
public:
29+
LHCIFfileReader() = default; // default constructor
30+
~LHCIFfileReader() = default; // default destructor
31+
32+
void loadLHCIFfile(const std::string& fileName); // load LHCIF file
33+
void loadLHCIFfile(gsl::span<const char> configBuf); // load LHCIF file from buffer
34+
template <typename T>
35+
void readValue(const std::string& alias, std::string& type, int& nel, int& nmeas, std::vector<std::pair<long, std::vector<T>>>& meas);
36+
37+
private:
38+
std::string mFileBuffStr; // buffer containing content of LHC IF file
39+
40+
ClassDefNV(LHCIFfileReader, 1);
41+
};
42+
43+
template <typename T>
44+
void LHCIFfileReader::readValue(const std::string& alias, std::string& type, int& nele, int& nmeas, std::vector<std::pair<long, std::vector<T>>>& meas)
45+
{
46+
// look for value 'value' in the string from the LHC
47+
48+
auto posStart = mFileBuffStr.find(alias);
49+
if (posStart == std::string::npos) {
50+
LOG(INFO) << alias << " not found in LHC IF file";
51+
return;
52+
}
53+
auto posEnd = mFileBuffStr.find("\n", posStart);
54+
LOG(DEBUG) << "posStart = " << posStart << ", posEnd = " << posEnd;
55+
if (posEnd == std::string::npos) {
56+
posEnd = mFileBuffStr.size();
57+
}
58+
std::string subStr = mFileBuffStr.substr(posStart, posEnd - posStart);
59+
LOG(DEBUG) << "subStr = " << subStr;
60+
auto tokensStr = o2::utils::Str::tokenize(subStr, '\t');
61+
LOG(DEBUG) << "size of tokensStr = " << tokensStr.size();
62+
if (tokensStr.size() < 5) {
63+
LOG(FATAL) << "Number of tokens too small: " << tokensStr.size() << ", should be at 5 (alias, type, nelements, value(s), timestamp(s)";
64+
}
65+
auto tokensStr_type = o2::utils::Str::tokenize(tokensStr[1], ':');
66+
LOG(DEBUG) << "size of tokensStr_type = " << tokensStr_type.size();
67+
68+
type = tokensStr_type[0];
69+
LOG(DEBUG) << "type = " << type;
70+
71+
nele = std::stoi(tokensStr_type[1]); // number of elements per measurement
72+
nmeas = std::stoi(tokensStr[2]); // number of measurements
73+
LOG(DEBUG) << "nele = " << nele << ", nmeas = " << nmeas;
74+
int shift = 3; // number of tokens that are not measurments (alias, type, number of measurements)
75+
if ((tokensStr.size() - shift) != (nele + 1) * nmeas) { // +1 to account for the timestamp
76+
LOG(FATAL) << "Wrong number of pairs (value(s), timestamp): " << tokensStr.size() - 3 << ", should be " << (nele + 1) * nmeas;
77+
}
78+
meas.reserve(nmeas);
79+
80+
for (int idx = 0; idx < nmeas; ++idx) {
81+
std::vector<T> vect;
82+
vect.reserve(nele);
83+
if constexpr (std::is_same<T, int32_t>::value) {
84+
if (type == "i" || type == "b") {
85+
for (int iele = 0; iele < nele; ++iele) {
86+
LOG(INFO) << alias << ": value int/bool = " << tokensStr[shift + iele];
87+
vect.emplace_back(std::stoi(tokensStr[shift + iele]));
88+
}
89+
} else {
90+
LOG(FATAL) << "templated function called with wrong type, should be int32_t or bool, but it is " << type;
91+
}
92+
} else if constexpr (std::is_same<T, float>::value) {
93+
if (type == "f") {
94+
for (int iele = 0; iele < nele; ++iele) {
95+
LOG(INFO) << alias << ": value float = " << tokensStr[shift + iele];
96+
vect.emplace_back(std::stof(tokensStr[shift + iele]));
97+
}
98+
} else {
99+
LOG(FATAL) << "templated function called with wrong type, should be float";
100+
}
101+
}
102+
103+
else if constexpr (std::is_same<T, std::string>::value) {
104+
if (type == "s") {
105+
for (int iele = 0; iele < nele; ++iele) {
106+
LOG(INFO) << alias << ": value string = " << tokensStr[shift + iele];
107+
vect.emplace_back(tokensStr[shift + iele]);
108+
}
109+
} else {
110+
LOG(FATAL) << "templated function called with wrong type, should be string";
111+
}
112+
}
113+
114+
LOG(DEBUG) << "timestamp = " << std::stof(tokensStr[shift + nele]);
115+
meas.emplace_back(std::stol(tokensStr[shift + nele]) * 1e6, vect); // measurement comes in seconds, we want it in microseconds
116+
}
117+
}
118+
119+
} // namespace grp
120+
} // namespace o2
121+
#endif
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2+
// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3+
// All rights not expressly granted are reserved.
4+
//
5+
// This software is distributed under the terms of the GNU General Public
6+
// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7+
//
8+
// In applying this license CERN does not waive the privileges and immunities
9+
// granted to it by virtue of its status as an Intergovernmental Organization
10+
// or submit itself to any jurisdiction.
11+
12+
#ifdef __CLING__
13+
14+
#pragma link off all globals;
15+
#pragma link off all classes;
16+
#pragma link off all functions;
17+
18+
#pragma link C++ class o2::grp::LHCIFfileReader + ;
19+
20+
#endif

0 commit comments

Comments
 (0)