ATLAS Offline Software
Json2Cool.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3 */
4 
5 #include "Json2Cool.h"
6 
7 #include "IOVDbStringFunctions.h"
8 #include "CoolKernel/RecordSpecification.h"
9 #include "CoolKernel/Record.h"
10 #include "CoralBase/AttributeList.h"
11 #include "CoralBase/Attribute.h"
13 #include "boost/regex.hpp"
14 #include "Base64Codec.h"
15 #include <stdexcept>
16 #include <iostream>
17 
19 using namespace cool;
20 using namespace IOVDbNamespace;
21 
22 
23 namespace {
24 
25 
26 const std::map<std::string, cool::StorageType::TypeId> typeCorrespondance={
27  //http://cool-doxygen.web.cern.ch/COOL-doxygen/classcool_1_1_storage_type.html
28  {"Bool", StorageType::Bool},
29  {"UChar",StorageType::UChar},
30  {"Int16", StorageType::Int16},
31  {"UInt16", StorageType::UInt16},
32  {"Int32", StorageType::Int32},
33  {"UInt32", StorageType::UInt32},
34  {"UInt63",StorageType::UInt63},
35  {"Int64", StorageType::Int64},
36  {"Float", StorageType::Float},
37  {"Double", StorageType::Double},
38  {"String255", StorageType::String255},
39  {"String4k", StorageType::String4k},
40  {"String64k", StorageType::String64k},
41  {"String16M", StorageType::String16M},
42  {"String128M", StorageType::String128M},
43  {"Blob64k", StorageType::Blob64k},
44  {"Blob16M", StorageType::Blob16M},
45  {"Blob128M", StorageType::Blob128M}
46  };
47 
48 
49 } // anonymous namespace
50 
51 
52 namespace IOVDbNamespace{
53 
54 
55  Json2Cool::Json2Cool(std::istream & stream, BasicFolder & b, const std::string & specString, const IovStore::Iov_t* iov):m_basicFolder(b){
56  init(stream, specString, iov);
57  }
58 
59  void
60  Json2Cool::init(std::istream & s, const std::string & specString, const IovStore::Iov_t* iov){
61  if (not s.good() or s.eof()){
62  const std::string msg("Json2Cool constructor; Input is invalid and could not be opened.");
63  throw std::runtime_error(msg);
64  } else {
65  json j;
66  try{
67  s>>j; //read into json
68  }catch (const std::exception& e) {
69  std::cout<<"ERROR AT LINE "<<__LINE__<<" of "<<__FILE__<<std::endl;
70  std::cout<<e.what()<<std::endl; //typically a parsing error
71  }
72  m_sharedSpec = parsePayloadSpec(specString);
73  const auto & payload=j["data"];//payload is an object in any case, of form {"0":["datastring"]}
74  //keep these lines for reference: iov handling is not yet implemented, but should be
75  //const auto & iovFromFile=j["iov"];//iov is a two-element array
76  //const std::pair<cool::ValidityKey, cool::ValidityKey> iov(iovFromFile[0], iovFromFile[1]);
77  if(iov) {
79  }
80  else {
81  m_basicFolder.setIov(IovStore::Iov_t(0, cool::ValidityKeyMax));
82  }
84  for (json::const_iterator k=payload.begin();k!=payload.end();++k){ //k are {"0":}
85  const json& f=k.value(); //channel id
86  const std::string& ks=k.key();
87  const long long key=std::stoll(ks);
88  std::vector<coral::AttributeList> tempVector;//can optimise this by pre constructing it and using 'clear'
89  for (json::const_iterator i=f.begin();i!=f.end();++i){
90  const json& arrayElem=i.value();
91  auto r=createAttributeList(m_sharedSpec,arrayElem);
92  const auto & attList=r.attributeList();
93  tempVector.push_back(attList);
94  }
95  m_basicFolder.addChannelPayload(key, tempVector);
96  //add payload with channelId here
97  }
98  } else {
99  for (json::const_iterator i=payload.begin();i!=payload.end();++i){
100  const json& f=i.value();
101  const std::string& ks=i.key();
102  const long long key=std::stoll(ks);
104  const auto & attList=r.attributeList();
106  }
107  }
108  }
109  }
110 
111  //parsing something like
112  // "folder_payloadspec": "crate: UChar, slot: UChar, ROB: Int32, SRCid: Int32, BCIDOffset: Int16, slave0: Int32, slave1: Int32, slave2: Int32, slave3: Int32"
113  cool::RecordSpecification *
114  Json2Cool::parsePayloadSpec(const std::string & stringSpecification){
115  if (stringSpecification.empty()) return nullptr;
116  auto *spec = new cool::RecordSpecification();
117 
118  std::string inputObj=stringSpecification;
119  nlohmann::json nl=nlohmann::json::parse(stringSpecification);
120  if(nl.is_array()){
121  for (unsigned int i = 0; i < nl.size(); i++)
122  {
123  if(nl[i].size()>0){
124  auto it = nl[i].items().begin();
125  std::string n((*it).key());
126  std::string t((*it).value());
127  spec->extend(n, typeCorrespondance.find(t)->second);
128  }
129  }
130  return spec;
131  }
132 
133  std::string input(stringSpecification);
134 
135  std::string regex=R"delim(([^\s,:]*):\s?([^\s,]*),?)delim";
137  boost::smatch what;
138 
139  bool match=boost::regex_search(input, what, expression);
140  while (match){
141  std::string n(what[1]);
142  std::string t(what[2]);
143  //todo: need to catch error if type not found, also
144  spec->extend(n, typeCorrespondance.find(t)->second);
145  input = what.suffix();
146  match=boost::regex_search(input, what, expression);
147 
148  }
149  return spec;
150  }
151 
152  cool::Record
153  Json2Cool::createAttributeList(cool::RecordSpecification * pSpec, const nlohmann::json & j){
154  cool::Record a(*pSpec);
155  unsigned int s=a.size();
156 
157  json::const_iterator it = j.begin();
158  for (unsigned int i(0);i!=s;++i){
159  auto & f=a[i];
160  if (it == j.end()){
161  continue;
162  }
163  const auto thisVal = it.value();
164  ++it;
165 
166  try{
167  // cool::Record does not provide non-const access to AttributeList.
168  // But this is safe because we are filling a local instance.
169  auto & att ATLAS_THREAD_SAFE = const_cast<coral::Attribute&>(a.attributeList()[i]);
170  if (thisVal.is_null()){
171  att.setNull();
172  continue;
173  }
174  cool::StorageType::TypeId typespec = f.storageType().id();
175  std::string strVal = to_string(thisVal);
176  if(strVal.size()>2&& strVal[0]=='"'&& strVal[strVal.size()-1]=='"')
177  strVal=strVal.substr(1,strVal.size()-2);
178 
179  if((strVal.compare("NULL")==0||strVal.compare("null")==0)&&
180  (typespec==StorageType::Bool || typespec==StorageType::Int16 || typespec==StorageType::UInt16
181  || typespec==StorageType::Int32 || typespec==StorageType::UInt32
182  || typespec==StorageType::Int64 || typespec==StorageType::UInt63
183  || typespec==StorageType::Float || typespec==StorageType::Double)){
184  att.setNull();
185  continue;
186  }
187  switch (typespec) {
188  case StorageType::Bool:
189  {
190  const bool newVal=(strVal == "true");
191  att.setValue<bool>(newVal);
192  break;
193  }
194  case StorageType::UChar:
195  {
196  const unsigned char newVal=std::stoul(strVal);
197  att.setValue<unsigned char>(newVal);
198  break;
199  }
200  case StorageType::Int16:
201  {
202  const short newVal=std::stol(strVal);
203  att.setValue<short>(newVal);
204  break;
205  }
206  case StorageType::UInt16:
207  {
208  const unsigned short newVal=std::stoul(strVal);
209  att.setValue<unsigned short>(newVal);
210  break;
211  }
212  case StorageType::Int32:
213  {
214  const int newVal=std::stoi(strVal);
215  att.setValue<int>(newVal);
216  break;
217  }
218  case StorageType::UInt32:
219  {
220  const unsigned int newVal=std::stoull(strVal);
221  att.setValue<unsigned int>(newVal);
222  break;
223  }
224  case StorageType::UInt63:
225  {
226  const unsigned long long newVal=std::stoull(strVal);
227  att.setValue<unsigned long long>(newVal);
228  break;
229  }
230  case StorageType::Int64:
231  {
232  const long long newVal=std::stoll(strVal);
233  att.setValue< long long>(newVal);
234  break;
235  }
236  case StorageType::Float:
237  {
238  const float newVal=std::stof(strVal);
239  att.setValue<float>(newVal);
240  break;
241  }
242  case StorageType::Double:
243  {
244  const double newVal=std::stod(strVal);
245  att.setValue<double>(newVal);
246  break;
247  }
248  case StorageType::String255:
249  case StorageType::String4k:
250  case StorageType::String64k:
251  case StorageType::String16M:
252  case StorageType::String128M:
253  {
254  att.setValue<std::string>(thisVal.get<std::string>());
255  break;
256  }
257  case StorageType::Blob128M:
258  case StorageType::Blob16M:
259  case StorageType::Blob64k:
260  {
261  auto blob = base64Decode(strVal);
262  att.setValue<coral::Blob>(blob);
263  break;
264  }
265  default:
266  {
267  std::string typeName{};
268  for (auto& [key,val] : typeCorrespondance) {
269  if(val==typespec) {
270  typeName = key;
271  break;
272  }
273  }
274  if(typeName.empty()) {
275  typeName = "Unexpected Type";
276  }
277  std::string errorMessage("UNTREATED TYPE! " + typeName);
278  std::cerr << errorMessage << std::endl;
279  throw std::runtime_error(errorMessage);
280  break;
281  }
282  }
283  }
284  catch (json::exception& e){
285  std::cerr << e.what() << std::endl;
286  throw std::runtime_error(e.what());
287  }
288  }
289  return a;
290  }
291 }//end of namespace
292 
IOVDbNamespace::BasicFolder::isVectorPayload
bool isVectorPayload() const
Definition: BasicFolder.cxx:41
AllowedVariables::e
e
Definition: AsgElectronSelectorTool.cxx:37
beamspotman.r
def r
Definition: beamspotman.py:676
python.SystemOfUnits.s
int s
Definition: SystemOfUnits.py:131
Json2Cool.h
dqt_zlumi_alleff_HIST.iov
iov
Definition: dqt_zlumi_alleff_HIST.py:119
json
nlohmann::json json
Definition: HistogramDef.cxx:9
CaloCondBlobAlgs_fillNoiseFromASCII.spec
spec
Definition: CaloCondBlobAlgs_fillNoiseFromASCII.py:47
IOVDbNamespace::Json2Cool::m_basicFolder
BasicFolder & m_basicFolder
Definition: Json2Cool.h:43
parse
std::map< std::string, std::string > parse(const std::string &list)
Definition: egammaLayerRecalibTool.cxx:1054
skel.it
it
Definition: skel.GENtoEVGEN.py:396
python.subdetectors.tile.Blob
Blob
Definition: tile.py:17
IOVDbNamespace::base64Decode
coral::Blob base64Decode(const std::string &base64String)
Definition: Base64Codec.cxx:26
python.HION12.expression
string expression
Definition: HION12.py:56
read_hist_ntuple.t
t
Definition: read_hist_ntuple.py:5
IOVDbNamespace::IovStore::Iov_t
std::pair< cool::ValidityKey, cool::ValidityKey > Iov_t
Definition: IovStore.h:22
AthenaPoolTestWrite.stream
string stream
Definition: AthenaPoolTestWrite.py:12
cool
Definition: CoolTagInfo.h:12
PrepareReferenceFile.regex
regex
Definition: PrepareReferenceFile.py:43
python.setupRTTAlg.size
int size
Definition: setupRTTAlg.py:39
IOVDbStringFunctions.h
lumiFormat.i
int i
Definition: lumiFormat.py:85
beamspotman.n
n
Definition: beamspotman.py:731
PlotPulseshapeFromCool.input
input
Definition: PlotPulseshapeFromCool.py:106
calibdata.exception
exception
Definition: calibdata.py:496
hist_file_dump.f
f
Definition: hist_file_dump.py:135
IOVDbNamespace::Json2Cool::parsePayloadSpec
static cool::RecordSpecification * parsePayloadSpec(const std::string &stringSpecification)
Definition: Json2Cool.cxx:114
python.ExitCodes.what
def what(code)
Definition: ExitCodes.py:73
IOVDbNamespace::BasicFolder
Definition: BasicFolder.h:21
Base64Codec.h
ActsTrk::to_string
std::string to_string(const DetectorType &type)
Definition: GeometryDefs.h:34
plotBeamSpotMon.b
b
Definition: plotBeamSpotMon.py:77
IOVDbNamespace::Json2Cool::m_sharedSpec
cool::RecordSpecification * m_sharedSpec
Definition: Json2Cool.h:42
PixelModuleFeMask_create_db.payload
string payload
Definition: PixelModuleFeMask_create_db.py:69
IOVDbNamespace::BasicFolder::addChannelPayload
void addChannelPayload(const cool::ChannelId &channelId, const std::string &name, const coral::AttributeList &payload)
Definition: BasicFolder.cxx:52
a
TList * a
Definition: liststreamerinfos.cxx:10
Pythia8_RapidityOrderMPI.val
val
Definition: Pythia8_RapidityOrderMPI.py:14
ReadCalibFromCool.typeName
typeName
Definition: ReadCalibFromCool.py:477
json
nlohmann::json json
Definition: Json2Cool.cxx:18
ATLAS_THREAD_SAFE
#define ATLAS_THREAD_SAFE
Definition: checker_macros.h:211
IOVDbNamespace::Json2Cool::createAttributeList
static cool::Record createAttributeList(cool::RecordSpecification *pSpec, const nlohmann::json &j)
Definition: Json2Cool.cxx:153
IOVDbNamespace::Json2Cool::init
void init(std::istream &stream, const std::string &specString, const IovStore::Iov_t *iov)
Definition: Json2Cool.cxx:60
checker_macros.h
Define macros for attributes used to control the static checker.
Crest::TypeId
TypeId
Definition: CrestContainer.h:24
IOVDbNamespace::BasicFolder::setIov
void setIov(const std::pair< cool::ValidityKey, cool::ValidityKey > &iov)
Definition: BasicFolder.cxx:46
python.AutoConfigFlags.msg
msg
Definition: AutoConfigFlags.py:7
CaloCondBlobAlgs_fillNoiseFromASCII.blob
blob
Definition: CaloCondBlobAlgs_fillNoiseFromASCII.py:96
match
bool match(std::string s1, std::string s2)
match the individual directories of two strings
Definition: hcg.cxx:356
fitman.k
k
Definition: fitman.py:528
IOVDbNamespace
Definition: Base64Codec.cxx:16
mapkey::key
key
Definition: TElectronEfficiencyCorrectionTool.cxx:37