14#include <boost/algorithm/string.hpp>
19#include <unordered_map>
21#include <yaml-cpp/yaml.h>
37 auto node = YAML::Node(YAML::NodeType::Undefined);
44 if (!node && !optional) {
45 std::stringstream msg;
46 msg <<
"requested node was not found ";
51 throw std::runtime_error(msg.str());
60 std::vector<std::string> res;
61 res.reserve(node.size());
63 for (
const auto& item : node) {
64 res.push_back(item.first.as<std::string>());
67 catch (
const YAML::InvalidNode& exc) {
69 <<
"L1 config: attempt to call ConfigReader::GetNodeKeys for node, keys of which could not be represented "
70 <<
"with strings. An empty vector will be returned";
71 std::vector<std::string>().swap(res);
80 std::vector<Iteration> res;
83 std::unordered_map<std::string, Iteration> mPossibleIterations;
87 for (
const auto& iterNode : currentNode) {
88 std::string thisIterName = iterNode[
"name"].as<std::string>(
"");
89 std::string baseIterName = iterNode[
"base_iteration"].as<std::string>(
"");
91 if (baseIterName.size()) {
92 if (mPossibleIterations.find(baseIterName) == mPossibleIterations.end()) {
93 std::stringstream msg;
94 msg <<
"A CA iteration \"" << thisIterName <<
"\" requires a base iteration with name \"" << baseIterName
95 <<
"\", which was not registered yet. Please, place an entry with the requested base iteration above "
96 <<
"in the possible_iterations node";
97 throw std::runtime_error(std::move(msg.str()));
99 mPossibleIterations[thisIterName] =
ReadSingleCAIteration(iterNode, mPossibleIterations.at(baseIterName));
111 LOG(info) <<
"- Reading user iterations ";
114 auto currentNode =
fUserConfigNode[
"core"][
"track_finder"][
"iterations"];
116 for (
const auto& iterNode : currentNode) {
117 std::string thisIterName = iterNode[
"name"].as<std::string>(
"");
118 std::string baseIterName = iterNode[
"base_iteration"].as<std::string>(
"");
120 LOG(info) <<
"- Reading user iteration " << thisIterName <<
"(" << baseIterName <<
")";
122 if (mPossibleIterations.find(thisIterName) != mPossibleIterations.end()) {
126 else if (mPossibleIterations.find(baseIterName) != mPossibleIterations.end()) {
132 auto itFound = std::find_if(res.begin(), res.end(), [&](
auto& i) { return i.GetName() == baseIterName; });
133 if (itFound != res.end()) {
144 if (res.size() == 0) {
145 auto currentNode =
fMainConfigNode[
"core"][
"track_finder"][
"iteration_sequence"];
147 assert(currentNode.size());
148 for (
const auto& iterNode : currentNode) {
149 std::string thisIterName = iterNode.as<std::string>();
150 if (mPossibleIterations.find(thisIterName) == mPossibleIterations.end()) {
151 std::stringstream msg;
152 msg <<
"Unknow iteration in the iteration sequence, defined in main config file: " << thisIterName;
153 throw std::runtime_error(std::move(msg.str()));
155 res.push_back(mPossibleIterations.at(thisIterName));
166 std::vector<std::pair<EDetectorID, int>> res;
169 std::string sNodePath =
"ca/core/common/inactive_stations";
170 auto node =
GetNode([](YAML::Node n) {
return n[
"core"][
"common"][
"inactive_stations"]; },
true);
171 if (!node || node.size() == 0) {
176 res.reserve(node.size());
177 for (
const auto& item : node) {
178 std::string nodeVal = item.as<std::string>();
181 if (nodeVal.empty()) {
186 if (std::any_of(nodeVal.begin(), nodeVal.end(), [](
auto c) { return c ==
' ' || c ==
'\t' || c ==
'\n'; })) {
187 throw std::runtime_error(
188 fmt::format(
"Station name passed in YAML branch {} contains illegal characters: {}", sNodePath, nodeVal));
192 std::vector<std::string> nodeValParts;
193 boost::algorithm::split(nodeValParts, nodeVal, boost::is_any_of(
":"));
194 if (nodeValParts.size() > 2) {
195 throw std::runtime_error(
196 fmt::format(
"Station name passed in YAML branch {} contains to many colon characters (max 2 allowed): {}",
197 sNodePath, nodeVal));
202 auto itDetName =
fDetNameMap.find(boost::algorithm::to_lower_copy(nodeValParts[0]));
204 throw std::runtime_error(
205 fmt::format(
"Detector name {} passed in YAML branch {} is not supported by CA. Please ensure, that "
206 "the detector is registered in enum class EDetectorID",
207 nodeValParts[0], sNodePath));
211 if (nodeValParts.size() == 1) {
212 res.emplace_back(detId, -1);
219 locId = std::stoi(nodeValParts[1]);
221 catch (
const std::exception& err) {
222 throw std::runtime_error(fmt::format(
"Could not convert the {} to integral locId value (node {}, branch {})",
223 nodeValParts[1], nodeVal, sNodePath));
227 throw std::runtime_error(
228 fmt::format(
"Illegal station locId passed in the node {} in YAML branch {}. The possible values are: "
229 "-1 to disable all stations, non-negative integer to disable a single station",
232 res.emplace_back(detId, locId);
242 std::string sNodePath =
"ca/core/common/misalignment_tolerance";
243 auto node =
GetNode([](YAML::Node n) {
return n[
"core"][
"common"][
"misalignment_tolerance"]; },
true);
244 if (!node || node.size() == 0) {
248 for (
const auto& item : node) {
249 std::string detName = boost::algorithm::to_lower_copy(item.first.as<std::string>());
252 throw std::runtime_error(
253 fmt::format(
"Detector name {} passed in YAML branch {} is not supported by CA. Please ensure, that "
254 "the detector is registered in enum class EDetectorID",
255 item.first.as<std::string>(), sNodePath));
258 auto detId = it->second;
259 auto v = item.second.as<std::vector<float>>();
261 throw std::runtime_error(fmt::format(
"Illegal number of elements, provided to initialize misalignment "
262 "tolerances ({} != 3)",
277 iter.SetName(node[
"name"].as<std::string>());
278 iter.SetTrackChi2Cut(node[
"track_chi2_cut"].as<float>(defaultIter.
GetTrackChi2Cut()));
279 iter.SetTripletChi2Cut(node[
"triplet_chi2_cut"].as<float>(defaultIter.
GetTripletChi2Cut()));
280 iter.SetTripletFinalChi2Cut(node[
"triplet_final_chi2_cut"].as<float>(defaultIter.
GetTripletFinalChi2Cut()));
281 iter.SetDoubletChi2Cut(node[
"doublet_chi2_cut"].as<float>(defaultIter.
GetDoubletChi2Cut()));
282 iter.SetPickGather(node[
"pick_gather"].as<float>(defaultIter.
GetPickGather()));
283 iter.SetTripletLinkChi2(node[
"triplet_link_chi2"].as<float>(defaultIter.
GetTripletLinkChi2()));
284 iter.SetMaxQp(node[
"max_qp"].as<float>(defaultIter.
GetMaxQp()));
285 iter.SetMaxSlopePV(node[
"max_slope_pv"].as<float>(defaultIter.
GetMaxSlopePV()));
286 iter.SetMaxSlope(node[
"max_slope"].as<float>(defaultIter.
GetMaxSlope()));
287 iter.SetMaxDZ(node[
"max_dz"].as<float>(defaultIter.
GetMaxDZ()));
288 iter.SetTargetPosSigmaXY(node[
"target_pos_sigma_x"].as<float>(defaultIter.
GetTargetPosSigmaX()),
290 iter.SetFirstStationIndex(node[
"first_station_index"].as<int>(defaultIter.
GetFirstStationIndex()));
291 iter.SetPrimaryFlag(node[
"is_primary"].as<bool>(defaultIter.
GetPrimaryFlag()));
292 iter.SetElectronFlag(node[
"is_electron"].as<bool>(defaultIter.
GetElectronFlag()));
294 iter.SetExtendTracksFlag(node[
"is_extend_tracks"].as<bool>(defaultIter.
GetExtendTracksFlag()));
295 iter.SetMaxStationGap(node[
"max_station_gap"].as<int>(defaultIter.
GetMaxStationGap()));
296 iter.SetMinNhits(node[
"min_n_hits"].as<int>(defaultIter.
GetMinNhits()));
297 iter.SetMinNhitsStation0(node[
"min_n_hits_station_0"].as<int>(defaultIter.
GetMinNhitsStation0()));
299 catch (
const YAML::InvalidNode& exc) {
301 const auto nodeKeysStr =
302 std::accumulate(nodeKeys.cbegin(), nodeKeys.cend(), std::string(
""),
303 [](std::string lhs, std::string rhs) { return std::move(lhs) +
"\n\t" + std::move(rhs); });
304 LOG(fatal) <<
"L1 config: attempt to access key which does not exist in the configuration file (message from "
305 <<
"YAML exception: " << exc.what() <<
"). Defined keys: " << nodeKeysStr;
315 std::move(yaml::Read<Config::Control>(
GetNode([](YAML::Node n) {
return n[
"core"][
"track_finder"]; }))),
316 std::move(yaml::Read<Config::Dev>(
GetNode([](YAML::Node n) {
return n[
"core"][
"dev"]; }))),
324 for (
int iDet = 0; iDet < static_cast<int>(input.size()); ++iDet) {
325 std::string detName = boost::algorithm::to_lower_copy(input[iDet]);
326 if (!detName.empty()) {
341 LOG(info) <<
"ConfigReader: Registering main configuraiton file: \"\033[1;32m" << path <<
"\033[0m\"";
344 catch (
const std::exception& err) {
345 LOG(error) <<
"ERROR: " << err.what();
359 LOG(info) <<
"ConfigReader: Registering user configuraiton file: \"\033[1;32m" << path <<
"\033[0m\"";
362 catch (
const std::exception& err) {
363 LOG(error) <<
"ERROR: " << err.what();
Configuration parameter file reader for the CA tracking algorithm (header)
Compile-time constants definition for the CA tracking algorithm.
ConfigReader(int verbose=1)
Constructor.
A reader for the CA parameters from the YAML configuration files.
std::vector< Iteration > ReadCAIterationVector() const
Reads CA track finder iterations from YAML node.
YAML::Node fUserConfigNode
User configuration node.
int fVerbose
Verbosity level.
void SetDetectorNames(const std::array< std::string, constants::size::MaxNdetectors > &input)
Sets detector names.
void SetUserConfigPath(const std::string &path)
Sets user config file.
Config::MisalignmentTolArray_t ReadMisalignmentTolerances() const
Reads misalignment tolerances.
Iteration ReadSingleCAIteration(const YAML::Node &node, const Iteration &defaultIter) const
Reads iteration from config file.
YAML::Node fMainConfigNode
Main configuration node.
std::unordered_map< std::string, EDetectorID > fDetNameMap
YAML::Node GetNode(std::function< YAML::Node(YAML::Node)> fn, bool optional=false) const
Accesses a node either from user config or from main config.
std::vector< std::pair< EDetectorID, int > > ReadInactiveStationMap() const
Reads inactive tracking station map.
std::string fsUserConfigPath
Path to the user config file (optional)
std::vector< std::string > GetNodeKeys(const YAML::Node &node) const
Gets parameters content of the node.
std::string fsMainConfigPath
Path to the main config file (mandatory)
void SetMainConfigPath(const std::string &path)
Sets main config file.
Config CreateConfig() const
Creates a config.
Configuration of the CA tracking (excluding geometry)
std::array< MisalignmentTolerance, constants::size::MaxNdetectors > MisalignmentTolArray_t
A set of parameters for the CA Track finder iteration.
int GetMinNhits() const
Gets min n hits.
float GetTripletChi2Cut() const
Gets triplet chi2 upper cut.
float GetMaxSlope() const
Gets max slope (tx\ty) in 3D hit position of a triplet.
float GetPickGather() const
Gets size of region [TODO: units??] to attach new hits to the created track.
float GetTrackChi2Cut() const
Gets track chi2 upper cut.
bool GetElectronFlag() const
flag check: electrons/positrons - true, heavy charged - false
float GetDoubletChi2Cut() const
Gets doublet chi2 upper cut.
float GetTripletFinalChi2Cut() const
Gets triplet chi2 upper cut.
int GetMaxStationGap() const
Gets flag: true - triplets are also built with skipping <= GetMaxStationGap stations.
int GetMinNhitsStation0() const
Gets min n hits for tracks that start on station 0.
float GetTargetPosSigmaX() const
Gets sigma target position in X direction [cm].
bool GetTrackFromTripletsFlag() const
float GetTripletLinkChi2() const
Gets min value of dp/dp_error, for which two tiplets are neighbours.
float GetMaxQp() const
Gets max considered q/p for tracks.
float GetMaxDZ() const
Gets correction for accounting overlaping and iff z.
bool GetPrimaryFlag() const
Checks flag: true - only primary tracks are searched, false - [all or only secondary?...
float GetTargetPosSigmaY() const
Gets sigma target position in Y direction [cm].
int GetFirstStationIndex() const
Gets station index of the first station used in tracking.
bool GetExtendTracksFlag() const
Sets flag: true - extends track candidates with unused hits.
float GetMaxSlopePV() const
Gets max slope (tx\ty) in primary vertex.
Misalignment correction for x, y and time measurements in tracking.
EDetectorID
Enumeration for the tracking detector subsystems in CBM-CA.