Skip to content

Commit

Permalink
improve TF timestamp calculation and add time margin
Browse files Browse the repository at this point in the history
  • Loading branch information
pillot committed Jul 10, 2024
1 parent 35b3277 commit eee9f11
Show file tree
Hide file tree
Showing 4 changed files with 120 additions and 69 deletions.
30 changes: 17 additions & 13 deletions Detectors/MUON/MCH/Status/include/MCHStatus/HVStatusCreator.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,20 +47,25 @@ class StatusMap;
class HVStatusCreator
{
public:
using DPID = dcs::DataPointIdentifier;
using DPVAL = dcs::DataPointValue;
using DPID = o2::dcs::DataPointIdentifier;
using DPVAL = o2::dcs::DataPointValue;
using DPMAP = std::unordered_map<DPID, std::vector<DPVAL>>;

/// @brief internal structure to define a time range
/// Internal structure to define a time range
struct TimeRange {
uint64_t begin = 0; ///< beginning of time range
uint64_t end = 0; ///< end of time range

TimeRange(uint64_t begin, uint64_t end) : begin(begin), end(end){}; // default constructor
/**
* Constructor of time range
* @param begin beginning of time range (ms)
* @param end end of time range (ms)
*/
TimeRange(uint64_t begin, uint64_t end) : begin(begin), end(end){};

/**
* @brief check if the time range contains the given time stamp
* @param timestamp time stamp of interest
* Check if the time range contains the given time stamp
* @param timestamp time stamp of interest (ms)
* @return true if the time stamp is in the time range
*/
bool contains(uint64_t timestamp) const { return timestamp >= begin && timestamp < end; }
Expand All @@ -69,9 +74,10 @@ class HVStatusCreator
using BADHVMAP = std::unordered_map<std::string, std::vector<TimeRange>>;

/**
* getter for the internal map of bad HV channels
* Getter for the internal map of HV issues
* @return map of bad HV channels with the time ranges concerned
*/
BADHVMAP getHVIssuesList();
const BADHVMAP& getBadHVs() const { return mBadHVTimeRanges; }

/**
* Find all HV issues and their time ranges
Expand All @@ -90,11 +96,9 @@ class HVStatusCreator
* Add channels affected by current HV issues to the status map
* @param statusMap statusMap to update
*/
void updateStatusMap(StatusMap& statusMap);
void updateStatusMap(StatusMap& statusMap) const;

/**
* clear the internal lists of HV issues
*/
/// Clear the internal lists of HV issues
void clear()
{
mBadHVTimeRanges.clear();
Expand All @@ -109,4 +113,4 @@ class HVStatusCreator

} // namespace o2::mch

#endif // O2_MCH_HV_STATUS_CREATOR_H_
#endif // O2_MCH_HV_STATUS_CREATOR_H_
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,15 @@ namespace o2::mch
*/
struct StatusMapCreatorParam : public o2::conf::ConfigurableParamHelper<StatusMapCreatorParam> {

bool useBadChannels = true; ///< reject bad channels (obtained during pedestal calibration runs)
bool useRejectList = true; ///< use extra rejection list (relative to other bad channels sources)
bool useHV = false; ///< reject channels connected to bad HV sectors
double hvLimits[10] = {1550., 1550., 1600., 1600., 1600., 1600., 1600., 1600., 1600., 1600.}; ///< chambers HV thresholds for detecting issues
uint64_t minDuration = 10 * 1000; ///< minimum duration of HV issues in ms
bool useBadChannels = true; ///< reject bad channels (obtained during pedestal calibration runs)
bool useRejectList = true; ///< use extra rejection list (relative to other bad channels sources)
bool useHV = true; ///< reject channels connected to bad HV sectors

/// chambers HV thresholds for detecting issues
double hvLimits[10] = {1550., 1550., 1600., 1600., 1600., 1600., 1600., 1600., 1600., 1600.};
uint64_t hvMinDuration = 10000; ///< minimum duration of HV issues in ms

uint64_t timeMargin = 2000; ///< time margin for comparing DCS and TF timestamps in ms

bool isActive() const { return useBadChannels || useRejectList || useHV; }

Expand Down
61 changes: 28 additions & 33 deletions Detectors/MUON/MCH/Status/src/HVStatusCreator.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@
#include "MCHStatus/StatusMap.h"
#include "MCHStatus/StatusMapCreatorParam.h"

using DPMAP2 = std::map<std::string, std::map<uint64_t, double>>;
using DPMAP2 = std::unordered_map<std::string, std::map<uint64_t, double>>;

// converts DCS data point value to double HV value
/// Converts DCS data point value to double HV value
double dpConverter(o2::dcs::DataPointValue v)
{
union Converter {
Expand All @@ -32,29 +32,28 @@ double dpConverter(o2::dcs::DataPointValue v)
return converter.value;
};

// decode the DCS DPMAP to be processed for HV issues
/// Decode the DCS DPMAP to be processed for HV issues
DPMAP2 decodeDPMAP(const o2::mch::HVStatusCreator::DPMAP& dpMap)
{
DPMAP2 dpsMapPerAlias;
DPMAP2 dpsMapPerAlias{};

auto timeMargin = o2::mch::StatusMapCreatorParam::Instance().timeMargin;

for (const auto& [dpId, dpsHV] : dpMap) {
std::string alias = dpId.get_alias();

if (alias.find("vMon") != std::string::npos) {
auto& dps2 = dpsMapPerAlias[alias];

// copy first point to the beginning of time
auto firstPoint = dpsHV.front();
dps2.emplace(0, dpConverter(firstPoint));
// copy first point to the beginning of time + margin (will be subtracted later on)
dps2.emplace(timeMargin, dpConverter(dpsHV.front()));

for (const auto& value : dpsHV) {
double valueConverted = dpConverter(value);
dps2.emplace(value.get_epoch_time(), valueConverted);
dps2.emplace(value.get_epoch_time(), dpConverter(value));
}

// copy last point to the end of time
auto lastPoint = dpsHV.back();
dps2.emplace(std::numeric_limits<uint64_t>::max(), dpConverter(lastPoint));
// copy last point to the end of time - margin (will be added later on)
dps2.emplace(std::numeric_limits<uint64_t>::max() - timeMargin, dpConverter(dpsHV.back()));
}
}

Expand All @@ -72,19 +71,21 @@ void HVStatusCreator::findBadHVs(const DPMAP& dpMap)
// decode the DCS DPMAP
DPMAP2 dpsMapPerAlias = decodeDPMAP(dpMap);

// Find list of HV issues per alias
auto minDuration = StatusMapCreatorParam::Instance().hvMinDuration;
auto timeMargin = StatusMapCreatorParam::Instance().timeMargin;

// find list of HV issues per alias
for (const auto& [alias, dpsHV] : dpsMapPerAlias) {
int chamber = o2::mch::dcs::toInt(o2::mch::dcs::aliasToChamber(alias));
auto chamberThreshold = StatusMapCreatorParam::Instance().hvLimits[chamber];
auto minDuration = StatusMapCreatorParam::Instance().minDuration;

std::vector<TimeRange> hvIssuesList;

uint64_t tStart, tStop = 0;
std::vector<TimeRange> hvIssuesList{};
uint64_t tStart = 0;
uint64_t tStop = 0;
bool ongoingIssue = false;

for (const auto& [timestamp, valueHV] : dpsHV) {
if (valueHV < chamberThreshold) { // check whether HV point is below set threshold for chamber
for (auto [timestamp, valueHV] : dpsHV) {
if (valueHV < chamberThreshold) {
if (!ongoingIssue) {
tStart = timestamp;
tStop = tStart;
Expand All @@ -95,18 +96,17 @@ void HVStatusCreator::findBadHVs(const DPMAP& dpMap)
} else {
if (ongoingIssue) {
tStop = timestamp;
if ((tStop - tStart) > minDuration) { // exclude issues less than set minimum duration parameter
TimeRange newIssue(tStart, tStop);
hvIssuesList.push_back(newIssue);
if (tStop - tStart > minDuration) {
hvIssuesList.emplace_back(tStart - timeMargin, tStop + timeMargin);
}
ongoingIssue = false;
}
}
}

// ongoing issue at the end of the object
if (ongoingIssue && ((tStop - tStart) > minDuration)) {
TimeRange newIssue(tStart, tStop);
hvIssuesList.push_back(newIssue);
if (ongoingIssue && tStop - tStart > minDuration) {
hvIssuesList.emplace_back(tStart - timeMargin, tStop + timeMargin);
}

// add issues for the alias if non-empty
Expand All @@ -122,7 +122,7 @@ bool HVStatusCreator::findCurrentBadHVs(uint64_t timestamp)
std::set<std::string> currentBadHVs{};
for (const auto& [alias, timeRanges] : mBadHVTimeRanges) {
auto it = std::find_if(timeRanges.begin(), timeRanges.end(),
[timestamp](const TimeRange& timeRange) { return timeRange.contains(timestamp); });
[timestamp](const TimeRange& r) { return r.contains(timestamp); });
if (it != timeRanges.end()) {
currentBadHVs.emplace(alias);
}
Expand All @@ -137,7 +137,7 @@ bool HVStatusCreator::findCurrentBadHVs(uint64_t timestamp)
return false;
}

void HVStatusCreator::updateStatusMap(StatusMap& statusMap)
void HVStatusCreator::updateStatusMap(StatusMap& statusMap) const
{
for (const auto& alias : mCurrentBadHVs) {
int deId = dcs::aliasToDetElemId(alias).value();
Expand All @@ -151,9 +151,4 @@ void HVStatusCreator::updateStatusMap(StatusMap& statusMap)
}
}

HVStatusCreator::BADHVMAP HVStatusCreator::getHVIssuesList()
{
return mBadHVTimeRanges;
}

} // namespace o2::mch
} // namespace o2::mch
84 changes: 66 additions & 18 deletions Detectors/MUON/MCH/Status/src/StatusMapCreatorSpec.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,11 @@

#include "MCHStatus/StatusMapCreatorSpec.h"

#include "CommonConstants/LHCConstants.h"
#include "DataFormatsMCH/DsChannelId.h"
#include "DetectorsBase/GRPGeomHelper.h"
#include "Framework/CCDBParamSpec.h"
#include "Framework/CallbackService.h"
#include "Framework/ConfigParamRegistry.h"
#include "Framework/ControlService.h"
#include "Framework/DataSpecUtils.h"
Expand All @@ -25,6 +28,7 @@
#include "MCHStatus/HVStatusCreator.h"
#include "MCHStatus/StatusMap.h"
#include "MCHStatus/StatusMapCreatorParam.h"
#include <chrono>
#include <fmt/format.h>
#include <functional>
#include <iostream>
Expand All @@ -50,27 +54,30 @@ size_t size(const StatusMap& sm)
class StatusMapCreatorTask
{
public:
StatusMapCreatorTask() = default;

void updateStatusMap()
{
mStatusMap.clear();
mStatusMap.add(mBadChannels, StatusMap::kBadPedestal);
mStatusMap.add(mRejectList, StatusMap::kRejectList);
mHVStatusCreator.updateStatusMap(mStatusMap);
mUpdateStatusMap = false;
}
StatusMapCreatorTask(bool useBadChannels, bool useRejectList, bool useHV,
std::shared_ptr<base::GRPGeomRequest> ggRequest)
: mUseBadChannels(useBadChannels),
mUseRejectList(useRejectList),
mUseHV(useHV),
mGGRequest(ggRequest) {}

void init(InitContext& ic)
{
mUseBadChannels = StatusMapCreatorParam::Instance().useBadChannels;
mUseRejectList = StatusMapCreatorParam::Instance().useRejectList;
mUseHV = StatusMapCreatorParam::Instance().useHV;
if (mGGRequest) {
base::GRPGeomHelper::instance().setRequest(mGGRequest);
}
mBadChannels.clear();
mRejectList.clear();
mHVStatusCreator.clear();
mStatusMap.clear();
mUpdateStatusMap = false;

auto stop = [this]() {
auto fullTime = mFindBadHVsTime + mFindCurrentBadHVsTime + mUpdateStatusTime;
LOGP(info, "duration: {:g} ms (findBadHVs: {:g} ms, findCurrentBadHVs: {:g} ms, updateStatusMap: {:g} ms)",
fullTime.count(), mFindBadHVsTime.count(), mFindCurrentBadHVsTime.count(), mUpdateStatusTime.count());
};
ic.services().get<CallbackService>().set<CallbackService::Id::Stop>(stop);
}

void finaliseCCDB(ConcreteDataMatcher& matcher, void* obj)
Expand All @@ -84,13 +91,21 @@ class StatusMapCreatorTask
mRejectList = *rl;
mUpdateStatusMap = true;
} else if (matcher == ConcreteDataMatcher("MCH", "HV", 0)) {
auto tStart = std::chrono::high_resolution_clock::now();
auto hv = static_cast<o2::mch::HVStatusCreator::DPMAP*>(obj);
mHVStatusCreator.findBadHVs(*hv);
mFindBadHVsTime += std::chrono::high_resolution_clock::now() - tStart;
} else if (mGGRequest) {
o2::base::GRPGeomHelper::instance().finaliseCCDB(matcher, obj);
}
}

void run(ProcessingContext& pc)
{
if (mGGRequest) {
o2::base::GRPGeomHelper::instance().checkUpdates(pc);
}

if (mUseBadChannels) {
// to trigger call to finaliseCCDB
pc.inputs().get<std::vector<o2::mch::DsChannelId>*>("badchannels");
Expand All @@ -106,10 +121,15 @@ class StatusMapCreatorTask
pc.inputs().get<o2::mch::HVStatusCreator::DPMAP*>("hv");

// check for update of bad HV channels
auto timestamp = pc.services().get<o2::framework::TimingInfo>().creation;
auto tStart = std::chrono::high_resolution_clock::now();
auto orbitReset = base::GRPGeomHelper::instance().getOrbitResetTimeMS();
auto firstTForbit = pc.services().get<o2::framework::TimingInfo>().firstTForbit;
auto timestamp = orbitReset + static_cast<uint64_t>(firstTForbit * constants::lhc::LHCOrbitMUS * 1.e-3);
if (mHVStatusCreator.findCurrentBadHVs(timestamp)) {
LOGP(info, "HV status updated at timestamp {}", timestamp);
mUpdateStatusMap = true;
}
mFindCurrentBadHVsTime += std::chrono::high_resolution_clock::now() - tStart;
}

// update the status map if needed
Expand All @@ -128,24 +148,52 @@ class StatusMapCreatorTask
bool mUseBadChannels{false};
bool mUseRejectList{false};
bool mUseHV{false};
std::shared_ptr<base::GRPGeomRequest> mGGRequest{};
std::vector<o2::mch::DsChannelId> mBadChannels{};
std::vector<o2::mch::DsChannelId> mRejectList{};
HVStatusCreator mHVStatusCreator{};
StatusMap mStatusMap{};
bool mUpdateStatusMap{false};
std::chrono::duration<double, std::milli> mFindBadHVsTime{};
std::chrono::duration<double, std::milli> mFindCurrentBadHVsTime{};
std::chrono::duration<double, std::milli> mUpdateStatusTime{};

void updateStatusMap()
{
auto tStart = std::chrono::high_resolution_clock::now();
mStatusMap.clear();
mStatusMap.add(mBadChannels, StatusMap::kBadPedestal);
mStatusMap.add(mRejectList, StatusMap::kRejectList);
mHVStatusCreator.updateStatusMap(mStatusMap);
mUpdateStatusMap = false;
mUpdateStatusTime += std::chrono::high_resolution_clock::now() - tStart;
}
};

framework::DataProcessorSpec getStatusMapCreatorSpec(std::string_view specName)
{
auto useBadChannels = StatusMapCreatorParam::Instance().useBadChannels;
auto useRejectList = StatusMapCreatorParam::Instance().useRejectList;
auto useHV = StatusMapCreatorParam::Instance().useHV;
std::shared_ptr<base::GRPGeomRequest> ggRequest{};

std::vector<InputSpec> inputs{};
if (StatusMapCreatorParam::Instance().useBadChannels) {
if (useBadChannels) {
inputs.emplace_back(InputSpec{"badchannels", "MCH", "BADCHANNELS", 0, Lifetime::Condition, ccdbParamSpec("MCH/Calib/BadChannel")});
}
if (StatusMapCreatorParam::Instance().useRejectList) {
if (useRejectList) {
inputs.emplace_back(InputSpec{"rejectlist", "MCH", "REJECTLIST", 0, Lifetime::Condition, ccdbParamSpec("MCH/Calib/RejectList")});
}
if (StatusMapCreatorParam::Instance().useHV) {
if (useHV) {
inputs.emplace_back(InputSpec{"hv", "MCH", "HV", 0, Lifetime::Condition, ccdbParamSpec("MCH/Calib/HV", {}, 1)}); // query every TF

ggRequest = std::make_shared<base::GRPGeomRequest>(true, // orbitResetTime
false, // GRPECS=true
false, // GRPLHCIF
false, // GRPMagField
false, // askMatLUT
base::GRPGeomRequest::None, // geometry
inputs);
}

std::vector<OutputSpec> outputs{};
Expand All @@ -168,7 +216,7 @@ framework::DataProcessorSpec getStatusMapCreatorSpec(std::string_view specName)
specName.data(),
inputs,
outputs,
AlgorithmSpec{adaptFromTask<StatusMapCreatorTask>()},
AlgorithmSpec{adaptFromTask<StatusMapCreatorTask>(useBadChannels, useRejectList, useHV, ggRequest)},
Options{}};
}
} // namespace o2::mch

0 comments on commit eee9f11

Please sign in to comment.