ATLAS Offline Software
parse_json.cxx
Go to the documentation of this file.
1 /*
2  Copyright (C) 2002-2021 CERN for the benefit of the ATLAS collaboration
3 */
4 
6 
7 #define BOOST_BIND_GLOBAL_PLACEHOLDERS // Needed to silence Boost pragma message
8 #include <boost/property_tree/ptree.hpp>
9 #include <boost/property_tree/json_parser.hpp>
10 #include <cassert>
11 #include <string>
12 #include <cmath> // for NAN
13 #include <set>
14 
15 #include<iostream>
16 
17 namespace {
18  using namespace boost::property_tree;
19  using namespace lwtDev;
20  LayerConfig get_layer(const ptree::value_type& pt);
21  Input get_input(const ptree::value_type& pt);
22  InputNodeConfig get_input_node(const ptree::value_type& pt);
23  NodeConfig get_node(const ptree::value_type& pt);
24  OutputNodeConfig get_output_node(const ptree::value_type& v);
25  NodeConfig::Type get_node_type(const std::string&);
27  Activation get_activation_function(const std::string&);
28  Architecture get_architecture(const std::string&);
29  void set_defaults(LayerConfig& lc);
30  void add_dense_info(LayerConfig& lc, const ptree::value_type& pt);
31  void add_maxout_info(LayerConfig& lc, const ptree::value_type& pt);
32  void add_component_info(LayerConfig& lc, const ptree::value_type& pt);
33  void add_bidirectional_info(LayerConfig& lc, const ptree::value_type& pt);
34  void add_embedding_info(LayerConfig& lc, const ptree::value_type& pt);
35 
36  std::map<std::string, double> get_defaults(const ptree& ptree);
37 }
38 
39 
40 namespace lwtDev {
41 
42  JSONConfig parse_json(std::istream& json)
43  {
45  boost::property_tree::read_json(json, pt);
46 
48  for (const auto& v: pt.get_child("inputs")) {
49  cfg.inputs.push_back(get_input(v));
50  }
51  for (const auto& v: pt.get_child("layers")) {
52  cfg.layers.push_back(get_layer(v));
53  }
54  for (const auto& v: pt.get_child("outputs"))
55  {
56  assert(v.first.empty()); // array elements have no names
57  cfg.outputs.push_back(v.second.data());
58  }
59  cfg.defaults = get_defaults(pt);
60  const std::string mname = "miscellaneous";
61  if (pt.count(mname)) {
62  for (const auto& misc: pt.get_child(mname)) {
63  cfg.miscellaneous.emplace(
64  misc.first, misc.second.get_value<std::string>());
65  }
66  }
67  return cfg;
68  }
69 
70 
73  boost::property_tree::read_json(json, pt);
74 
76  for (const auto& v: pt.get_child("inputs")) {
77  cfg.inputs.push_back(get_input_node(v));
78  }
79  for (const auto& v: pt.get_child("input_sequences")) {
80  cfg.input_sequences.push_back(get_input_node(v));
81  }
82  for (const auto& v: pt.get_child("nodes")) {
83  cfg.nodes.push_back(get_node(v));
84  }
85  for (const auto& v: pt.get_child("layers")) {
86  cfg.layers.push_back(get_layer(v));
87  }
88  for (const auto& v: pt.get_child("outputs")) {
89  cfg.outputs.emplace(v.first, get_output_node(v));
90  }
91  return cfg;
92  }
93 
94 }
95 
96 namespace {
97 
98  lwtDev::Input get_input(const ptree::value_type& v) {
99  std::string name = v.second.get<std::string>("name");
100  auto offset = v.second.get<double>("offset");
101  auto scale = v.second.get<double>("scale");
102  return {name, offset, scale};
103  }
104 
105  lwtDev::InputNodeConfig get_input_node(const ptree::value_type& v) {
107  cfg.name = v.second.get<std::string>("name");
108  for (const auto& var: v.second.get_child("variables")) {
109  cfg.variables.push_back(get_input(var));
110  if (var.second.count("default")) {
111  std::string name = var.second.get<std::string>("name");
112  cfg.defaults.emplace(name, var.second.get<double>("default"));
113  }
114  }
115  return cfg;
116  }
117 
118  const std::set<NodeConfig::Type> layerless_nodes {
119  NodeConfig::Type::CONCATENATE, NodeConfig::Type::SUM };
120  NodeConfig get_node(const ptree::value_type& v) {
121  NodeConfig cfg;
122 
123  for (const auto& source: v.second.get_child("sources")) {
124  int source_number = source.second.get_value<int>();
125  if (source_number < 0) {
126  throw std::logic_error("node source number must be positive");
127  }
128  cfg.sources.push_back(source_number);
129  }
130 
131  cfg.type = get_node_type(v.second.get<std::string>("type"));
132  typedef NodeConfig::Type Type;
133  if (cfg.type == Type::INPUT || cfg.type == Type::INPUT_SEQUENCE) {
134  cfg.index = v.second.get<int>("size");
135  } else if (cfg.type == Type::FEED_FORWARD || cfg.type == Type::SEQUENCE ||
136  cfg.type == Type::TIME_DISTRIBUTED) {
137  cfg.index = v.second.get<int>("layer_index");
138  } else if (layerless_nodes.count(cfg.type)){
139  cfg.index = -1;
140  } else {
141  throw std::logic_error("unknown node type");
142  }
143  return cfg;
144  }
145 
146  OutputNodeConfig get_output_node(const ptree::value_type& v) {
148  for (const auto& lab: v.second.get_child("labels")) {
149  cfg.labels.push_back(lab.second.get_value<std::string>());
150  }
151  int idx = v.second.get<int>("node_index");
152  if (idx < 0) throw std::logic_error("output node index is negative");
153  cfg.node_index = idx;
154  return cfg;
155  }
156 
157  NodeConfig::Type get_node_type(const std::string& type) {
158  typedef NodeConfig::Type Type;
159  if (type == "feed_forward") return Type::FEED_FORWARD;
160  if (type == "sequence") return Type::SEQUENCE;
161  if (type == "input") return Type::INPUT;
162  if (type == "input_sequence") return Type::INPUT_SEQUENCE;
163  if (type == "concatenate") return Type::CONCATENATE;
164  if (type == "time_distributed") return Type::TIME_DISTRIBUTED;
165  if (type == "sum") return Type::SUM;
166  throw std::logic_error("no node type '" + type + "'");
167  }
168 
169  LayerConfig get_layer(const ptree::value_type& v) {
170  using namespace lwtDev;
172  set_defaults(layer);
173  Architecture arch = get_architecture(
174  v.second.get<std::string>("architecture"));
175 
176  if (arch == Architecture::DENSE) {
177  add_dense_info(layer, v);
178  } else if (arch == Architecture::NORMALIZATION) {
179  add_dense_info(layer, v); // re-use dense layer
180  } else if (arch == Architecture::MAXOUT) {
181  add_maxout_info(layer, v);
182  } else if (arch == Architecture::LSTM ||
183  arch == Architecture::GRU ||
184  arch == Architecture::HIGHWAY) {
185  add_component_info(layer, v);
186  } else if (arch == Architecture::BIDIRECTIONAL) {
187  add_bidirectional_info(layer, v);
188  } else if (arch == Architecture::EMBEDDING) {
189  add_embedding_info(layer, v);
190  } else {
191  throw std::logic_error("architecture not implemented");
192  }
193  layer.architecture = arch;
194  return layer;
195  }
196 
198  // check if this is an "advanced" activation function, in which
199  // case it should store the values slightly differently
201  if (v.size() > 0) {
202  cfg.function = get_activation_function(
203  v.get<std::string>("function"));
204  cfg.alpha = v.get<double>("alpha");
205  } else {
206  cfg.function = get_activation_function(v.data());
207  cfg.alpha = NAN;
208  // special case: kerasfunc2json converter used to pass through
209  // the elu activation function. For cases where this has been
210  // saved in JSON files we assume an alpha parameter of 1.
211  if (cfg.function == Activation::ELU) {
212  cfg.alpha = 1.0;
213  }
214  }
215  return cfg;
216  }
217 
218  lwtDev::Activation get_activation_function(const std::string& str) {
219  using namespace lwtDev;
220  if (str == "linear") return Activation::LINEAR;
221  if (str == "sigmoid") return Activation::SIGMOID;
222  if (str == "rectified") return Activation::RECTIFIED;
223  if (str == "softmax") return Activation::SOFTMAX;
224  if (str == "tanh") return Activation::TANH;
225  if (str == "hard_sigmoid") return Activation::HARD_SIGMOID;
226  if (str == "elu") return Activation::ELU;
227  if (str == "leakyrelu") return Activation::LEAKY_RELU;
228  if (str == "swish") return Activation::SWISH;
229  if (str == "abs") return Activation::ABS;
230  throw std::logic_error("activation function " + str + " not recognized");
231  return Activation::LINEAR;
232  }
233 
234 
235  lwtDev::Architecture get_architecture(const std::string& str) {
236  using namespace lwtDev;
237  if (str == "dense") return Architecture::DENSE;
238  if (str == "normalization") return Architecture::NORMALIZATION;
239  if (str == "highway") return Architecture::HIGHWAY;
240  if (str == "maxout") return Architecture::MAXOUT;
241  if (str == "lstm") return Architecture::LSTM;
242  if (str == "gru") return Architecture::GRU;
243  if (str == "bidirectional") return Architecture::BIDIRECTIONAL;
244  if (str == "embedding") return Architecture::EMBEDDING;
245  throw std::logic_error("architecture " + str + " not recognized");
246  }
247 
248  void set_defaults(LayerConfig& layer) {
249  layer.activation.function = Activation::NONE;
250  layer.inner_activation.function = Activation::NONE;
251  layer.architecture = Architecture::NONE;
252  }
253 
254  void add_dense_info(LayerConfig& layer, const ptree::value_type& v) {
255  for (const auto& wt: v.second.get_child("weights")) {
256  layer.weights.push_back(wt.second.get_value<double>());
257  }
258  for (const auto& bs: v.second.get_child("bias")) {
259  layer.bias.push_back(bs.second.get_value<double>());
260  }
261  // this last category is currently only used for LSTM
262  if (v.second.count("U") != 0) {
263  for (const auto& wt: v.second.get_child("U") ) {
264  layer.U.push_back(wt.second.get_value<double>());
265  }
266  }
267 
268  if (v.second.count("activation") != 0) {
269  layer.activation = get_activation(v.second.get_child("activation"));
270  }
271 
272  }
273 
274  void add_maxout_info(LayerConfig& layer, const ptree::value_type& v) {
275  using namespace lwtDev;
276  for (const auto& sub: v.second.get_child("sublayers")) {
277  LayerConfig sublayer;
278  set_defaults(sublayer);
279  add_dense_info(sublayer, sub);
280  layer.sublayers.push_back(sublayer);
281  }
282  }
283 
284 
285  const std::map<std::string, lwtDev::Component> component_map {
286  {"i", Component::I},
287  {"o", Component::O},
288  {"c", Component::C},
289  {"f", Component::F},
290  {"z", Component::Z},
291  {"r", Component::R},
292  {"h", Component::H},
293  {"t", Component::T},
294  {"carry", Component::CARRY}
295  };
296 
297  void add_component_info(LayerConfig& layer, const ptree::value_type& v) {
298  using namespace lwtDev;
299  for (const auto& comp: v.second.get_child("components")) {
301  set_defaults(cfg);
302  add_dense_info(cfg, comp);
303  layer.components[component_map.at(comp.first)] = cfg;
304  }
305  layer.activation = get_activation(v.second.get_child("activation"));
306  layer.go_backwards = false;
307  if (v.second.count("return_sequence") != 0)
308  layer.return_sequence = v.second.get<bool>("return_sequence");
309  if (v.second.count("go_backwards") != 0)
310  layer.go_backwards = v.second.get<bool>("go_backwards");
311  if (v.second.count("inner_activation") != 0) {
312  layer.inner_activation = get_activation(
313  v.second.get_child("inner_activation"));
314  }
315  }
316 
317  void add_bidirectional_info(LayerConfig& layer, const ptree::value_type& v) {
318  using namespace lwtDev;
319  set_defaults(layer);
320  LayerConfig forward_layer;
321  LayerConfig backward_layer;
322  for(auto val: v.second){
323  if(val.first == "forward_layer"){
324  add_component_info(forward_layer, val);
325  forward_layer.architecture = get_architecture(val.second.get<std::string>("architecture"));
326  }
327  if(val.first == "backward_layer"){
328  add_component_info(backward_layer, val);
329  backward_layer.architecture = get_architecture(val.second.get<std::string>("architecture"));
330  }
331  }
332  layer.sublayers.push_back(forward_layer);
333  layer.sublayers.push_back(backward_layer);
334  layer.return_sequence = v.second.get<bool>("return_sequence");
335  layer.merge_mode = v.second.get<std::string>("merge_mode");
336  layer.architecture = Architecture::BIDIRECTIONAL;
337  }
338 
339  void add_embedding_info(LayerConfig& layer, const ptree::value_type& v) {
340  using namespace lwtDev;
341  for (const auto& sub: v.second.get_child("sublayers")) {
342  EmbeddingConfig emb;
343  for (const auto& wt: sub.second.get_child("weights")) {
344  emb.weights.push_back(wt.second.get_value<double>());
345  }
346  emb.index = sub.second.get<int>("index");
347  emb.n_out = sub.second.get<int>("n_out");
348  layer.embedding.push_back(emb);
349  }
350  }
351 
352  std::map<std::string, double> get_defaults(const ptree& pt) {
353  const std::string dname = "defaults";
354  std::map<std::string, double> defaults;
355  // NOTE: at some point we may deprecate this first way of storing
356  // default values.
357  if (pt.count(dname)) {
358  for (const auto& def: pt.get_child(dname)) {
359  defaults.emplace(def.first, def.second.get_value <double>());
360  }
361  } else {
362  const std::string dkey = "default";
363  for (const auto& v: pt.get_child("inputs")) {
364  if (v.second.count(dkey)) {
365  std::string key = v.second.get<std::string>("name");
366  defaults.emplace(key, v.second.get<double>(dkey));
367  }
368  }
369  }
370  return defaults;
371  }
372 }
NONE
@ NONE
Definition: sTGCenumeration.h:13
lwtDev::InputNodeConfig
Definition: lightweight_network_config.h:46
plotting.yearwise_luminosity_vs_mu.comp
comp
Definition: yearwise_luminosity_vs_mu.py:23
beamspotnt.var
var
Definition: bin/beamspotnt.py:1394
lwtDev::Architecture
Architecture
Definition: NNLayerConfig.h:22
json
nlohmann::json json
Definition: HistogramDef.cxx:9
Monitored::Z
@ Z
Definition: HistogramFillerUtils.h:24
DMTest::C
C_v1 C
Definition: C.h:26
test_pyathena.pt
pt
Definition: test_pyathena.py:11
python.TrigValSteering.Input.get_input
def get_input(keyword)
Definition: Input.py:96
python.LumiCalcHtml.lc
lc
Definition: LumiCalcHtml.py:579
yodamerge_tmp.scale
scale
Definition: yodamerge_tmp.py:138
lwtDev::LayerConfig::architecture
Architecture architecture
Definition: NNLayerConfig.h:64
lwtDev::parse_json
JSONConfig parse_json(std::istream &json)
Definition: parse_json.cxx:42
lwtDev::Input
Definition: lightweight_network_config.h:25
lwtDev::LayerConfig
Definition: NNLayerConfig.h:46
Type
RootType Type
Definition: TrigTSerializer.h:30
H
#define H(x, y, z)
Definition: MD5.cxx:114
lwtDev::EmbeddingConfig
Definition: NNLayerConfig.h:32
lwtDev::EmbeddingConfig::n_out
int n_out
Definition: NNLayerConfig.h:35
TRT::Hit::layer
@ layer
Definition: HitInfo.h:79
AnalysisUtils::Delta::R
double R(const INavigable4Momentum *p1, const double v_eta, const double v_phi)
Definition: AnalysisMisc.h:49
parse_json.h
lwtDev
Definition: Reconstruction/tauRecTools/Root/lwtnn/Exceptions.cxx:8
ptree
boost::property_tree::ptree ptree
Definition: JsonFileLoader.cxx:16
name
std::string name
Definition: Control/AthContainers/Root/debug.cxx:228
internal_poltrig::INPUT
@ INPUT
Definition: PolygonTriangulator.cxx:112
WriteCaloSwCorrections.cfg
cfg
Definition: WriteCaloSwCorrections.py:23
Base_Fragment.defaults
dictionary defaults
This includes now the top quark, the leptons and the bosons.
Definition: GeneratorFilters/share/common/Base_Fragment.py:79
lwtDev::ActivationConfig
Definition: NNLayerConfig.h:39
python.PyAthena.v
v
Definition: PyAthena.py:154
lwtDev::parse_json_graph
GraphConfig parse_json_graph(std::istream &json)
Definition: parse_json.cxx:71
lwtDev::get_activation
std::function< double(double)> get_activation(lwtDev::ActivationConfig act)
Definition: Stack.cxx:671
Pythia8_RapidityOrderMPI.val
val
Definition: Pythia8_RapidityOrderMPI.py:14
python.CaloScaleNoiseConfig.type
type
Definition: CaloScaleNoiseConfig.py:78
F
#define F(x, y, z)
Definition: MD5.cxx:112
lwtDev::EmbeddingConfig::weights
std::vector< double > weights
Definition: NNLayerConfig.h:33
convertTimingResiduals.offset
offset
Definition: convertTimingResiduals.py:71
LArNewCalib_DelayDump_OFC_Cali.idx
idx
Definition: LArNewCalib_DelayDump_OFC_Cali.py:69
dq_defect_create_virtual_defects.dname
dname
Definition: dq_defect_create_virtual_defects.py:71
copySelective.source
string source
Definition: copySelective.py:32
str
Definition: BTagTrackIpAccessor.cxx:11
I
#define I(x, y, z)
Definition: MD5.cxx:116
lwtDev::OutputNodeConfig
Definition: lightweight_network_config.h:53
lwtDev::Activation
Activation
Definition: NNLayerConfig.h:20
lwtDev::GraphConfig
Definition: lightweight_network_config.h:58
lwtDev::NodeConfig::Type
Type
Definition: NNLayerConfig.h:70
TSU::T
unsigned long long T
Definition: L1TopoDataTypes.h:35
lwtDev::NodeConfig
Definition: NNLayerConfig.h:69
lwtDev::JSONConfig
Definition: lightweight_network_config.h:36
lwtDev::EmbeddingConfig::index
int index
Definition: NNLayerConfig.h:34
mapkey::key
key
Definition: TElectronEfficiencyCorrectionTool.cxx:37
COOLRates.LINEAR
LINEAR
Definition: COOLRates.py:1245