Skip to content

Commit 110107d

Browse files
committed
MCH: small exe to generate electronic mapping in json format
in particular can be used to generate the `solars.json` data file for mchview, using : ``` o2-mch-global-mapper -s -m > solars.json ```
1 parent ccded3c commit 110107d

8 files changed

Lines changed: 371 additions & 0 deletions

File tree

DataFormats/Detectors/MUON/MCH/include/DataFormatsMCH/DsChannelId.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ class DsChannelId
5252

5353
std::string asString() const;
5454

55+
uint32_t value() const { return mChannelId; }
56+
5557
private:
5658
uint32_t mChannelId{0};
5759

Detectors/MUON/MCH/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,3 +27,4 @@ add_subdirectory(Workflow)
2727
add_subdirectory(Conditions)
2828
add_subdirectory(Calibration)
2929
add_subdirectory(DevIO)
30+
add_subdirectory(GlobalMapping)
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
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(MCHGlobalMapping
13+
SOURCES src/Mapper.cxx
14+
PUBLIC_LINK_LIBRARIES O2::MCHRawElecMap O2::MCHMappingInterface)
15+
16+
o2_add_executable(
17+
global-mapper
18+
SOURCES src/global-mapper.cxx
19+
COMPONENT_NAME mch
20+
PUBLIC_LINK_LIBRARIES Boost::program_options
21+
O2::DataFormatsMCH
22+
O2::MCHGlobalMapping
23+
O2::MCHMappingImpl4
24+
RapidJSON::RapidJSON)
25+
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<!-- doxy
2+
\page refDetectorsMUONMCHGlobalMapping Global Mapping
3+
/doxy -->
4+
5+
# MCH Global Mapping
6+
7+
Global mapping is just a gathering a few functions that do depend on the other two mappings in use : the [detector mapping](/Detectors/MUON/MCH/Mapping/Interface/include/MCHMappingInterface/Segmentation.h) and the [electronic mapping](/Detectors/MUON/MCH/Raw/ElecMap/include/MCHRawElecMap/Mapper.h)
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
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 O2_MCH_GLOBAL_MAPPING_MAPPER_H_
13+
#define O2_MCH_GLOBAL_MAPPING_MAPPER_H_
14+
15+
#include <cstdint>
16+
#include <utility>
17+
18+
#include "MCHRawElecMap/DsDetId.h"
19+
20+
namespace o2::mch
21+
{
22+
/** DsIndex is an integer, from 0 to 16719, which uniquely identifies
23+
* one pair (deId,dsId), i.e. one DualSampa, within the whole detector
24+
*/
25+
using DsIndex = uint16_t;
26+
27+
constexpr uint16_t NumberOfDualSampas = 16820;
28+
29+
/** getDsIndex returns the unique index of one dual sampa. */
30+
DsIndex getDsIndex(const o2::mch::raw::DsDetId& dsDetId);
31+
32+
/** decodeDsIndex converts a unique dual sampa index into a pair (deId,dsId). */
33+
o2::mch::raw::DsDetId getDsDetId(DsIndex dsIndex);
34+
35+
/** get the number of channels for a given dual sampa (will be 64 in most of the cases. */
36+
uint8_t numberOfDualSampaChannels(DsIndex dsIndex);
37+
} // namespace o2::mch
38+
39+
#endif
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
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+
#include "MCHGlobalMapping/Mapper.h"
13+
#include "MCHMappingInterface/Segmentation.h"
14+
#include <map>
15+
#include <vector>
16+
17+
namespace o2::mch
18+
{
19+
20+
template <typename KEY, typename VALUE>
21+
std::map<VALUE, KEY> inverseMap(const std::map<KEY, VALUE>& src)
22+
{
23+
std::map<VALUE, KEY> dest;
24+
for (auto p : src) {
25+
dest.emplace(p.second, p.first);
26+
}
27+
return dest;
28+
}
29+
30+
std::map<uint32_t, uint16_t> buildDetId2DsIndexMap()
31+
{
32+
static std::map<uint32_t, uint16_t> m;
33+
if (m.empty()) {
34+
uint16_t dsIndex{0};
35+
o2::mch::mapping::forEachDetectionElement([&](int deId) {
36+
const auto& seg = o2::mch::mapping::segmentation(deId);
37+
std::vector<int> dsids;
38+
seg.forEachDualSampa([&](int dsid) {
39+
dsids.emplace_back(dsid);
40+
});
41+
// ensure dual sampa are sorted by dsid
42+
std::sort(dsids.begin(), dsids.end());
43+
for (auto dsId : dsids) {
44+
raw::DsDetId det{deId, dsId};
45+
m.emplace(encode(det), dsIndex);
46+
++dsIndex;
47+
}
48+
});
49+
}
50+
return m;
51+
}
52+
53+
DsIndex getDsIndex(const o2::mch::raw::DsDetId& dsDetId)
54+
{
55+
static std::map<uint32_t, uint16_t> m = buildDetId2DsIndexMap();
56+
return m[encode(dsDetId)];
57+
}
58+
59+
o2::mch::raw::DsDetId getDsDetId(DsIndex dsIndex)
60+
{
61+
static std::map<uint16_t, uint32_t> m = inverseMap(buildDetId2DsIndexMap());
62+
return raw::decodeDsDetId(m[dsIndex]);
63+
}
64+
65+
uint8_t numberOfDualSampaChannels(DsIndex dsIndex)
66+
{
67+
static std::vector<uint8_t> channelsPerDS;
68+
if (channelsPerDS.empty()) {
69+
for (uint16_t dsIndex = 0; dsIndex < o2::mch::NumberOfDualSampas; ++dsIndex) {
70+
raw::DsDetId det{o2::mch::getDsDetId(dsIndex)};
71+
uint8_t nch{0};
72+
auto dsId = det.dsId();
73+
auto deId = det.deId();
74+
const auto& seg = o2::mch::mapping::segmentation(deId);
75+
seg.bending().forEachPadInDualSampa(dsId, [&nch](int /*catPadIndex*/) { ++nch; });
76+
seg.nonBending().forEachPadInDualSampa(dsId, [&nch](int /*catPadIndex*/) { ++nch; });
77+
channelsPerDS.emplace_back(nch);
78+
}
79+
}
80+
return channelsPerDS[dsIndex];
81+
}
82+
} // namespace o2::mch
Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,214 @@
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+
/// @author Laurent Aphecetche
13+
14+
#include "DataFormatsMCH/DsChannelId.h"
15+
#include "MCHGlobalMapping/Mapper.h"
16+
#include "MCHRawElecMap/DsDetId.h"
17+
#include "MCHRawElecMap/DsElecId.h"
18+
#include "MCHRawElecMap/Mapper.h"
19+
#include "boost/program_options.hpp"
20+
#include <cstdint>
21+
#include <fmt/format.h>
22+
#include <fstream>
23+
#include <gsl/span>
24+
#include <iostream>
25+
#include <iostream>
26+
#include <iterator>
27+
#include <limits>
28+
#include <map>
29+
#include <optional>
30+
#include <rapidjson/document.h>
31+
#include <rapidjson/stringbuffer.h>
32+
#include <rapidjson/writer.h>
33+
#include <stdexcept>
34+
#include <string>
35+
36+
namespace po = boost::program_options;
37+
using namespace o2::mch::raw;
38+
39+
uint16_t computeDsBinX(int feeId, int linkId, int elinkId)
40+
{
41+
constexpr uint64_t maxLinkId = 12;
42+
constexpr uint64_t maxElinkId = 40;
43+
44+
int v = feeId * maxLinkId * maxElinkId +
45+
(linkId % maxLinkId) * maxElinkId + elinkId + 1;
46+
return static_cast<uint16_t>(v & 0xFFFF);
47+
}
48+
49+
struct DualSampaInfo {
50+
uint16_t dsBin;
51+
uint16_t dsBinX;
52+
int deId;
53+
int dsId;
54+
uint16_t feeId;
55+
uint8_t linkId;
56+
uint8_t eLinkId;
57+
uint16_t solarId;
58+
uint8_t nch;
59+
uint32_t firstDsChannelId;
60+
};
61+
62+
std::vector<DualSampaInfo> dualSampaInfos;
63+
64+
std::vector<DualSampaInfo> computeDualSampaInfos()
65+
{
66+
uint16_t dsBin{0};
67+
68+
auto elec2det = createElec2DetMapper<ElectronicMapperGenerated>();
69+
auto det2elec = createDet2ElecMapper<ElectronicMapperGenerated>();
70+
auto solar2FeeLink = createSolar2FeeLinkMapper<ElectronicMapperGenerated>();
71+
72+
for (uint16_t dsIndex = 0; dsIndex < o2::mch::NumberOfDualSampas; ++dsIndex) {
73+
DsDetId det{o2::mch::getDsDetId(dsIndex)};
74+
auto elec = det2elec(det);
75+
if (!elec.has_value()) {
76+
throw std::runtime_error("mapping is wrong somewhere...");
77+
}
78+
auto eLinkId = elec->elinkId();
79+
auto solarId = elec->solarId();
80+
auto s2f = solar2FeeLink(solarId);
81+
if (!s2f.has_value()) {
82+
throw std::runtime_error("mapping is wrong somewhere...");
83+
}
84+
auto feeId = s2f->feeId();
85+
auto linkId = s2f->linkId();
86+
87+
auto dsBinX = computeDsBinX(feeId, linkId, eLinkId);
88+
89+
uint8_t nch = o2::mch::numberOfDualSampaChannels(dsIndex);
90+
91+
o2::mch::DsChannelId firstDsChannelId(solarId, eLinkId, 0);
92+
93+
auto dsId = det.dsId();
94+
auto deId = det.deId();
95+
96+
dualSampaInfos.emplace_back(DualSampaInfo{dsIndex, dsBinX,
97+
deId, dsId,
98+
feeId, linkId,
99+
eLinkId, solarId, nch,
100+
firstDsChannelId.value()});
101+
}
102+
return dualSampaInfos;
103+
}
104+
105+
void solar2json(bool mchview)
106+
{
107+
rapidjson::StringBuffer buffer;
108+
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
109+
110+
auto solar2FeeLink = createSolar2FeeLinkMapper<ElectronicMapperGenerated>();
111+
auto dualSampaInfos = computeDualSampaInfos();
112+
113+
auto outputSolars = [&](uint16_t solarId) {
114+
auto dualSampas = getDualSampas<ElectronicMapperGenerated>(solarId);
115+
auto deId = dualSampas.begin()->deId();
116+
117+
writer.StartObject();
118+
writer.Key("solarId");
119+
writer.Int(solarId);
120+
auto feelink = solar2FeeLink(solarId);
121+
uint16_t feeId{std::numeric_limits<uint16_t>::max()};
122+
uint8_t linkId{std::numeric_limits<uint8_t>::max()};
123+
if (feelink.has_value()) {
124+
feeId = feelink->feeId();
125+
linkId = feelink->linkId();
126+
writer.Key("FeeId");
127+
writer.Int(feeId);
128+
writer.Key("LinkId");
129+
writer.Int(linkId);
130+
}
131+
writer.Key("deId");
132+
writer.Int(deId);
133+
writer.Key("ds");
134+
writer.StartArray();
135+
for (const auto& dsi : dualSampaInfos) {
136+
if (dsi.feeId == feeId &&
137+
dsi.linkId == linkId) {
138+
writer.StartObject();
139+
writer.Key("dsId");
140+
writer.Int(dsi.dsId);
141+
if (mchview) {
142+
writer.Key("elinkId");
143+
} else {
144+
writer.Key("eLinkId");
145+
}
146+
writer.Int(dsi.eLinkId);
147+
if (mchview) {
148+
writer.Key("dsbin");
149+
writer.Int(dsi.dsBinX);
150+
} else {
151+
writer.Key("binX");
152+
writer.Int(dsi.dsBinX);
153+
writer.Key("bin");
154+
writer.Int(dsi.dsBin);
155+
if (dsi.nch != 64) {
156+
writer.Key("nch");
157+
writer.Int(dsi.nch);
158+
}
159+
writer.Key("fdci");
160+
writer.Int(dsi.firstDsChannelId);
161+
}
162+
writer.EndObject();
163+
}
164+
}
165+
writer.EndArray();
166+
writer.EndObject();
167+
};
168+
169+
auto solarIds = getSolarUIDs<ElectronicMapperGenerated>();
170+
writer.StartArray();
171+
for (auto s : solarIds) {
172+
outputSolars(s);
173+
}
174+
writer.EndArray();
175+
176+
std::cout << buffer.GetString() << "\n";
177+
}
178+
179+
int main(int argc, char* argv[])
180+
{
181+
po::variables_map vm;
182+
po::options_description generic("Generic options");
183+
184+
// clang-format off
185+
generic.add_options()
186+
("help,h", "produce help message")
187+
("solar,s","output solar based file")
188+
("mchview,m","output format suitable for mchview")
189+
;
190+
// clang-format on
191+
192+
po::options_description cmdline;
193+
cmdline.add(generic);
194+
195+
po::store(po::command_line_parser(argc, argv).options(cmdline).run(), vm);
196+
197+
if (vm.count("help")) {
198+
std::cout << generic << "\n";
199+
return 2;
200+
}
201+
202+
try {
203+
po::notify(vm);
204+
} catch (boost::program_options::error& e) {
205+
std::cout << "Error: " << e.what() << "\n";
206+
exit(1);
207+
}
208+
209+
if (vm.count("solar")) {
210+
solar2json(vm.count("mchview"));
211+
}
212+
213+
return 0;
214+
}

Detectors/MUON/MCH/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,5 @@ This is a top page for the MCH detector documentation.
2323
\subpage refDetectorsMUONMCHTracking
2424
\subpage refDetectorsMUONMCHTriggering
2525
\subpage refDetectorsMUONMCHWorkflow
26+
\subpage refDetectorsMUONMCHGlobalMapping
2627
/doxy -->

0 commit comments

Comments
 (0)