diff --git a/CMakeLists.txt b/CMakeLists.txt index 285e4a862..03e26d44b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -57,6 +57,7 @@ target_compile_options(slsProjectWarnings INTERFACE -Woverloaded-virtual -Wdouble-promotion -Wformat=2 + -Wshadow ) diff --git a/integrationTests/src/a.cpp b/integrationTests/src/a.cpp index af5cd3f13..ff02ffbe4 100644 --- a/integrationTests/src/a.cpp +++ b/integrationTests/src/a.cpp @@ -9,6 +9,7 @@ #include "sls_detector_defs.h" #include "sls_detector_exceptions.h" #include "sls_detector_funcs.h" +#include #include #include @@ -18,16 +19,59 @@ #include #include +#include + #include "network_utils.h" using namespace sls; +using ROI = slsDetectorDefs::ROI; + +// Easy printing of an ROI +std::ostream &operator<<(std::ostream &out, const ROI &r) { + return out << "xmin: " << std::setw(5) << r.xmin + << " xmax: " << std::setw(5) << r.xmax + << " ymin: " << std::setw(5) << r.ymin + << " ymax: " << std::setw(5) << r.ymax; +} int main() { - IpAddr a("129.129.205.242"); - IpAddr b(4073554305); + slsDetectorDefs::ROI roilimits[5]; + roilimits[0].xmin = 5; + roilimits[0].xmax = 12; + roilimits[0].ymin = 5; + roilimits[0].ymax = 15; - std::vector vec; - vec.push_back(a); - return 0; + roilimits[1].xmin = 0; + roilimits[1].xmax = 3; + roilimits[1].ymin = 20; + roilimits[1].ymax = 25; + + roilimits[2].xmin = 500; + roilimits[2].xmax = 600; + roilimits[2].ymin = 100; + roilimits[2].ymax = 200; + + roilimits[3].xmin = 300; + roilimits[3].xmax = 500; + roilimits[3].ymin = 800; + roilimits[3].ymax = 900; + + roilimits[4].xmin = 1000; + roilimits[4].xmax = 2000; + roilimits[4].ymin = 300; + roilimits[4].ymax = 500; + + std::cout << "Before sorting:\n"; + for (auto r : roilimits) { + std::cout << r << '\n'; + } + + std::sort(std::begin(roilimits), std::end(roilimits), + [](ROI a, ROI b) { return a.xmin < b.xmin; }); + + std::cout << "After sorting: \n"; + for (auto r : roilimits) { + std::cout << r << '\n'; + } } diff --git a/slsDetectorSoftware/include/multiSlsDetector.h b/slsDetectorSoftware/include/multiSlsDetector.h index ebccea081..c34ecd63e 100644 --- a/slsDetectorSoftware/include/multiSlsDetector.h +++ b/slsDetectorSoftware/include/multiSlsDetector.h @@ -5,6 +5,8 @@ #include "gitInfoLib.h" #include "logger.h" #include "sls_detector_defs.h" + + class slsDetector; class ZmqSocket; class detectorData; @@ -1283,7 +1285,7 @@ class multiSlsDetector : public virtual slsDetectorDefs { * @param detPos -1 for all detectors in list or specific detector position * @returns OK or FAIL */ - ROI *getROI(int &n, int detPos = -1); + const ROI *getROI(int &n, int detPos = -1); /** * Write to ADC register (Gotthard, Jungfrau, ChipTestBoard). For expert diff --git a/slsDetectorSoftware/include/slsDetector.h b/slsDetectorSoftware/include/slsDetector.h index 122f4bb72..96abd28c5 100644 --- a/slsDetectorSoftware/include/slsDetector.h +++ b/slsDetectorSoftware/include/slsDetector.h @@ -1134,7 +1134,7 @@ class slsDetector : public virtual slsDetectorDefs{ * @param n number of rois * @returns OK or FAIL */ - slsDetectorDefs::ROI *getROI(int &n); + const slsDetectorDefs::ROI * getROI(int &n); /** * Returns number of rois diff --git a/slsDetectorSoftware/include/slsDetectorUsers.h b/slsDetectorSoftware/include/slsDetectorUsers.h index 1aea31f81..7675bf113 100644 --- a/slsDetectorSoftware/include/slsDetectorUsers.h +++ b/slsDetectorSoftware/include/slsDetectorUsers.h @@ -545,7 +545,7 @@ public: * @param detPos -1 for all detectors in list or specific detector position * @returns pointer to array of ROI structure */ - slsDetectorDefs::ROI* getROI(int &n, int detPos = -1); + const slsDetectorDefs::ROI* getROI(int &n, int detPos = -1); diff --git a/slsDetectorSoftware/src/multiSlsDetector.cpp b/slsDetectorSoftware/src/multiSlsDetector.cpp index 430ab4a73..9b09d7b62 100644 --- a/slsDetectorSoftware/src/multiSlsDetector.cpp +++ b/slsDetectorSoftware/src/multiSlsDetector.cpp @@ -2278,13 +2278,14 @@ int multiSlsDetector::setROI(int n, ROI roiLimits[], int detPos) { // settings the rois for each detector std::vector r; - for (size_t idet = 0; idet < detectors.size(); ++idet) { - r.push_back(detectors[idet]->setROI(nroi[idet], allroi[idet])); + r.reserve(detectors.size()); + for (size_t i = 0; i != detectors.size(); ++i) { + r.push_back(detectors[i]->setROI(nroi[i], allroi[i])); } return sls::allEqualTo(r, static_cast(OK)) ? OK : FAIL; } -slsDetectorDefs::ROI *multiSlsDetector::getROI(int &n, int detPos) { +const slsDetectorDefs::ROI *multiSlsDetector::getROI(int &n, int detPos) { // single if (detPos >= 0) { return detectors[detPos]->getROI(n); @@ -2298,7 +2299,7 @@ slsDetectorDefs::ROI *multiSlsDetector::getROI(int &n, int detPos) { ROI temproi; ROI roiLimits[maxroi]; ROI *retval = new ROI[maxroi]; - ROI *temp = nullptr; + const ROI *temp = nullptr; int index = 0; // get each detector's roi array diff --git a/slsDetectorSoftware/src/slsDetector.cpp b/slsDetectorSoftware/src/slsDetector.cpp index bd9e3dcaa..8c4b78f8f 100644 --- a/slsDetectorSoftware/src/slsDetector.cpp +++ b/slsDetectorSoftware/src/slsDetector.cpp @@ -24,6 +24,8 @@ #include #include +#include + using namespace sls; #define DEFAULT_HOSTNAME "localhost" @@ -2497,8 +2499,7 @@ std::string slsDetector::getAdditionalJsonHeader() { std::string slsDetector::setAdditionalJsonParameter(const std::string &key, const std::string &value) { - // validation (value or key is empty) - if (!key.length() || !value.length()) { + if (key.empty() || value.empty()) { throw("Could not set additional json header parameter as the key or " "value is empty"); } @@ -2822,33 +2823,14 @@ int slsDetector::sendROIToProcessor() { } int slsDetector::setROI(int n, ROI roiLimits[]) { - // sort ascending order - for (int i = 0; i < n; ++i) { - for (int j = i + 1; j < n; ++j) { - if (roiLimits[j].xmin < roiLimits[i].xmin) { - int temp = roiLimits[i].xmin; - roiLimits[i].xmin = roiLimits[j].xmin; - roiLimits[j].xmin = temp; - temp = roiLimits[i].xmax; - roiLimits[i].xmax = roiLimits[j].xmax; - roiLimits[j].xmax = temp; - temp = roiLimits[i].ymin; - roiLimits[i].ymin = roiLimits[j].ymin; - roiLimits[j].ymin = temp; - temp = roiLimits[i].ymax; - roiLimits[i].ymax = roiLimits[j].ymax; - roiLimits[j].ymax = temp; - } - } - } + std::sort(roiLimits, roiLimits+n, + [](ROI a, ROI b) { return a.xmin < b.xmin; }); int ret = sendROI(n, roiLimits); - // moench (send to processor) if (detector_shm()->myDetectorType == MOENCH) { sendROIToProcessor(); } // update #nchans and databytes, as it depends on #samples, roi, - // readoutflags (ctb only) if (detector_shm()->myDetectorType == CHIPTESTBOARD || detector_shm()->myDetectorType == MOENCH) { updateTotalNumberOfChannels(); @@ -2856,7 +2838,7 @@ int slsDetector::setROI(int n, ROI roiLimits[]) { return ret; } -slsDetectorDefs::ROI *slsDetector::getROI(int &n) { +const slsDetectorDefs::ROI * slsDetector::getROI(int &n) { sendROI(-1, nullptr); n = detector_shm()->nROI; // moench - get json header(due to different clients, diff shm) (get roi is @@ -2924,6 +2906,15 @@ int slsDetector::sendROI(int n, ROI roiLimits[]) { << "," << detector_shm()->roiLimits[i].ymax << ")"; } } + }else{ + //detector is offline lets just update SHM + if (n!=-1){ + detector_shm()->nROI = n; + for(int i = 0; i!=n; ++i){ + detector_shm()->roiLimits[i] = roiLimits[i]; + } + } + } if (ret == FORCE_UPDATE) { ret = updateDetector(); diff --git a/slsDetectorSoftware/src/slsDetectorCommand.cpp b/slsDetectorSoftware/src/slsDetectorCommand.cpp index 201b15d20..1c10d8a87 100644 --- a/slsDetectorSoftware/src/slsDetectorCommand.cpp +++ b/slsDetectorSoftware/src/slsDetectorCommand.cpp @@ -3384,7 +3384,7 @@ std::string slsDetectorCommand::cmdDetectorSize(int narg, char *args[], int acti myDet->setReceiverOnline(ONLINE_FLAG, detPos); ret = myDet->setDynamicRange(val, detPos); } else if (cmd == "roi") { - ROI* r = myDet->getROI(ret, detPos); + const ROI* r = myDet->getROI(ret, detPos); if (r != NULL) delete [] r; } else if (cmd == "detsizechan") { @@ -4663,7 +4663,7 @@ std::string slsDetectorCommand::helpSpeed(int action) { std::string slsDetectorCommand::cmdAdvanced(int narg, char *args[], int action, int detPos) { - int retval; + char answer[1000] = ""; if (action == HELP_ACTION) @@ -4702,7 +4702,7 @@ std::string slsDetectorCommand::cmdAdvanced(int narg, char *args[], int action, } myDet->setOnline(ONLINE_FLAG, detPos); - retval = myDet->setReadOutFlags(flag, detPos); + int retval = myDet->setReadOutFlags(flag, detPos); // std::cout << std::hex << flag << " " << retval << std::endl; @@ -5074,7 +5074,6 @@ std::string slsDetectorCommand::cmdReceiver(int narg, char *args[], int action, } else return std::string("could not scan max frames per file\n"); } - char answer[100]; memset(answer, 0, 100); sprintf(answer, "%d", myDet->setReceiverFramesPerFile(-1, detPos)); return std::string(answer); @@ -5097,7 +5096,6 @@ std::string slsDetectorCommand::cmdReceiver(int narg, char *args[], int action, } else return std::string("could not scan receiver padding enable\n"); } - char answer[100]; memset(answer, 0, 100); sprintf(answer, "%d", myDet->setReceiverPartialFramesPadding(-1, detPos)); return std::string(answer); @@ -5636,7 +5634,7 @@ std::string slsDetectorCommand::cmdPattern(int narg, char *args[], int action, i // myDet->writeRegister(120,addr, detPos); } - ROI *aa = myDet->getROI(nroi, detPos); + const ROI *aa = myDet->getROI(nroi, detPos); int reg = 0xffffffff; if (nroi < 1) diff --git a/slsDetectorSoftware/src/slsDetectorUsers.cpp b/slsDetectorSoftware/src/slsDetectorUsers.cpp index d1a5b4b1f..68464c93c 100644 --- a/slsDetectorSoftware/src/slsDetectorUsers.cpp +++ b/slsDetectorSoftware/src/slsDetectorUsers.cpp @@ -236,7 +236,7 @@ int slsDetectorUsers::setROI(int n, slsDetectorDefs::ROI roiLimits[], int detPos return detector.setROI(n, roiLimits, detPos); } -slsDetectorDefs::ROI* slsDetectorUsers::getROI(int &n, int detPos) { +const slsDetectorDefs::ROI* slsDetectorUsers::getROI(int &n, int detPos) { return detector.getROI(n, detPos); } diff --git a/slsDetectorSoftware/tests/test-slsDetector.cpp b/slsDetectorSoftware/tests/test-slsDetector.cpp index 77ad83637..d8f54414b 100644 --- a/slsDetectorSoftware/tests/test-slsDetector.cpp +++ b/slsDetectorSoftware/tests/test-slsDetector.cpp @@ -2,14 +2,13 @@ #include "catch.hpp" #include "container_utils.h" #include "slsDetector.h" +#include "sls_detector_defs.h" #include "string_utils.h" - +#include #include using namespace sls; - - TEST_CASE("Set and get trimen", "[detector]") { // Free shared memory to be sure that we start in a clean state slsDetector::freeSharedMemory(0, 0); @@ -31,8 +30,6 @@ TEST_CASE("Set and get trimen", "[detector]") { for (size_t i = 0; i != res2.size(); ++i) CHECK(res2[i] == energies[i]); - - // Setting trimen with too many vales throws an exception and keeps the // old values std::vector too_many(150, 1000); @@ -49,3 +46,134 @@ TEST_CASE("Set and get trimen", "[detector]") { // Clean up before next test d.freeSharedMemory(); } + +TEST_CASE("Set additional JSON header", "[detector]") { + slsDetector::freeSharedMemory(0, 0); + slsDetector d(slsDetectorDefs::detectorType::EIGER, 0, 0); + auto header = d.getAdditionalJsonHeader(); + CHECK(header.empty()); + + // The header set is not validated + d.setAdditionalJsonHeader("any header"); + header = d.getAdditionalJsonHeader(); + CHECK(header == "any header"); + + // make sure reset works + d.setAdditionalJsonHeader(""); + CHECK(d.getAdditionalJsonHeader().empty()); + + // Setting and getting one parameter + d.setAdditionalJsonParameter("exptime", "5"); + CHECK(d.getAdditionalJsonParameter("exptime") == "5"); + CHECK(d.getAdditionalJsonHeader() == "\"exptime\":5"); + + // Making sure setting another paramer does not mess up + // the first + d.setAdditionalJsonParameter("gain", "low"); + CHECK(d.getAdditionalJsonParameter("exptime") == "5"); + CHECK(d.getAdditionalJsonParameter("gain") == "low"); + CHECK(d.getAdditionalJsonHeader() == "\"exptime\":5,\"gain\":\"low\""); + + // Change a value + d.setAdditionalJsonParameter("exptime", "90"); + CHECK(d.getAdditionalJsonParameter("exptime") == "90"); + CHECK(d.getAdditionalJsonHeader() == "\"exptime\":90,\"gain\":\"low\""); + + // Ask for a key that does not exists + // TODO!(Erik) Is an empty string the right return or should we throw + CHECK(d.getAdditionalJsonParameter("somerandomkey").empty()); + + // Throws if value or key is empty + CHECK_THROWS(d.setAdditionalJsonParameter("somekey", "")); + CHECK_THROWS(d.setAdditionalJsonParameter("", "parameter")); + CHECK_THROWS(d.setAdditionalJsonParameter("", "")); + + // Throws if key or value has illegal char + CHECK_THROWS(d.setAdditionalJsonParameter("mykey,", "5")); + CHECK_THROWS(d.setAdditionalJsonParameter("some:key", "9")); + CHECK_THROWS(d.setAdditionalJsonParameter("some\"key", "1")); + CHECK_THROWS(d.setAdditionalJsonParameter("key", "value:")); + CHECK_THROWS(d.setAdditionalJsonParameter("key", "va,lue")); + CHECK_THROWS(d.setAdditionalJsonParameter("key", "va\"l\"ue")); + + d.freeSharedMemory(); +} + +TEST_CASE("Set ROI", "[detector]") { + using ROI = slsDetectorDefs::ROI; + + slsDetector::freeSharedMemory(0, 0); + slsDetector d(slsDetectorDefs::detectorType::EIGER, 0, 0); + + int n{0}; + auto res = d.getROI(n); + // CHECK(n == 0); + CHECK(d.getNRoi() == 0); + + // set one ROI + ROI r; + r.xmin = 5; + r.xmax = 100; + r.ymin = 10; + r.ymax = 300; + d.setROI(1, &r); + + auto res2 = d.getROI(n); + CHECK(n == 1); + CHECK(d.getNRoi() == 1); + + CHECK(res2->xmin == 5); + CHECK(res2->xmax == 100); + CHECK(res2->ymin == 10); + CHECK(res2->ymax == 300); + + d.freeSharedMemory(); +} + +TEST_CASE("Set multiple ROIs", "[detector]") { + using ROI = slsDetectorDefs::ROI; + + slsDetector::freeSharedMemory(0, 0); + slsDetector d(slsDetectorDefs::detectorType::EIGER, 0, 0); + + // set one ROI + constexpr int n = 3; + ROI r[n]; + r[0].xmin = 500; + r[0].xmax = 60000; + r[0].ymin = 100; + r[0].ymax = 800; + + r[1].xmin = 2; + r[1].xmax = 100; + r[1].ymin = 1; + r[1].ymax = 300; + + r[2].xmin = 200; + r[2].xmax = 300; + r[2].ymin = 15; + r[2].ymax = 307; + d.setROI(n, r); + + int n_roi{0}; + auto res = d.getROI(n_roi); + CHECK(n_roi == n); + CHECK(d.getNRoi() == n); + + CHECK(res[0].xmin == 2); + CHECK(res[0].xmax == 100); + CHECK(res[0].ymin == 1); + CHECK(res[0].ymax == 300); + + CHECK(res[1].xmin == 200); + CHECK(res[1].xmax == 300); + CHECK(res[1].ymin == 15); + CHECK(res[1].ymax == 307); + + CHECK(res[2].xmin == 500); + CHECK(res[2].xmax == 60000); + CHECK(res[2].ymin == 100); + CHECK(res[2].ymax == 800); + + d.freeSharedMemory(); +} \ No newline at end of file