5 #include <unordered_set>
6 #include <boost/tokenizer.hpp>
14 #define BOOST_BIND_GLOBAL_PLACEHOLDERS // Needed to silence Boost pragma message
15 #include <boost/property_tree/json_parser.hpp>
30 #include <nlohmann/json.hpp>
36 std::tuple<std::string, std::vector<std::string>>
38 std::string definition{
""};
39 std::vector<std::string> bgps;
41 std::vector<const TrigConf::TriggerItemNode*> nodes;
43 std::map<unsigned int, const TrigConf::TriggerItemNode*> nodeMap;
44 for(
auto *
node : nodes) {
48 for (
auto & tok : boost::tokenizer<boost::char_separator<char> > (
item->definition(), boost::char_separator<char>(
" ",
"()&|!")) ) {
51 int idx = std::stoi(tok);
53 if(
node->triggerThreshold()->
type()==
"BGRP") {
54 bgps.push_back(
node->thresholdName());
55 if(definition.back()==
'&') {
56 definition.pop_back();
67 if(definition.front()==
'(' and definition.back()==
')') {
68 definition = definition.substr(1,definition.size()-2);
70 return make_tuple(definition, bgps);
80 const std::string&
filename,
bool writeTmpFile)
84 std::cout <<
"No CTPConfig, no L1Menu file will be produced" << std::endl;
94 item[
"name"] = sourceItem->name();
95 item[
"legacy"] =
true;
96 item[
"ctpid"] = sourceItem->ctpId();
97 auto [definition, bunchgroups] = decodeItemDefinition(sourceItem);
98 item[
"definition"] = definition;
99 item[
"bunchgroups"] = bunchgroups;
101 item[
"partition"] = sourceItem->partition();
102 std::string smon(
"LF:");
103 smon += (sourceItem->monitor() & 0x04 ?
'1' :
'0');
104 smon += (sourceItem->monitor() & 0x02 ?
'1' :
'0');
105 smon += (sourceItem->monitor() & 0x01 ?
'1' :
'0');
107 smon += (sourceItem->monitor() & 0x20 ?
'1' :
'0');
108 smon += (sourceItem->monitor() & 0x10 ?
'1' :
'0');
109 smon += (sourceItem->monitor() & 0x08 ?
'1' :
'0');
110 item[
"monitor"] = smon;
115 json thresholds = json::object_t{};
116 std::unordered_set<std::string> legacyThrTypes{
"EM",
"TAU",
"JET",
"JB",
"JE",
"JF",
"XE",
"XS",
"TE",
"ZB",
"R2TOPO"};
118 std::string thrType = sourceThr->type();
119 if(thrType==
"BGRP" || thrType==
"RNDM") {
122 if(thrType==
"MUON") {
125 else if(thrType==
"TOPO") {
129 bool isLegacyCalo = legacyThrTypes.count(thrType) > 0;
130 json &jThisType = isLegacyCalo ? thresholds[
"legacyCalo"][thrType] : thresholds[thrType];
131 bool firstOfItsType = jThisType.empty();
134 jThisType[
"type"] = thrType;
137 size_t mapping = sourceThr->mapping();
142 jThisType[
"type"] =
"MU";
143 jThisType[
"exclusionLists"] = json::object_t{};
144 jThisType[
"roads"][
"rpc"] = json::object_t{};
145 jThisType[
"roads"][
"tgc"] = json::object_t{};
147 int ptCut = sourceThr->triggerThresholdValue(0,0)->ptCutCount();
148 thr[
"baThr"] = ptCut;
149 thr[
"ecThr"] = ptCut;
150 thr[
"fwThr"] = ptCut;
154 thr[
"tgcFlags"] =
"";
155 thr[
"rpcFlags"] =
"";
156 thr[
"region"] =
"ALL";
160 else if (thrType ==
"EM")
162 thr[
"thrValues"] = json::array_t{};
167 jtv[
"value"] =
static_cast<unsigned int>(tv->ptcut());
168 std::string isobits =
"00000";
169 auto isomask =
cl->isolationMask();
170 for (
size_t b = 0;
b < 5; ++
b)
172 if (isomask & (1 <<
b))
174 isobits[4 -
b] =
'1';
177 jtv[
"isobits"] = isobits;
178 jtv[
"etamin"] = tv->etamin();
179 jtv[
"etamax"] = tv->etamax();
180 jtv[
"phimin"] = tv->phimin();
181 jtv[
"phimax"] = tv->phimax();
182 jtv[
"priority"] =
static_cast<unsigned int>(tv->priority());
183 thr[
"thrValues"] += jtv;
186 else if (thrType ==
"TAU")
189 int ptCut = (
int)
cl->ptcut();
190 thr[
"value"] = ptCut;
191 std::string isobits =
"00000";
192 auto isomask =
cl->isolationMask();
193 for (
size_t b = 0;
b < 5; ++
b)
195 if (isomask & (1 <<
b))
197 isobits[4 -
b] =
'1';
200 thr[
"isobits"] = isobits;
202 else if (thrType ==
"JET" || thrType ==
"JB" || thrType ==
"JF")
204 thr[
"thrValues"] = json::array_t{};
209 jtv[
"value"] =
static_cast<unsigned int>(tv->ptcut());
210 jtv[
"etamin"] = tv->
etamin();
211 jtv[
"etamax"] = tv->etamax();
212 jtv[
"phimin"] = tv->phimin();
213 jtv[
"phimax"] = tv->phimax();
215 jtv[
"priority"] =
static_cast<unsigned int>(tv->priority());
216 thr[
"thrValues"] += jtv;
219 else if (thrType ==
"XE" || thrType ==
"TE" || thrType ==
"XS" || thrType ==
"JE")
221 thr[
"value"] =
static_cast<unsigned int>(sourceThr->thresholdValueVector().at(0)->ptcut());
223 else if (thrType ==
"ZB")
225 thr[
"seed"] = sourceThr->zbSeedingThresholdName();
226 thr[
"seedMultiplicity"] = sourceThr->zbSeedingThresholdMulti();
227 thr[
"seedBcdelay"] = sourceThr->bcDelay();
229 jThisType[
"thresholds"][sourceThr->name()] = thr;
234 thresholds[
"legacyCalo"][
"EM"][
"ptMinToTopo"] = ci.
minTobEM().
ptmin;
235 thresholds[
"legacyCalo"][
"EM"][
"resolutionMeV"] = (
int)(1000/ci.
globalEmScale());
236 thresholds[
"legacyCalo"][
"TAU"][
"ptMinToTopo"] = ci.
minTobTau().
ptmin;
240 json isoHAforEM{ {
"thrtype",
"HAIsoForEMthr"}, {
"Parametrization", json::array_t{}} };
241 json isoEMforEM{ {
"thrtype",
"EMIsoForEMthr"}, {
"Parametrization", json::array_t{}} };
242 json isoEMforTAU{ {
"thrtype",
"EMIsoForTAUthr"}, {
"Parametrization", json::array_t{}} };
244 json p{ {
"etamax", iso.etamax()}, {
"etamin", iso.etamin()}, {
"isobit", iso.isobit()}, {
"mincut", iso.mincut()},
245 {
"offset", iso.offset()}, {
"priority", iso.priority()}, {
"slope", iso.slope()}, {
"upperlimit", iso.upperlimit()} };
246 isoHAforEM[
"Parametrization"] +=
p;
249 json p{ {
"etamax", iso.etamax()}, {
"etamin", iso.etamin()}, {
"isobit", iso.isobit()}, {
"mincut", iso.mincut()},
250 {
"offset", iso.offset()}, {
"priority", iso.priority()}, {
"slope", iso.slope()}, {
"upperlimit", iso.upperlimit()} };
251 isoEMforEM[
"Parametrization"] +=
p;
254 json p{ {
"etamax", iso.etamax()}, {
"etamin", iso.etamin()}, {
"isobit", iso.isobit()}, {
"mincut", iso.mincut()},
255 {
"offset", iso.offset()}, {
"priority", iso.priority()}, {
"slope", iso.slope()}, {
"upperlimit", iso.upperlimit()} };
256 isoEMforTAU[
"Parametrization"] +=
p;
258 thresholds[
"legacyCalo"][
"EM"][
"isolation"][
"HAIsoForEMthr"] = std::move(isoHAforEM);
259 thresholds[
"legacyCalo"][
"EM"][
"isolation"][
"EMIsoForEMthr"] = std::move(isoEMforEM);
260 thresholds[
"legacyCalo"][
"TAU"][
"isolation"][
"EMIsoForTAUthr"] = std::move(isoEMforTAU);
263 thresholds[
"legacyCalo"][
"XS"][
"significance"] = json::object_t{
264 {
"xsSigmaScale", xs.
xsSigmaScale()}, {
"xsSigmaOffset", xs.
xsSigmaOffset()}, {
"xeMin", xs.
xeMin()}, {
"xeMax", xs.
xeMax()}, {
"teSqrtMin", xs.
teSqrtMin()}, {
"teSqrtMax", xs.
teSqrtMax()}};
267 json boards = json::object_t{};
268 boards[
"Ctpin7"] = json::object_t{ {
"type",
"CTPIN"}, {
"legacy",
true},
269 {
"connectors", std::vector<std::string>{
"EM1",
"EM2",
"TAU1",
"TAU2"}} };
270 boards[
"Ctpin8"] = json::object_t{ {
"type",
"CTPIN"}, {
"legacy",
true},
271 {
"connectors", std::vector<std::string>{
"JET1",
"JET2",
"EN1",
"EN2"}} };
272 boards[
"Ctpin9"] = json::object_t{ {
"type",
"CTPIN"}, {
"legacy",
true},
273 {
"connectors", std::vector<std::string>{
"MUCTPI",
"CTPCAL",
"NIM1",
"NIM2"}} };
274 boards[
"LegacyTopo0"] = json::object_t{ {
"type",
"TOPO"}, {
"legacy",
true},
275 {
"connectors", std::vector<std::string>{
"LegacyTopo0"}} };
276 boards[
"LegacyTopo1"] = json::object_t{ {
"type",
"TOPO"}, {
"legacy",
true},
277 {
"connectors", std::vector<std::string>{
"LegacyTopo1"}} };
280 json connectors = json::object_t{};
281 std::map<std::string,std::vector<const TrigConf::TriggerThreshold*>> triggerlinesMap;
283 if(sourceThr->isInternal()) {
286 std::string cableName = sourceThr->cableName();
287 if(cableName==
"ALFA") {
288 cableName =
"AlfaCtpin";
290 else if(cableName==
"TOPO1") {
291 cableName =
"LegacyTopo0";
293 else if(cableName==
"TOPO2") {
294 cableName =
"LegacyTopo1";
296 triggerlinesMap[cableName].push_back(sourceThr);
298 for(
auto & [
type, triggerlines] : triggerlinesMap) {
302 if(!connectors.contains(
type)) {
303 if(thr->input()==
"ctpcore") {
304 connectors[
type][
"type"] =
"electrical";
305 if(
type==
"AlfaCtpin") {
306 connectors[
type][
"triggerlines"][
"clock0"] = json::array_t{};
307 connectors[
type][
"triggerlines"][
"clock1"] = json::array_t{};
309 connectors[
type][
"triggerlines"][
"fpga0"][
"clock0"] = json::array_t{};
310 connectors[
type][
"triggerlines"][
"fpga0"][
"clock1"] = json::array_t{};
311 connectors[
type][
"triggerlines"][
"fpga1"][
"clock0"] = json::array_t{};
312 connectors[
type][
"triggerlines"][
"fpga1"][
"clock1"] = json::array_t{};
314 }
else if(thr->input()==
"ctpin") {
315 connectors[
type][
"type"] =
"ctpin";
316 connectors[
type][
"triggerlines"] = json::array_t{};
318 throw std::runtime_error(
"Unknown connector type" + thr->input());
320 connectors[
type][
"legacy"] =
true;
322 size_t start = thr->cableStart();
323 size_t nbits = thr->cableEnd() - thr->cableStart() + 1;
324 if(thr->input()==
"ctpcore") {
325 unsigned int clock = thr->clock();
326 if(
type==
"AlfaCtpin") {
327 json tl{{
"name", thr->name()}, {
"startbit",
start}, {
"nbits", nbits}};
335 json tl{{
"name",
"R2TOPO_" + thr->name()}, {
"startbit",
start}, {
"nbits", nbits}};
339 json tl{{
"name", thr->name()}, {
"startbit",
start}, {
"nbits", nbits}};
340 connectors[
type][
"triggerlines"] +=
tl;
346 json::object_t decAlgos;
347 json::object_t sortAlgos;
350 jAlg[
"algId"] =
alg.algoID();
351 jAlg[
"klass"] =
alg.type();
352 jAlg[
"fixedParameters"][
"generics"] = json::object_t{};
357 auto vInt = std::stoi(fixP.value);
358 jAlg[
"fixedParameters"][
"generics"][fixP.name] = json::object_t{{
"value", vInt}, {
"position",
pos++}};
360 catch (std::invalid_argument &)
362 jAlg[
"fixedParameters"][
"generics"][fixP.name] = json::object_t{{
"value", fixP.value}, {
"position",
pos++}};
365 jAlg[
"variableParameters"] = json::array_t{};
368 if (regP.name ==
"MaxMSqr") {
369 unsigned val = std::stoul(regP.value);
373 jAlg[
"variableParameters"] += json::object_t{{
"name", regP.name}, {
"selection", regP.selection}, {
"value",
val}};
376 jAlg[
"variableParameters"] += json::object_t{{
"name", regP.name}, {
"selection", regP.selection}, {
"value", std::stoi(regP.value)}};
379 if(
alg.isSortAlg()) {
380 jAlg[
"input"] =
alg.getInputNames()[0];
381 jAlg[
"output"] =
alg.output();
382 sortAlgos[
alg.name()] = std::move(jAlg);
383 }
else if(
alg.isDecAlg()) {
384 jAlg[
"input"] =
alg.getInputNames();
385 jAlg[
"output"] =
alg.getOutputNames();
386 decAlgos[
alg.name()] = std::move(jAlg);
389 json topo = json::object_t{};
391 topo[
"R2TOPO"][
"decisionAlgorithms"] = decAlgos;
392 topo[
"R2TOPO"][
"sortingAlgorithms"] = sortAlgos;
397 ctp[
"inputs"][
"ctpin"][
"slot7"] = json::object_t{{
"connector0",
"EM1"}, {
"connector1",
"EM2"},
398 {
"connector2",
"TAU1"}, {
"connector3",
"TAU2"}};
399 ctp[
"inputs"][
"ctpin"][
"slot8"] = json::object_t{{
"connector0",
"JET1"}, {
"connector1",
"JET2"},
400 {
"connector2",
"EN1"}, {
"connector3",
"EN2"}};
401 ctp[
"inputs"][
"ctpin"][
"slot9"] = json::object_t{{
"connector0",
"MUCTPI"}, {
"connector1",
"CTPCAL"},
402 {
"connector2",
"NIM1"}, {
"connector3",
"NIM2"}};
404 ctp[
"inputs"][
"electrical"] = json::object_t{{
"connector0",
"AlfaCtpin"}, {
"connector1",
"LegacyTopo0"}, {
"connector2",
"LegacyTopo1"}};
406 ctp[
"inputs"][
"electrical"] = json::object_t{};
408 ctp[
"inputs"][
"optical"] = json::object_t{};
409 ctp[
"monitoring"][
"ctpmon"] = json::object_t{};
413 menu[
"filetype"] =
"l1menu";
417 menu[
"thresholds"] = std::move(thresholds);
418 menu[
"topoAlgorithms"] = std::move(topo);
419 menu[
"boards"] = std::move(boards);
420 menu[
"connectors"] = std::move(connectors);
427 std::cout <<
"Wrote tmp" <<
filename << std::endl;
429 std::stringstream
ss;
432 boost::property_tree::read_json(
ss,
top);
441 std::vector<std::pair<int, int>>
444 if ( bunches.empty() ) {
447 if (bunches.size() == 1) {
448 return { {bunches.front(), bunches.front()} };
452 std::vector<std::pair<int, int>>
ranges;
453 std::vector<int>
sorted = bunches;
456 std::vector<int> differences;
457 std::adjacent_difference(
sorted.begin(),
sorted.end(), std::back_inserter(differences));
461 for (
size_t i = 1;
i < differences.size(); ++
i) {
462 if (differences[
i] == 1)
continue;
475 std::cout <<
"BunchgroupSet is empty, no file will be produced" << std::endl;
480 bgset[
"filetype"] =
"bunchgroupset";
481 bgset[
"name"] = bgs.
name();
484 const std::vector<TrigConf::BunchGroup>& bgVec = bgs.
bunchGroups();
485 for (
auto &
group : bgVec) {
488 jGroup[
"name"] =
group.name();
489 jGroup[
"id"] =
group.internalNumber();
492 json jBCIDS = json::array_t{};
496 jGroup[
"bcids"] = std::move(jBCIDS);
500 bgset[
"bunchGroups"] = std::move(jGroups);
504 outfile << std::setw(4) << bgset << std::endl;
505 std::cout <<
"Wrote tmp" <<
filename << std::endl;
507 std::stringstream
ss;
510 boost::property_tree::read_json(
ss,
top);
523 std::cout <<
"L1PrescaleSet is empty, no file will be produced" << std::endl;
528 psset[
"filetype"] =
"l1prescale";
529 psset[
"name"] = l1pss.
name();
533 auto itemPtr = ctpConfig->
menu().
item(
id);
534 if ( itemPtr !=
nullptr ) {
535 int32_t
cut = l1pss.
cuts().at(
id);
536 jCut[
"cut"] = abs(
cut);
537 jCut[
"enabled"] =
cut > 0;
538 double ps =
static_cast<double>(0xFFFFFF) / ( 0x1000000 -
cut );
540 jCuts[itemPtr->name()] = std::move(jCut);
543 psset[
"cutValues"] = std::move(jCuts);
547 outfile << std::setw(4) << psset << std::endl;
548 std::cout <<
"Wrote tmp" <<
filename << std::endl;
550 std::stringstream
ss;
553 boost::property_tree::read_json(
ss,
top);