Skip to content

Commit d5e8cc6

Browse files
authored
Merge pull request #49 from Mu2e/jcampos/AddChannelStatus
Jcampos/add channel status
2 parents f12e5dc + e941230 commit d5e8cc6

File tree

5 files changed

+256
-0
lines changed

5 files changed

+256
-0
lines changed

_codeql_detected_source_root

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
add_subdirectory(FEInterfaces)
22
add_subdirectory(Generators)
33
add_subdirectory(ArtModules)
4+
add_subdirectory(TablePlugins)
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
2+
include(otsdaq::table)
3+
4+
cet_build_plugin(SubsystemCalorimeterParametersTable otsdaq::table LIBRARIES REG
5+
otsdaq::SlowControlsTableBase
6+
otsdaq::XDAQContextTable
7+
Offline::DataProducts
8+
)
9+
10+
11+
12+
install_headers()
13+
install_source()
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
#ifndef _ots_SubsystemCalorimeterParametersTable_h_
2+
#define _ots_SubsystemCalorimeterParametersTable_h_
3+
4+
#include "otsdaq/ConfigurationInterface/ConfigurationManager.h"
5+
#include "otsdaq/TableCore/TableBase.h"
6+
7+
namespace ots {
8+
class SubsystemCalorimeterParametersTable : public TableBase {
9+
// clang-format off
10+
11+
public:
12+
SubsystemCalorimeterParametersTable (void);
13+
virtual ~SubsystemCalorimeterParametersTable (void);
14+
15+
// Methods
16+
void init (ConfigurationManager* configManager) override;
17+
18+
virtual std::string getStructureAsJSON (const ConfigurationManager* configManager) override;
19+
20+
virtual std::string getChannelMapAndCSVFormat (const ConfigurationManager* configManager, const std::string& OfflineCxxClassName);
21+
22+
virtual std::string getStatusTableInCSVFormat (const ConfigurationManager* configManager, const std::string& OfflineCxxClassName);
23+
24+
void generateOfflineTableMap (const ConfigurationManager* configManager);
25+
26+
27+
private:
28+
29+
const static std::string PATH_TO_TRIGGER_OFFLINE_DB;
30+
const static std::string CHANNEL_STATUS_TABLE;
31+
const static std::string CHANNEL_MAP_TABLE;
32+
33+
std::map<std::string, std::string> mapOfflineTables_;
34+
std::map<uint16_t, uint16_t> mapChannels_;
35+
36+
// Column names
37+
struct ColParameters // Calorimeter subsystem top level
38+
{
39+
// Incomplete list
40+
std::string const colLinkToFETypeTable = "LinkToChannelStatusTableInfo";
41+
std::string const colLinkToSlowControlsChannelTable_ = "LinkToChannelThresholdTableInfo";
42+
} ColParameters;
43+
44+
struct ColChannelMap // LinkToChannelMapTableInfo
45+
{
46+
std::string const offlineId_ = "offID";
47+
std::string const onlineId_ = "FEEchan";
48+
} ColChannelMap;
49+
50+
struct ColChannelStatus // LinkToChannelStatusTableInfo
51+
{
52+
std::string const colBoardId_ = "BoardID";
53+
std::string const colStatus_ = "Status";
54+
} ColChannelStatus;
55+
56+
struct ColChannelThreshold // LinkToChannelThresholdTableInfo
57+
{
58+
std::string const colBoardId_ = "BoardID";
59+
std::string const colROCGroupID_ = "Thresholds";
60+
std::string const colROCInterfacePluginName_= "Baseline";
61+
std::string const colLinkToSlowControlsChannelTable_ = "LinkToSlowControlsChannelTable";
62+
} ColChannelThreshold;
63+
64+
// clang-format on
65+
};
66+
} // namespace ots
67+
#endif
Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
#include "otsdaq-mu2e-calorimeter/TablePlugins/SubsystemCalorimeterParametersTable.h"
2+
#include "otsdaq/Macros/TablePluginMacros.h" //for DEFINE_OTS_TABLE
3+
4+
#include "otsdaq/TablePlugins/XDAQContextTable/XDAQContextTable.h"
5+
6+
#include "Offline/DataProducts/inc/CaloConst.hh"
7+
8+
#include <sys/stat.h> //for mkdir
9+
#include <fstream>
10+
#include <iostream>
11+
12+
using namespace ots;
13+
14+
const std::string SubsystemCalorimeterParametersTable::PATH_TO_TRIGGER_OFFLINE_DB = getenv("PATH_TO_TRIGGER_OFFLINE_DB") ? getenv("PATH_TO_TRIGGER_OFFLINE_DB") : "";
15+
const std::string SubsystemCalorimeterParametersTable::CHANNEL_MAP_TABLE = "SubsystemCalorimeterMapTable";
16+
const std::string SubsystemCalorimeterParametersTable::CHANNEL_STATUS_TABLE = "SubsystemCalorimeterStatusTable";
17+
18+
//==============================================================================
19+
SubsystemCalorimeterParametersTable::SubsystemCalorimeterParametersTable(void) : TableBase("SubsystemCalorimeterParametersTable") {}
20+
21+
//==============================================================================
22+
SubsystemCalorimeterParametersTable::~SubsystemCalorimeterParametersTable(void) {}
23+
24+
//==============================================================================
25+
/// init
26+
/// generate calo specific files needed by the online trigger and save them in the filesystem 'offline' db
27+
void SubsystemCalorimeterParametersTable::init(ConfigurationManager* configManager) {
28+
// use isFirstAppInContext to only run once per context, for example to avoid
29+
// generating files on local disk multiple times.
30+
bool isFirstAppInContext_ = configManager->isOwnerFirstAppInContext();
31+
32+
__COUTV__(isFirstAppInContext_);
33+
if(!isFirstAppInContext_)
34+
return;
35+
36+
__COUTV__(SubsystemCalorimeterParametersTable::PATH_TO_TRIGGER_OFFLINE_DB);
37+
if(SubsystemCalorimeterParametersTable::PATH_TO_TRIGGER_OFFLINE_DB.size() == 0)
38+
return;
39+
40+
__COUT__ << "*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*&*" << __E__;
41+
__COUT__ << configManager->__SELF_NODE__ << __E__;
42+
43+
generateOfflineTableMap(configManager);
44+
45+
for(const auto& offlineTable : mapOfflineTables_) {
46+
std::string offlineTableFileName = PATH_TO_TRIGGER_OFFLINE_DB + "/" + offlineTable.first + ".txt";
47+
48+
try {
49+
std::ofstream out(offlineTableFileName);
50+
if(!out) {
51+
__SS__ << "Failed to open file: " << offlineTableFileName << __E__;
52+
__SS_THROW__;
53+
}
54+
out << offlineTable.second;
55+
out.close();
56+
} catch(const std::exception& e) {
57+
__SS__ << "Failed to write offline table " << offlineTable.first << " to file: " << e.what() << __E__;
58+
__SS_THROW__;
59+
}
60+
}
61+
62+
} // end init()
63+
64+
//==============================================================================
65+
void SubsystemCalorimeterParametersTable::generateOfflineTableMap(const ConfigurationManager* configManager) {
66+
mapOfflineTables_.clear();
67+
mapOfflineTables_["CalChannelMap"] = getChannelMapAndCSVFormat(configManager, "CalChannelMap");
68+
__COUTT__ << mapOfflineTables_["CalChannelMap"] << __E__;
69+
mapOfflineTables_["CalChannelStatus"] = getStatusTableInCSVFormat(configManager, "CalChannelStatus");
70+
__COUTT__ << mapOfflineTables_["CalChannelStatus"] << __E__;
71+
} // end generateOfflineTableMap()
72+
73+
//==============================================================================
74+
std::string SubsystemCalorimeterParametersTable::getChannelMapAndCSVFormat(const ConfigurationManager* configManager, const std::string& OfflineCxxClassName) {
75+
mapChannels_.clear();
76+
77+
std::stringstream OfflineTable;
78+
OfflineTable << "TABLE " << OfflineCxxClassName << __E__;
79+
std::vector<std::pair<std::string, ConfigurationTree>> channelMapRecords = configManager->getNode(SubsystemCalorimeterParametersTable::CHANNEL_MAP_TABLE).getChildren();
80+
81+
// start main fe/DTC record loop
82+
for(auto& channelMapPair : channelMapRecords) {
83+
uint16_t onlineID = channelMapPair.second.getNode(ColChannelMap.onlineId_).getValue<uint16_t>();
84+
uint16_t offlineID = channelMapPair.second.getNode(ColChannelMap.offlineId_).getValue<uint16_t>();
85+
mapChannels_[onlineID] = offlineID;
86+
87+
OfflineTable << onlineID << "," << offlineID << "\n";
88+
}
89+
return OfflineTable.str();
90+
} // end getChannelMapAndCSVFormat()
91+
92+
//==============================================================================
93+
std::string SubsystemCalorimeterParametersTable::getStatusTableInCSVFormat(const ConfigurationManager* configManager, const std::string& OfflineCxxClassName) {
94+
std::stringstream OfflineTable;
95+
OfflineTable << "TABLE " << OfflineCxxClassName << __E__;
96+
std::vector<std::pair<std::string, ConfigurationTree>> channelStatusRecords = configManager->getNode(SubsystemCalorimeterParametersTable::CHANNEL_STATUS_TABLE).getChildren();
97+
98+
// start main fe/DTC record loop
99+
for(auto& channelStatusPair : channelStatusRecords) {
100+
uint16_t boardID = channelStatusPair.second.getNode(ColChannelStatus.colBoardId_).getValue<uint16_t>();
101+
ConfigurationTree::BitMap<std::string> bitmap = channelStatusPair.second.getNode(ColChannelStatus.colStatus_).getValueAsBitMap();
102+
103+
// assume data is 1-dimensional
104+
for(uint32_t j = 0; j < bitmap.numberOfColumns(0); j++) {
105+
const uint32_t onlineID = boardID * mu2e::CaloConst::_nChPerDIRAC + j;
106+
auto it = mapChannels_.find(onlineID);
107+
if(it == mapChannels_.end()) {
108+
__SS__ << "No channel map entry found for online ID " << onlineID << " (boardID=" << boardID << ", channel=" << j << "). Tables may be inconsistent." << __E__;
109+
__SS_THROW__;
110+
}
111+
OfflineTable << it->second << ", ";
112+
OfflineTable << ((bitmap.get(0, j).size() == 0) ? "0" : bitmap.get(0, j));
113+
OfflineTable << ((j + 1 == bitmap.numberOfColumns(0)) ? "" : "\n");
114+
}
115+
OfflineTable << "\n";
116+
}
117+
return OfflineTable.str();
118+
} // end getStatusTableInCSVFormat()
119+
120+
//==============================================================================
121+
// return status structures
122+
std::string SubsystemCalorimeterParametersTable::getStructureAsJSON(const ConfigurationManager* cfgMgr) {
123+
// Don't generate maps if done already in init()
124+
if(mapOfflineTables_.size() == 0)
125+
generateOfflineTableMap(cfgMgr);
126+
127+
std::vector<std::pair<std::string, ConfigurationTree>> channelStatusRecords = cfgMgr->getNode(SubsystemCalorimeterParametersTable::CHANNEL_STATUS_TABLE).getChildren();
128+
129+
std::stringstream outstream;
130+
131+
outstream << "{";
132+
133+
// Write all cat-3 tables converted from MongoDB
134+
outstream << "\t\"cat3\": {" << __E__;
135+
std::map<std::string, std::string>::iterator it;
136+
for(it = mapOfflineTables_.begin(); it != mapOfflineTables_.end(); ++it) {
137+
outstream << "\"" << it->first << "\":" << it->second;
138+
outstream << (std::next(it) == mapOfflineTables_.end() ? "" : ",");
139+
}
140+
outstream << "},";
141+
142+
// Write any desired table in a custom format for user-friendly quick reading
143+
outstream << "\t\"custom\": ";
144+
outstream << "{" << __E__;
145+
outstream << "\t\"Number of rows\": " << channelStatusRecords.size() << "," << __E__;
146+
outstream << "\t\"Rows\": [" << __E__;
147+
148+
uint16_t statusPairIdx = 0;
149+
for(auto& channelStatusPair : channelStatusRecords) {
150+
uint16_t boardID = channelStatusPair.second.getNode(ColChannelStatus.colBoardId_).getValue<uint16_t>();
151+
ConfigurationTree::BitMap<std::string> bitmap = channelStatusPair.second.getNode(ColChannelStatus.colStatus_).getValueAsBitMap();
152+
statusPairIdx++;
153+
154+
outstream << "\t\t{" << __E__;
155+
outstream << "\t\t\"BoardID\": " << boardID << "," << __E__;
156+
outstream << "\t\t\"Rows\": " << bitmap.numberOfRows() << "," << __E__;
157+
outstream << "\t\t\"BitMap\": [";
158+
159+
// assume data is 1-dimensional
160+
for(uint32_t j = 0; j < bitmap.numberOfColumns(0); j++) {
161+
outstream << ((bitmap.get(0, j).size() == 0) ? "0" : bitmap.get(0, j));
162+
outstream << ((j + 1 == bitmap.numberOfColumns(0)) ? "" : ", ");
163+
}
164+
outstream << "]" << __E__;
165+
outstream << "\t\t}" << (statusPairIdx == channelStatusRecords.size() ? "" : ",") << __E__;
166+
}
167+
168+
outstream << "\t]" << __E__;
169+
outstream << "}"; // close custom blob
170+
outstream << "}"; // close full blob
171+
return outstream.str();
172+
} // end getStructureAsJSON()
173+
174+
DEFINE_OTS_TABLE(SubsystemCalorimeterParametersTable)

0 commit comments

Comments
 (0)