added none or 0 to unset bad channels (#632)

* added none or 0 to unset bad channels

* free function split to get int array from string of arguments for badchannels

* missed a file

* allowing list for badchannels in command line

* added badchannels in python

* added size check

* more comments in Detector.h and added more tests for facny command line badchannels

* removeDuplicates accept any container, added tests

* corner cases: 1:5,6,7 or 5,6,7 or just 1:5

Co-authored-by: Erik Frojdh <erik.frojdh@gmail.com>
This commit is contained in:
Dhanya Thattil
2023-01-27 09:59:31 +01:00
committed by GitHub
parent 3f7c9529dd
commit 9ba907f9f7
12 changed files with 231 additions and 66 deletions

View File

@ -221,6 +221,17 @@ class Detector {
*/
void setBadChannels(const std::string &fname, Positions pos = {});
/** [Gotthard2][Mythen3] */
Result<std::vector<int>> getBadChannels(Positions pos = {}) const;
/** [Gotthard2][Mythen3] Empty list resets bad channel list */
void setBadChannels(const std::vector<int> list, Positions pos = {});
/** [Gotthard2][Mythen3] Size of list should match number of modules. Each
* value is at module level and can start at 0. Empty vector resets bad
* channel list. */
void setBadChannels(const std::vector<std::vector<int>> list);
Result<bool> isVirtualDetectorServer(Positions pos = {}) const;
///@}

View File

@ -7,6 +7,7 @@
#include "sls/ToString.h"
#include "sls/bit_utils.h"
#include "sls/container_utils.h"
#include "sls/file_utils.h"
#include "sls/logger.h"
#include "sls/sls_detector_defs.h"
@ -548,9 +549,9 @@ std::string CmdProxy::BadChannels(int action) {
std::ostringstream os;
os << cmd << ' ';
if (action == defs::HELP_ACTION) {
os << "[fname]\n\t[Gotthard2][Mythen3] Sets the bad channels (from "
"file of bad channel numbers) to be masked out."
"\n\t[Mythen3] Also does trimming"
os << "[fname|none|0]\n\t[Gotthard2][Mythen3] Sets the bad channels "
"(from file of bad channel numbers) to be masked out. None or 0 "
"unsets all the badchannels.\n\t[Mythen3] Also does trimming"
<< '\n';
} else if (action == defs::GET_ACTION) {
if (args.size() != 1) {
@ -559,10 +560,25 @@ std::string CmdProxy::BadChannels(int action) {
det->getBadChannels(args[0], std::vector<int>{det_id});
os << "successfully retrieved" << '\n';
} else if (action == defs::PUT_ACTION) {
if (args.size() != 1) {
bool parse = false;
if (args.size() == 0) {
WrongNumberOfParameters(1);
} else if (args.size() == 1) {
if (args[0] == "none" || args[0] == "0") {
det->setBadChannels(std::vector<int>{},
std::vector<int>{det_id});
} else if (args[0].find(".") != std::string::npos) {
det->setBadChannels(args[0], std::vector<int>{det_id});
} else {
parse = true;
}
}
// parse multi args or single one with range or single value
if (parse || args.size() > 1) {
// get channels
auto list = getChannelsFromStringList(args);
det->setBadChannels(list, std::vector<int>{det_id});
}
det->setBadChannels(args[0], std::vector<int>{det_id});
os << "successfully loaded" << '\n';
} else {
throw RuntimeError("Unknown action");

View File

@ -349,6 +349,29 @@ void Detector::setBadChannels(const std::string &fname, Positions pos) {
pimpl->setBadChannels(fname, pos);
}
Result<std::vector<int>> Detector::getBadChannels(Positions pos) const {
return pimpl->Parallel(&Module::getBadChannels, pos);
}
void Detector::setBadChannels(const std::vector<std::vector<int>> list) {
if (list.size() != static_cast<size_t>(size())) {
std::stringstream ss;
ss << "Number of bad channel sets (" << list.size()
<< ") needs to match the number of modules (" << size() << ")";
throw RuntimeError(ss.str());
}
for (int idet = 0; idet < size(); ++idet) {
// TODO! Call in parallel since loading trimbits is slow?
pimpl->Parallel(&Module::setBadChannels, {idet}, list[idet]);
}
}
void Detector::setBadChannels(const std::vector<int> list, Positions pos) {
pimpl->setBadChannels(list, pos);
}
Result<bool> Detector::isVirtualDetectorServer(Positions pos) const {
return pimpl->Parallel(&Module::isVirtualDetectorServer, pos);
}

View File

@ -1778,6 +1778,10 @@ void DetectorImpl::setBadChannels(const std::string &fname, Positions pos) {
if (list.empty()) {
throw RuntimeError("Bad channel file is empty.");
}
setBadChannels(list, pos);
}
void DetectorImpl::setBadChannels(const std::vector<int> list, Positions pos) {
// update to multi values if multi modules
if (isAllPositions(pos)) {

View File

@ -84,7 +84,9 @@ class DetectorImpl : public virtual slsDetectorDefs {
*/
virtual ~DetectorImpl();
template <class CT> struct NonDeduced { using type = CT; };
template <class CT> struct NonDeduced {
using type = CT;
};
template <typename RT, typename... CT>
Result<RT> Parallel(RT (Module::*somefunc)(CT...),
std::vector<int> positions,
@ -306,6 +308,7 @@ class DetectorImpl : public virtual slsDetectorDefs {
void getBadChannels(const std::string &fname, Positions pos) const;
void setBadChannels(const std::string &fname, Positions pos);
void setBadChannels(const std::vector<int> list, Positions pos);
std::vector<std::string> getCtbDacNames() const;
std::string getCtbDacName(defs::dacIndex i) const;

View File

@ -644,6 +644,8 @@ TEST_CASE("badchannels", "[.cmd]") {
auto det_type = det.getDetectorType().squash();
if (det_type == defs::GOTTHARD2 || det_type == defs::MYTHEN3) {
auto prev = det.getBadChannels();
REQUIRE_THROWS(proxy.Call("badchannels", {}, -1, GET));
std::string fname_put =
@ -656,6 +658,51 @@ TEST_CASE("badchannels", "[.cmd]") {
std::vector<int> expected = {0, 12, 15, 40, 41, 42, 43, 44, 1279};
REQUIRE(list == expected);
REQUIRE_NOTHROW(proxy.Call("badchannels", {"none"}, 0, PUT));
REQUIRE_NOTHROW(proxy.Call("badchannels", {fname_get}, 0, GET));
list = getChannelsFromFile(fname_get);
REQUIRE(list.empty());
REQUIRE_NOTHROW(proxy.Call("badchannels", {fname_put}, 0, PUT));
REQUIRE_NOTHROW(proxy.Call("badchannels", {"0"}, 0, PUT));
REQUIRE_NOTHROW(proxy.Call("badchannels", {fname_get}, 0, GET));
list = getChannelsFromFile(fname_get);
REQUIRE(list.empty());
REQUIRE_NOTHROW(proxy.Call("badchannels", {"12"}, 0, PUT));
REQUIRE_NOTHROW(proxy.Call("badchannels", {fname_get}, 0, GET));
list = getChannelsFromFile(fname_get);
expected = {12};
REQUIRE(list == expected);
REQUIRE_NOTHROW(proxy.Call(
"badchannels", {"0", "12,", "15", "43", "40:45", "1279"}, 0, PUT));
REQUIRE_NOTHROW(proxy.Call("badchannels", {fname_get}, 0, GET));
list = getChannelsFromFile(fname_get);
expected = {0, 12, 15, 40, 41, 42, 43, 44, 1279};
REQUIRE(list == expected);
REQUIRE_NOTHROW(proxy.Call("badchannels", {"40:45"}, 0, PUT));
REQUIRE_NOTHROW(proxy.Call("badchannels", {fname_get}, 0, GET));
list = getChannelsFromFile(fname_get);
expected = {40, 41, 42, 43, 44};
REQUIRE(list == expected);
REQUIRE_NOTHROW(proxy.Call("badchannels", {"5,6,7"}, 0, PUT));
REQUIRE_NOTHROW(proxy.Call("badchannels", {fname_get}, 0, GET));
list = getChannelsFromFile(fname_get);
expected = {5, 6, 7};
REQUIRE(list == expected);
REQUIRE_NOTHROW(proxy.Call("badchannels", {"1:5,6,7"}, 0, PUT));
REQUIRE_NOTHROW(proxy.Call("badchannels", {fname_get}, 0, GET));
list = getChannelsFromFile(fname_get);
expected = {1, 2, 3, 4, 6, 7};
REQUIRE(list == expected);
det.setBadChannels(prev);
} else {
REQUIRE_THROWS(proxy.Call("badchannels", {}, -1, GET));
}