added parallel and container3

This commit is contained in:
Erik Frojdh
2020-04-27 15:20:13 +02:00
parent 4f712fcd70
commit d66df844e5
11 changed files with 1245 additions and 878 deletions

View File

@ -0,0 +1,157 @@
#pragma once
#include <array>
#include <cstddef>
#include <iostream>
#include <numeric>
namespace sls{
template <typename T> class Container3 {
std::array<size_t, 3> shape_{0, 0, 0};
T *data_{nullptr};
public:
Container3(){};
Container3(std::array<size_t, 3> shape)
: Container3(shape[0], shape[1], shape[2]) {}
Container3(std::array<size_t, 3> shape, T value)
: Container3(shape[0], shape[1], shape[2], value) {}
Container3(size_t x, size_t y, size_t z)
: shape_{x, y, z}, data_(new T[size()]{}) {}
Container3(size_t x, size_t y, size_t z, const T &value)
: shape_{x, y, z}, data_(new T[size()]) {
std::fill_n(data_, size(), value);
}
// Copy constructor
Container3(const Container3 &other) {
shape_ = other.shape_;
data_ = new T[size()];
std::copy(other.data_, other.data_ + size(), data_);
}
// Move constructor
Container3(Container3 &&other) {
shape_ = other.shape_;
other.shape_ = {0, 0, 0};
data_ = other.data_;
other.data_ = nullptr;
}
// Copy assignment
Container3 &operator=(const Container3 &other) {
if (this != &other) {
Container3<T> tmp(other);
std::swap(shape_, tmp.shape_);
std::swap(data_, tmp.data_);
}
return *this;
}
// Move assignment
Container3 &operator=(Container3 &&other) {
if (this != &other) {
shape_ = other.shape_;
other.shape_ = {0, 0, 0};
delete[] data_;
data_ = other.data_;
other.data_ = nullptr;
}
return *this;
}
~Container3() { delete[] data_; }
size_t size() const noexcept {
return std::accumulate(std::begin(shape_), std::end(shape_), 1,
std::multiplies<size_t>());
}
size_t size(size_t i) const noexcept { return shape_[i]; }
std::array<size_t, 3> shape() const noexcept { return shape_; }
T *data() noexcept { return data_; }
const T *data() const noexcept { return data_; }
bool is_valid_index(size_t x, size_t y, size_t z) const noexcept {
return x < shape_[0] && y < shape_[1] && z < shape_[2];
}
// Will truncate if other is larger in any dimension
// In the future move object out of other, rename function
void copy_data(const Container3 &other) {
for (size_t i = 0; i < std::min(size(0), other.size(0)); ++i) {
for (size_t j = 0; j < std::min(size(1), other.size(1)); ++j) {
for (size_t k = 0; k < std::min(size(2), other.size(2)); ++k) {
(*this)(i, j, k) = other(i, j, k);
}
}
}
}
void move_data(Container3 &other) {
for (size_t i = 0; i < std::min(size(0), other.size(0)); ++i) {
for (size_t j = 0; j < std::min(size(1), other.size(1)); ++j) {
for (size_t k = 0; k < std::min(size(2), other.size(2)); ++k) {
(*this)(i, j, k) = std::move(other(i, j, k));
}
}
}
}
void resize(size_t x, size_t y, size_t z) {
Container3<T> tmp(x, y, z);
tmp.move_data(*this);
*this = std::move(tmp);
}
T &operator()(size_t x, size_t y, size_t z) noexcept {
return data_[element_offset(x, y, z)];
}
const T &operator()(size_t x, size_t y, size_t z) const noexcept {
return data_[element_offset(x, y, z)];
}
// throws on out of bounds access
const T &at(size_t x, size_t y, size_t z) const {
if (!is_valid_index(x, y, z))
throw std::runtime_error("Index error");
return data_[element_offset(x, y, z)];
}
T &at(size_t x, size_t y, size_t z) {
return const_cast<T &>(
static_cast<const Container3 &>(*this).at(x, y, z));
}
T &operator[](size_t i) { return data_[i]; }
const T &operator[](size_t i) const { return data_[i]; }
T *begin() { return data_; }
T *end() { return data_ + size(); }
void clear(){
*this = Container3<T>();
}
// reference to position, grow if needed, prefer resize and .at()
T &at_can_grow(size_t x, size_t y, size_t z) {
if (!is_valid_index(x, y, z)) {
resize(std::max(x + 1, size(0)), std::max(y + 1, size(1)),
std::max(z + 1, size(2)));
}
return data_[element_offset(x, y, z)];
}
private:
size_t element_offset(size_t x, size_t y, size_t z) const noexcept {
return x * shape_[1] * shape_[2] + y * shape_[2] + z;
}
};
} // namespace sls

View File

@ -1,11 +1,11 @@
#include "DetectorImpl.h" #include "DetectorImpl.h"
#include "Module.h"
#include "Receiver.h"
#include "SharedMemory.h" #include "SharedMemory.h"
#include "ZmqSocket.h" #include "ZmqSocket.h"
#include "detectorData.h" #include "detectorData.h"
#include "file_utils.h" #include "file_utils.h"
#include "logger.h" #include "logger.h"
#include "Module.h"
#include "Receiver.h"
#include "sls_detector_exceptions.h" #include "sls_detector_exceptions.h"
#include "versionAPI.h" #include "versionAPI.h"
@ -27,7 +27,7 @@
#include <future> #include <future>
#include <vector> #include <vector>
namespace sls{ namespace sls {
DetectorImpl::DetectorImpl(int detector_id, bool verify, bool update) DetectorImpl::DetectorImpl(int detector_id, bool verify, bool update)
: detectorId(detector_id), detector_shm(detector_id, -1) { : detectorId(detector_id), detector_shm(detector_id, -1) {
@ -63,8 +63,10 @@ void DetectorImpl::freeSharedMemory(int detectorId, int moduleId) {
} }
moduleShm.RemoveSharedMemory(); moduleShm.RemoveSharedMemory();
} }
for (int iReceiver = 0; iReceiver < numReceivers + numReceivers2; ++iReceiver) { for (int iReceiver = 0; iReceiver < numReceivers + numReceivers2;
SharedMemory<sharedModule> receiverShm(detectorId, moduleId, iReceiver); ++iReceiver) {
SharedMemory<sharedModule> receiverShm(detectorId, moduleId,
iReceiver);
if (receiverShm.IsExisting()) { if (receiverShm.IsExisting()) {
receiverShm.RemoveSharedMemory(); receiverShm.RemoveSharedMemory();
} }
@ -93,8 +95,10 @@ void DetectorImpl::freeSharedMemory(int detectorId, int moduleId) {
} }
moduleShm.RemoveSharedMemory(); moduleShm.RemoveSharedMemory();
} }
for (int iReceiver = 0; iReceiver < numReceivers + numReceivers2; ++iReceiver) { for (int iReceiver = 0; iReceiver < numReceivers + numReceivers2;
SharedMemory<sharedModule> receiverShm(detectorId, iModule, iReceiver); ++iReceiver) {
SharedMemory<sharedModule> receiverShm(detectorId, iModule,
iReceiver);
if (receiverShm.IsExisting()) { if (receiverShm.IsExisting()) {
receiverShm.RemoveSharedMemory(); receiverShm.RemoveSharedMemory();
} }
@ -108,10 +112,8 @@ void DetectorImpl::freeSharedMemory() {
d->freeSharedMemory(); d->freeSharedMemory();
} }
detectors.clear(); detectors.clear();
for (auto &dr : receivers) { for (auto &r : receivers) {
for (auto &r : dr) { r->freeSharedMemory();
r->freeSharedMemory();
}
} }
receivers.clear(); receivers.clear();
for (auto &dr : receivers2) { for (auto &dr : receivers2) {
@ -175,11 +177,11 @@ void DetectorImpl::initSharedMemory(bool verify) {
detector_shm.OpenSharedMemory(); detector_shm.OpenSharedMemory();
if (verify && detector_shm()->shmversion != DETECTOR_SHMVERSION) { if (verify && detector_shm()->shmversion != DETECTOR_SHMVERSION) {
LOG(logERROR) << "Detector shared memory (" << detectorId LOG(logERROR) << "Detector shared memory (" << detectorId
<< ") version mismatch " << ") version mismatch "
"(expected 0x" "(expected 0x"
<< std::hex << DETECTOR_SHMVERSION << " but got 0x" << std::hex << DETECTOR_SHMVERSION << " but got 0x"
<< detector_shm()->shmversion << std::dec << detector_shm()->shmversion << std::dec
<< ". Clear Shared memory to continue."; << ". Clear Shared memory to continue.";
throw SharedMemoryError("Shared memory version mismatch!"); throw SharedMemoryError("Shared memory version mismatch!");
} }
} }
@ -207,23 +209,28 @@ void DetectorImpl::initializeMembers(bool verify) {
try { try {
for (int iModule = 0; iModule < numModules; ++iModule) { for (int iModule = 0; iModule < numModules; ++iModule) {
detectors.push_back( detectors.push_back(
sls::make_unique<Module>(detectorId, iModule, verify)); sls::make_unique<Module>(detectorId, iModule, verify));
int numReceivers = detectors[iModule]->getNumberOfReceivers(); int numReceivers = detectors[iModule]->getNumberOfReceivers();
if (numReceivers != 0) { if (numReceivers != 0) {
receivers.resize(numModules); receivers.resize(numModules, 1, numReceivers);
for (int iReceiver = 0; iReceiver < numReceivers; ++iReceiver) { for (int iReceiver = 0; iReceiver < numReceivers; ++iReceiver) {
receivers[iModule].push_back( receivers(iModule, 0, iReceiver) =
sls::make_unique<Receiver>(detectorId, iModule, 0, sls::make_unique<Receiver>(detectorId, iModule, 0,
iReceiver, verify)); iReceiver, verify);
} }
} }
int numReceivers2 = detectors[iModule]->getNumberOfReceivers2(); int numReceivers2 = detectors[iModule]->getNumberOfReceivers2();
if (numReceivers2 != 0) { if (numReceivers2 != 0) {
receivers2.resize(numModules); if (numReceivers2 != numReceivers) {
for (int iReceiver = 0; iReceiver < numReceivers2; ++iReceiver) { throw sls::RuntimeError("Mismatch in number of receivers");
receivers2[iModule].push_back( }
sls::make_unique<Receiver>(detectorId, iModule, 1, receivers.resize(numModules, 2, numReceivers2);
iReceiver, verify)); for (int iReceiver = 0; iReceiver < numReceivers2;
++iReceiver) {
receivers(iModule, 1, iReceiver) =
sls::make_unique<Receiver>(detectorId, iModule, 1,
iReceiver, verify);
} }
} }
} }
@ -233,7 +240,7 @@ void DetectorImpl::initializeMembers(bool verify) {
receivers2.clear(); receivers2.clear();
throw; throw;
} }
} } // namespace sls
void DetectorImpl::updateUserdetails() { void DetectorImpl::updateUserdetails() {
detector_shm()->lastPID = getpid(); detector_shm()->lastPID = getpid();
@ -293,9 +300,8 @@ void DetectorImpl::setVirtualDetectorServers(const int numdet, const int port) {
void DetectorImpl::setHostname(const std::vector<std::string> &name) { void DetectorImpl::setHostname(const std::vector<std::string> &name) {
// this check is there only to allow the previous detsizechan command // this check is there only to allow the previous detsizechan command
if (detector_shm()->numberOfModules != 0) { if (detector_shm()->numberOfModules != 0) {
LOG(logWARNING) LOG(logWARNING) << "There are already detector(s) in shared memory."
<< "There are already detector(s) in shared memory." "Freeing Shared memory now.";
"Freeing Shared memory now.";
bool initialChecks = detector_shm()->initialChecks; bool initialChecks = detector_shm()->initialChecks;
freeSharedMemory(); freeSharedMemory();
setupDetector(); setupDetector();
@ -308,15 +314,15 @@ void DetectorImpl::setHostname(const std::vector<std::string> &name) {
} }
void DetectorImpl::setHostname(const std::vector<std::string> &name, void DetectorImpl::setHostname(const std::vector<std::string> &name,
const std::vector<int> &port) { const std::vector<int> &port) {
if (name.size() != port.size()) { if (name.size() != port.size()) {
throw RuntimeError("hostname vector size and port vector size do not match"); throw RuntimeError(
"hostname vector size and port vector size do not match");
} }
// this check is there only to allow the previous detsizechan command // this check is there only to allow the previous detsizechan command
if (detector_shm()->numberOfModules != 0) { if (detector_shm()->numberOfModules != 0) {
LOG(logWARNING) LOG(logWARNING) << "There are already detector(s) in shared memory."
<< "There are already detector(s) in shared memory." "Freeing Shared memory now.";
"Freeing Shared memory now.";
bool initialChecks = detector_shm()->initialChecks; bool initialChecks = detector_shm()->initialChecks;
freeSharedMemory(); freeSharedMemory();
setupDetector(); setupDetector();
@ -328,8 +334,7 @@ void DetectorImpl::setHostname(const std::vector<std::string> &name,
updateDetectorSize(); updateDetectorSize();
} }
void DetectorImpl::addModule(const std::string &hostname, void DetectorImpl::addModule(const std::string &hostname, const int port) {
const int port) {
LOG(logINFO) << "Adding detector " << hostname << " on port " << port; LOG(logINFO) << "Adding detector " << hostname << " on port " << port;
if (hostname != "localhost") { if (hostname != "localhost") {
@ -362,128 +367,120 @@ void DetectorImpl::addModule(const std::string &hostname,
} }
int DetectorImpl::getNumberofReceiversPerModule() const { int DetectorImpl::getNumberofReceiversPerModule() const {
int retval = receivers.size(); return receivers.size(1) * receivers.size(2);
if (receivers2.size()) {
retval *= 2;
}
// for round robin
if (retval) {
retval *= receivers[0].size();
}
return retval;
} }
void DetectorImpl::initReceiver(const int udpInterface) { void DetectorImpl::initReceiver(const int udpInterface) {
if (udpInterface == 1) { // if (udpInterface == 1) {
if (receivers.size() != 0) { // if (receivers.size() != 0) {
throw RuntimeError("receiver vector already initialized"); // throw RuntimeError("receiver vector already initialized");
} // }
int tcpPort = DEFAULT_RX_PORTNO; // int tcpPort = DEFAULT_RX_PORTNO;
int zmqPort = DEFAULT_ZMQ_CL_PORTNO; // int zmqPort = DEFAULT_ZMQ_CL_PORTNO;
try { // try {
for (int iModule = 0; iModule < size(); ++iModule) { // for (int iModule = 0; iModule < size(); ++iModule) {
receivers.resize(detectors.size()); // receivers.resize(detectors.size());
receivers[iModule].push_back( // receivers[iModule].push_back(
sls::make_unique<Receiver>(detectorId, iModule, 0, // sls::make_unique<Receiver>(detectorId, iModule, 0,
0, tcpPort++, "", zmqPort++)); // 0, tcpPort++, "", zmqPort++));
detectors[iModule]->setNumberOfReceivers(1); // detectors[iModule]->setNumberOfReceivers(1);
} // }
} catch (...) { // } catch (...) {
receivers.clear(); // receivers.clear();
throw; // throw;
} // }
} else if (udpInterface == 2) { // } else if (udpInterface == 2) {
if (receivers2.size() != 0) { // if (receivers2.size() != 0) {
throw RuntimeError("receiver2 vector already initialized"); // throw RuntimeError("receiver2 vector already initialized");
} // }
int tcpPort = DEFAULT_RX_PORTNO + size(); // int tcpPort = DEFAULT_RX_PORTNO + size();
int zmqPort = DEFAULT_ZMQ_CL_PORTNO + size(); // int zmqPort = DEFAULT_ZMQ_CL_PORTNO + size();
try { // try {
for (int iModule = 0; iModule < size(); ++iModule) { // for (int iModule = 0; iModule < size(); ++iModule) {
receivers2.resize(detectors.size()); // receivers2.resize(detectors.size());
receivers2[iModule].push_back( // receivers2[iModule].push_back(
sls::make_unique<Receiver>(detectorId, iModule, 1, // sls::make_unique<Receiver>(detectorId, iModule, 1,
0, tcpPort++, "", zmqPort++)); // 0, tcpPort++, "", zmqPort++));
detectors[iModule]->setNumberOfReceivers2(1); // detectors[iModule]->setNumberOfReceivers2(1);
} // }
} catch (...) { // } catch (...) {
receivers2.clear(); // receivers2.clear();
throw; // throw;
} // }
} else { // } else {
throw RuntimeError("Invalid udp interface number " + // throw RuntimeError("Invalid udp interface number " +
std::to_string(udpInterface)); // std::to_string(udpInterface));
} // }
} }
bool DetectorImpl::isReceiverInitialized(const int udpInterface) { bool DetectorImpl::isReceiverInitialized(const int udpInterface) {
switch (udpInterface) { switch (udpInterface) {
case 1: case 1:
return (receivers.size() > 0); return (receivers.size() > 0);
case 2: case 2:
return (receivers2.size() > 0); return (receivers2.size() > 0);
default: default:
throw RuntimeError("Invalid udp interface number " + throw RuntimeError("Invalid udp interface number " +
std::to_string(udpInterface)); std::to_string(udpInterface));
} }
} }
void DetectorImpl::removeReceivers(const int udpInterface) { void DetectorImpl::removeReceivers(const int udpInterface) {
if (udpInterface == 1) { if (udpInterface == 1) {
for (auto & dr: receivers) { for (auto &r : receivers) {
for (auto & r : dr) { r->freeSharedMemory();
r->freeSharedMemory();
}
} }
receivers.clear(); receivers.clear();
} else if (udpInterface == 2) { } else if (udpInterface == 2) {
for (auto & dr: receivers2) { for (auto &dr : receivers2) {
for (auto & r : dr) { for (auto &r : dr) {
r->freeSharedMemory(); r->freeSharedMemory();
} }
} }
receivers2.clear(); receivers2.clear();
} else { } else {
throw RuntimeError("Invalid udp interface number " + throw RuntimeError("Invalid udp interface number " +
std::to_string(udpInterface)); std::to_string(udpInterface));
} }
} }
void DetectorImpl::configureReceiver(const int udpInterface, Positions pos, void DetectorImpl::configureReceiver(const int udpInterface, Positions pos,
const std::string &hostname) { const std::string &hostname) {
if (Parallel(&Module::getRunStatus, pos).squash(defs::ERROR) == defs::RUNNING) { // if (Parallel(&Module::getRunStatus, pos).squash(defs::ERROR) ==
LOG(logWARNING) << "Acquisition already running, Stopping it."; // defs::RUNNING) {
Parallel(&Module::stopAcquisition, {}); // LOG(logWARNING) << "Acquisition already running, Stopping it.";
} // Parallel(&Module::stopAcquisition, {});
if (!isReceiverInitialized(udpInterface)) { // }
initReceiver(udpInterface); // if (!isReceiverInitialized(udpInterface)) {
} // initReceiver(udpInterface);
auto t = Parallel(&Module::getReceiverParameters, pos); // }
if (udpInterface == 1) { // auto t = Parallel(&Module::getReceiverParameters, pos);
Parallel1(&Receiver::setHostname, pos, {}, hostname); // if (udpInterface == 1) {
for (int iMod = 0; iMod < size(); ++iMod) { // Parallel1(&Receiver::setHostname, pos, {}, hostname);
auto m = receivers[iMod][0]->configure(t[iMod]); // for (int iMod = 0; iMod < size(); ++iMod) {
if (m != 0) { // auto m = receivers[iMod][0]->configure(t[iMod]);
detectors[iMod]->setDestinationUDPMAC(m); // if (m != 0) {
} // detectors[iMod]->setDestinationUDPMAC(m);
} // }
} else { // }
Parallel2(&Receiver::setHostname, pos, {}, hostname); // } else {
for (int iMod = 0; iMod < size(); ++iMod) { // Parallel2(&Receiver::setHostname, pos, {}, hostname);
auto m = receivers2[iMod][0]->configure(t[iMod]); // for (int iMod = 0; iMod < size(); ++iMod) {
if (m != 0) { // auto m = receivers2[iMod][0]->configure(t[iMod]);
detectors[iMod]->setDestinationUDPMAC2(m); // if (m != 0) {
} // detectors[iMod]->setDestinationUDPMAC2(m);
} // }
} // }
// }
} }
void DetectorImpl::configureReceiver(const int udpInterface, int module_id, void DetectorImpl::configureReceiver(const int udpInterface, int module_id,
const std::string &hostname, const int port) { const std::string &hostname,
const int port) {
if (Parallel(&Module::getRunStatus, {}).squash(defs::ERROR) == defs::RUNNING) { if (Parallel(&Module::getRunStatus, {}).squash(defs::ERROR) ==
defs::RUNNING) {
LOG(logWARNING) << "Acquisition already running, Stopping it."; LOG(logWARNING) << "Acquisition already running, Stopping it.";
Parallel(&Module::stopAcquisition, {}); Parallel(&Module::stopAcquisition, {});
} }
@ -491,21 +488,35 @@ void DetectorImpl::configureReceiver(const int udpInterface, int module_id,
initReceiver(udpInterface); initReceiver(udpInterface);
} }
auto t = detectors[module_id]->getReceiverParameters(); auto t = detectors[module_id]->getReceiverParameters();
if (udpInterface == 1) {
receivers[module_id][0]->setTCPPort(port); receivers(module_id, udpInterface, 0)->setTCPPort(port);
receivers[module_id][0]->setHostname(hostname); receivers(module_id, udpInterface, 0)->setHostname(hostname);
auto m = receivers[module_id][0]->configure(t); auto m = receivers(module_id, udpInterface, 0)->configure(t);
if (m != 0) { if (m != 0) {
if (udpInterface == 0) {
detectors[module_id]->setDestinationUDPMAC(m); detectors[module_id]->setDestinationUDPMAC(m);
} } else if (udpInterface == 1) {
} else {
receivers2[module_id][0]->setTCPPort(port);
receivers2[module_id][0]->setHostname(hostname);
auto m = receivers2[module_id][0]->configure(t);
if (m != 0) {
detectors[module_id]->setDestinationUDPMAC2(m); detectors[module_id]->setDestinationUDPMAC2(m);
} else {
throw sls::RuntimeError("Incorrect udp interface id");
} }
} }
// if (udpInterface == 1) {
// receivers[module_id][0]->setTCPPort(port);
// receivers[module_id][0]->setHostname(hostname);
// auto m = receivers[module_id][0]->configure(t);
// if (m != 0) {
// detectors[module_id]->setDestinationUDPMAC(m);
// }
// } else {
// receivers2[module_id][0]->setTCPPort(port);
// receivers2[module_id][0]->setHostname(hostname);
// auto m = receivers2[module_id][0]->configure(t);
// if (m != 0) {
// detectors[module_id]->setDestinationUDPMAC2(m);
// }
// }
} }
void DetectorImpl::updateDetectorSize() { void DetectorImpl::updateDetectorSize() {
@ -530,13 +541,13 @@ void DetectorImpl::updateDetectorSize() {
detector_shm()->numberOfChannels.y = det_size.y * ndety; detector_shm()->numberOfChannels.y = det_size.y * ndety;
LOG(logDEBUG) << "\n\tNumber of Detectors in X direction:" LOG(logDEBUG) << "\n\tNumber of Detectors in X direction:"
<< detector_shm()->numberOfDetector.x << detector_shm()->numberOfDetector.x
<< "\n\tNumber of Detectors in Y direction:" << "\n\tNumber of Detectors in Y direction:"
<< detector_shm()->numberOfDetector.y << detector_shm()->numberOfDetector.y
<< "\n\tNumber of Channels in X direction:" << "\n\tNumber of Channels in X direction:"
<< detector_shm()->numberOfChannels.x << detector_shm()->numberOfChannels.x
<< "\n\tNumber of Channels in Y direction:" << "\n\tNumber of Channels in Y direction:"
<< detector_shm()->numberOfChannels.y; << detector_shm()->numberOfChannels.y;
for (auto &d : detectors) { for (auto &d : detectors) {
d->updateDetectorSize(detector_shm()->numberOfDetector); d->updateDetectorSize(detector_shm()->numberOfDetector);
@ -568,74 +579,74 @@ bool DetectorImpl::getGapPixelsinCallback() const {
void DetectorImpl::setGapPixelsinCallback(const bool enable) { void DetectorImpl::setGapPixelsinCallback(const bool enable) {
if (enable) { if (enable) {
switch (detector_shm()->multiDetectorType) { switch (detector_shm()->multiDetectorType) {
case JUNGFRAU: case JUNGFRAU:
break;
case EIGER:
if (size() && detectors[0]->getQuad()) {
break; break;
case EIGER: }
if (size() && detectors[0]->getQuad()) { if (detector_shm()->numberOfDetector.y % 2 != 0) {
break; throw RuntimeError("Gap pixels can only be used "
} "for full modules.");
if (detector_shm()->numberOfDetector.y % 2 != 0) { }
throw RuntimeError("Gap pixels can only be used " break;
"for full modules."); default:
} throw RuntimeError("Gap Pixels is not implemented for " +
break; detector_shm()->multiDetectorType);
default:
throw RuntimeError("Gap Pixels is not implemented for "
+ detector_shm()->multiDetectorType);
} }
} }
detector_shm()->gapPixels = enable; detector_shm()->gapPixels = enable;
} }
int DetectorImpl::createReceivingDataSockets(const bool destroy) { int DetectorImpl::createReceivingDataSockets(const bool destroy) {
if (destroy) { // if (destroy) {
LOG(logINFO) << "Going to destroy data sockets"; // LOG(logINFO) << "Going to destroy data sockets";
// close socket // // close socket
zmqSocket.clear(); // zmqSocket.clear();
client_downstream = false; // client_downstream = false;
LOG(logINFO) << "Destroyed Receiving Data Socket(s)"; // LOG(logINFO) << "Destroyed Receiving Data Socket(s)";
return OK; // return OK;
} // }
if (client_downstream) { // if (client_downstream) {
return OK; // return OK;
} // }
LOG(logINFO) << "Going to create data sockets"; // LOG(logINFO) << "Going to create data sockets";
size_t numSockets = detectors.size(); // size_t numSockets = detectors.size();
size_t numSocketsPerDetector = 1; // size_t numSocketsPerDetector = 1;
if (detector_shm()->multiDetectorType == EIGER) { // if (detector_shm()->multiDetectorType == EIGER) {
numSocketsPerDetector = 2; // numSocketsPerDetector = 2;
} // }
if (Parallel(&Module::getNumberofUDPInterfacesFromShm, {}).squash() == // if (Parallel(&Module::getNumberofUDPInterfacesFromShm, {}).squash() ==
2) { // 2) {
numSocketsPerDetector = 2; // numSocketsPerDetector = 2;
} // }
numSockets *= numSocketsPerDetector; // numSockets *= numSocketsPerDetector;
for (size_t iSocket = 0; iSocket < numSockets; ++iSocket) { // for (size_t iSocket = 0; iSocket < numSockets; ++iSocket) {
uint32_t portnum = (receivers[iSocket / numSocketsPerDetector][0] // uint32_t portnum = (receivers[iSocket / numSocketsPerDetector][0]
->getClientZmqPort());//FIXME 2 receivers // ->getClientZmqPort());//FIXME 2 receivers
portnum += (iSocket % numSocketsPerDetector); // portnum += (iSocket % numSocketsPerDetector);
try { // try {
zmqSocket.push_back(sls::make_unique<ZmqSocket>( // zmqSocket.push_back(sls::make_unique<ZmqSocket>(
receivers[iSocket / numSocketsPerDetector][0] // receivers[iSocket / numSocketsPerDetector][0]
->getClientZmqIP() // ->getClientZmqIP()
.str() // .str()
.c_str(), // .c_str(),
portnum)); // portnum));
LOG(logINFO) << "Zmq Client[" << iSocket << "] at " // LOG(logINFO) << "Zmq Client[" << iSocket << "] at "
<< zmqSocket.back()->GetZmqServerAddress(); // << zmqSocket.back()->GetZmqServerAddress();
} catch (...) { // } catch (...) {
LOG(logERROR) // LOG(logERROR)
<< "Could not create Zmq socket on port " << portnum; // << "Could not create Zmq socket on port " << portnum;
createReceivingDataSockets(true); // createReceivingDataSockets(true);
return FAIL; // return FAIL;
} // }
} // }
client_downstream = true; // client_downstream = true;
LOG(logINFO) << "Receiving Data Socket(s) created"; // LOG(logINFO) << "Receiving Data Socket(s) created";
return OK; return OK;
} }
@ -650,9 +661,8 @@ void DetectorImpl::readFrameFromReceiver() {
int nDetPixelsY = 0; int nDetPixelsY = 0;
bool quadEnable = false; bool quadEnable = false;
bool eiger = false; bool eiger = false;
int numInterfaces = int numInterfaces = Parallel(&Module::getNumberofUDPInterfacesFromShm, {})
Parallel(&Module::getNumberofUDPInterfacesFromShm, {}) .squash(); // cannot pick up from zmq
.squash(); // cannot pick up from zmq
bool runningList[zmqSocket.size()], connectList[zmqSocket.size()]; bool runningList[zmqSocket.size()], connectList[zmqSocket.size()];
int numRunning = 0; int numRunning = 0;
@ -665,7 +675,7 @@ void DetectorImpl::readFrameFromReceiver() {
// to remember the list it connected to, to disconnect later // to remember the list it connected to, to disconnect later
connectList[i] = false; connectList[i] = false;
LOG(logERROR) << "Could not connect to socket " LOG(logERROR) << "Could not connect to socket "
<< zmqSocket[i]->GetZmqServerAddress(); << zmqSocket[i]->GetZmqServerAddress();
runningList[i] = false; runningList[i] = false;
} }
} }
@ -712,8 +722,8 @@ void DetectorImpl::readFrameFromReceiver() {
{ {
zmqHeader zHeader; zmqHeader zHeader;
if (zmqSocket[isocket]->ReceiveHeader( if (zmqSocket[isocket]->ReceiveHeader(
isocket, zHeader, SLS_DETECTOR_JSON_HEADER_VERSION) == isocket, zHeader,
0) { SLS_DETECTOR_JSON_HEADER_VERSION) == 0) {
// parse error, version error or end of acquisition for // parse error, version error or end of acquisition for
// socket // socket
runningList[isocket] = false; runningList[isocket] = false;
@ -730,7 +740,7 @@ void DetectorImpl::readFrameFromReceiver() {
multiframe = new char[multisize]; multiframe = new char[multisize];
memset(multiframe, 0xFF, multisize); memset(multiframe, 0xFF, multisize);
// dynamic range // dynamic range
dynamicRange = zHeader.dynamicRange; dynamicRange = zHeader.dynamicRange;
bytesPerPixel = (float)dynamicRange / 8; bytesPerPixel = (float)dynamicRange / 8;
// shape // shape
nPixelsX = zHeader.npixelsx; nPixelsX = zHeader.npixelsx;
@ -743,13 +753,13 @@ void DetectorImpl::readFrameFromReceiver() {
nDetPixelsY = nY * nPixelsY; nDetPixelsY = nY * nPixelsY;
// det type // det type
eiger = (zHeader.detType == static_cast<int>(3)) eiger = (zHeader.detType == static_cast<int>(3))
? true ? true
: false; // to be changed to EIGER when firmware : false; // to be changed to EIGER when
// updates its header data // firmware updates its header data
quadEnable = (zHeader.quad == 0) ? false : true; quadEnable = (zHeader.quad == 0) ? false : true;
LOG(logDEBUG1) LOG(logDEBUG1)
<< "One Time Header Info:" << "One Time Header Info:"
"\n\tsize: " "\n\tsize: "
<< size << "\n\tmultisize: " << multisize << size << "\n\tmultisize: " << multisize
<< "\n\tdynamicRange: " << dynamicRange << "\n\tdynamicRange: " << dynamicRange
<< "\n\tbytesPerPixel: " << bytesPerPixel << "\n\tbytesPerPixel: " << bytesPerPixel
@ -774,9 +784,9 @@ void DetectorImpl::readFrameFromReceiver() {
if (zHeader.completeImage == 0) { if (zHeader.completeImage == 0) {
completeImage = false; completeImage = false;
} }
LOG(logDEBUG1) LOG(logDEBUG1)
<< "Header Info:" << "Header Info:"
"\n\tcurrentFileName: " "\n\tcurrentFileName: "
<< currentFileName << "\n\tcurrentAcquisitionIndex: " << currentFileName << "\n\tcurrentAcquisitionIndex: "
<< currentAcquisitionIndex << currentAcquisitionIndex
<< "\n\tcurrentFrameIndex: " << currentFrameIndex << "\n\tcurrentFrameIndex: " << currentFrameIndex
@ -800,10 +810,10 @@ void DetectorImpl::readFrameFromReceiver() {
uint32_t rowoffset = nX * singledetrowoffset; uint32_t rowoffset = nX * singledetrowoffset;
if (detector_shm()->multiDetectorType == CHIPTESTBOARD) { if (detector_shm()->multiDetectorType == CHIPTESTBOARD) {
singledetrowoffset = size; singledetrowoffset = size;
} }
LOG(logDEBUG1) LOG(logDEBUG1)
<< "Multi Image Info:" << "Multi Image Info:"
"\n\txoffset: " "\n\txoffset: "
<< xoffset << "\n\tyoffset: " << yoffset << xoffset << "\n\tyoffset: " << yoffset
<< "\n\tsingledetrowoffset: " << singledetrowoffset << "\n\tsingledetrowoffset: " << singledetrowoffset
<< "\n\trowoffset: " << rowoffset; << "\n\trowoffset: " << rowoffset;
@ -829,33 +839,33 @@ void DetectorImpl::readFrameFromReceiver() {
} }
} }
LOG(logDEBUG)<< "Call Back Info:" LOG(logDEBUG) << "Call Back Info:"
<< "\n\t nDetPixelsX: " << nDetPixelsX << "\n\t nDetPixelsX: " << nDetPixelsX
<< "\n\t nDetPixelsY: " << nDetPixelsY << "\n\t nDetPixelsY: " << nDetPixelsY
<< "\n\t databytes: " << multisize << "\n\t databytes: " << multisize
<< "\n\t dynamicRange: " << dynamicRange; << "\n\t dynamicRange: " << dynamicRange;
// send data to callback // send data to callback
if (data) { if (data) {
char* image = multiframe; char *image = multiframe;
int imagesize = multisize; int imagesize = multisize;
if (gapPixels) { if (gapPixels) {
int n = InsertGapPixels(multiframe, multigappixels, int n = InsertGapPixels(multiframe, multigappixels, quadEnable,
quadEnable, dynamicRange, nDetPixelsX, nDetPixelsY); dynamicRange, nDetPixelsX, nDetPixelsY);
image = multigappixels; image = multigappixels;
imagesize = n; imagesize = n;
} }
LOG(logDEBUG) LOG(logDEBUG) << "Image Info:"
<< "Image Info:" << "\n\tnDetPixelsX: " << nDetPixelsX
<< "\n\tnDetPixelsX: " << nDetPixelsX << "\n\tnDetPixelsY: " << nDetPixelsY
<< "\n\tnDetPixelsY: " << nDetPixelsY << "\n\timagesize: " << imagesize
<< "\n\timagesize: " << imagesize << "\n\tdynamicRange: " << dynamicRange;
<< "\n\tdynamicRange: " << dynamicRange;
thisData = new detectorData(currentProgress, thisData =
currentFileName, nDetPixelsX, nDetPixelsY, image, new detectorData(currentProgress, currentFileName, nDetPixelsX,
imagesize, dynamicRange, currentFileIndex, completeImage); nDetPixelsY, image, imagesize, dynamicRange,
currentFileIndex, completeImage);
dataReady( dataReady(
thisData, currentFrameIndex, thisData, currentFrameIndex,
@ -901,14 +911,13 @@ void DetectorImpl::readFrameFromReceiver() {
delete[] multigappixels; delete[] multigappixels;
} }
int DetectorImpl::InsertGapPixels(char *image, char *&gpImage, int DetectorImpl::InsertGapPixels(char *image, char *&gpImage, bool quadEnable,
bool quadEnable, int dr, int &nPixelsx, int &nPixelsy) { int dr, int &nPixelsx, int &nPixelsy) {
LOG(logDEBUG)<< "Insert Gap pixels:" LOG(logDEBUG) << "Insert Gap pixels:"
<< "\n\t nPixelsx: " << nPixelsx << "\n\t nPixelsx: " << nPixelsx
<< "\n\t nPixelsy: " << nPixelsy << "\n\t nPixelsy: " << nPixelsy
<< "\n\t quadEnable: " << quadEnable << "\n\t quadEnable: " << quadEnable << "\n\t dr: " << dr;
<< "\n\t dr: " << dr;
// inter module gap pixels // inter module gap pixels
int modGapPixelsx = 8; int modGapPixelsx = 8;
@ -940,7 +949,7 @@ int DetectorImpl::InsertGapPixels(char *image, char *&gpImage,
// (setting gap pixels and then adding half module or disabling quad) // (setting gap pixels and then adding half module or disabling quad)
if (nPixelsy / nMod1Pixelsy == 0) { if (nPixelsy / nMod1Pixelsy == 0) {
LOG(logERROR) << "Gap pixels can only be enabled with full modules. " LOG(logERROR) << "Gap pixels can only be enabled with full modules. "
"Sending dummy data without gap pixels.\n"; "Sending dummy data without gap pixels.\n";
double bytesPerPixel = (double)dr / 8.00; double bytesPerPixel = (double)dr / 8.00;
int imagesize = nPixelsy * nPixelsx * bytesPerPixel; int imagesize = nPixelsy * nPixelsx * bytesPerPixel;
if (gpImage == NULL) { if (gpImage == NULL) {
@ -951,8 +960,10 @@ int DetectorImpl::InsertGapPixels(char *image, char *&gpImage,
} }
// total number of pixels // total number of pixels
int nTotx = nPixelsx + (nMod1GapPixelsx * nModx) + (modGapPixelsx * (nModx - 1)); int nTotx =
int nToty = nPixelsy + (nMod1GapPixelsy * nMody) + (modGapPixelsy * (nMody - 1)); nPixelsx + (nMod1GapPixelsx * nModx) + (modGapPixelsx * (nModx - 1));
int nToty =
nPixelsy + (nMod1GapPixelsy * nMody) + (modGapPixelsy * (nMody - 1));
// total number of chips // total number of chips
int nChipx = nPixelsx / nChipPixelsx; int nChipx = nPixelsx / nChipPixelsx;
int nChipy = nPixelsy / nChipPixelsy; int nChipy = nPixelsy / nChipPixelsy;
@ -960,13 +971,15 @@ int DetectorImpl::InsertGapPixels(char *image, char *&gpImage,
double bytesPerPixel = (double)dr / 8.00; double bytesPerPixel = (double)dr / 8.00;
int imagesize = nTotx * nToty * bytesPerPixel; int imagesize = nTotx * nToty * bytesPerPixel;
int nChipBytesx = nChipPixelsx * bytesPerPixel; // 1 chip bytes in x int nChipBytesx = nChipPixelsx * bytesPerPixel; // 1 chip bytes in x
int nChipGapBytesx = chipGapPixelsx * bytesPerPixel; // 2 pixel bytes int nChipGapBytesx = chipGapPixelsx * bytesPerPixel; // 2 pixel bytes
int nModGapBytesx = modGapPixelsx * bytesPerPixel; // 8 pixel bytes int nModGapBytesx = modGapPixelsx * bytesPerPixel; // 8 pixel bytes
int nChipBytesy = nChipPixelsy * nTotx * bytesPerPixel; // 1 chip bytes in y int nChipBytesy = nChipPixelsy * nTotx * bytesPerPixel; // 1 chip bytes in y
int nChipGapBytesy = chipGapPixelsy * nTotx * bytesPerPixel; // 2 lines int nChipGapBytesy = chipGapPixelsy * nTotx * bytesPerPixel; // 2 lines
int nModGapBytesy = modGapPixelsy * nTotx * bytesPerPixel; // 36 lines int nModGapBytesy = modGapPixelsy * nTotx *
// 4 bit mode, its 1 byte (because for 4 bit mode, we handle 1 byte at a time) bytesPerPixel; // 36 lines
// 4 bit mode, its 1 byte (because for 4
// bit mode, we handle 1 byte at a time)
int pixel1 = (int)(ceil(bytesPerPixel)); int pixel1 = (int)(ceil(bytesPerPixel));
int row1Bytes = nTotx * bytesPerPixel; int row1Bytes = nTotx * bytesPerPixel;
int nMod1TotPixelsx = nMod1Pixelsx + nMod1GapPixelsx; int nMod1TotPixelsx = nMod1Pixelsx + nMod1GapPixelsx;
@ -980,38 +993,37 @@ int DetectorImpl::InsertGapPixels(char *image, char *&gpImage,
if (detType == JUNGFRAU) { if (detType == JUNGFRAU) {
divisionValue = 1; divisionValue = 1;
} }
LOG(logDEBUG) LOG(logDEBUG) << "Insert Gap pixels Calculations:\n\t"
<< "Insert Gap pixels Calculations:\n\t" << "nPixelsx: " << nPixelsx << "\n\t"
<< "nPixelsx: " << nPixelsx << "\n\t" << "nPixelsy: " << nPixelsy << "\n\t"
<< "nPixelsy: " << nPixelsy << "\n\t" << "nMod1Pixelsx: " << nMod1Pixelsx << "\n\t"
<< "nMod1Pixelsx: " << nMod1Pixelsx << "\n\t" << "nMod1Pixelsy: " << nMod1Pixelsy << "\n\t"
<< "nMod1Pixelsy: " << nMod1Pixelsy << "\n\t" << "nMod1GapPixelsx: " << nMod1GapPixelsx << "\n\t"
<< "nMod1GapPixelsx: " << nMod1GapPixelsx << "\n\t" << "nMod1GapPixelsy: " << nMod1GapPixelsy << "\n\t"
<< "nMod1GapPixelsy: " << nMod1GapPixelsy << "\n\t" << "nChipy: " << nChipy << "\n\t"
<< "nChipy: " << nChipy << "\n\t" << "nChipx: " << nChipx << "\n\t"
<< "nChipx: " << nChipx << "\n\t" << "nModx: " << nModx << "\n\t"
<< "nModx: " << nModx << "\n\t" << "nMody: " << nMody << "\n\t"
<< "nMody: " << nMody << "\n\t" << "nTotx: " << nTotx << "\n\t"
<< "nTotx: " << nTotx << "\n\t" << "nToty: " << nToty << "\n\t"
<< "nToty: " << nToty << "\n\t" << "bytesPerPixel: " << bytesPerPixel << "\n\t"
<< "bytesPerPixel: " << bytesPerPixel << "\n\t" << "imagesize: " << imagesize << "\n\t"
<< "imagesize: " << imagesize << "\n\t" << "nChipBytesx: " << nChipBytesx << "\n\t"
<< "nChipBytesx: " << nChipBytesx << "\n\t" << "nChipGapBytesx: " << nChipGapBytesx << "\n\t"
<< "nChipGapBytesx: " << nChipGapBytesx << "\n\t" << "nModGapBytesx: " << nModGapBytesx << "\n\t"
<< "nModGapBytesx: " << nModGapBytesx << "\n\t" << "nChipBytesy: " << nChipBytesy << "\n\t"
<< "nChipBytesy: " << nChipBytesy << "\n\t" << "nChipGapBytesy: " << nChipGapBytesy << "\n\t"
<< "nChipGapBytesy: " << nChipGapBytesy << "\n\t" << "nModGapBytesy: " << nModGapBytesy << "\n\t"
<< "nModGapBytesy: " << nModGapBytesy << "\n\t" << "pixel1: " << pixel1 << "\n\t"
<< "pixel1: " << pixel1 << "\n\t" << "row1Bytes: " << row1Bytes << "\n\t"
<< "row1Bytes: " << row1Bytes << "\n\t" << "nMod1TotPixelsx: " << nMod1TotPixelsx << "\n\t"
<< "nMod1TotPixelsx: " << nMod1TotPixelsx << "\n\t" << "divisionValue: " << divisionValue << "\n\n";
<< "divisionValue: " << divisionValue << "\n\n";
if (gpImage == NULL) { if (gpImage == NULL) {
gpImage = new char[imagesize]; gpImage = new char[imagesize];
} }
memset(gpImage, 0xFF, imagesize); memset(gpImage, 0xFF, imagesize);
//memcpy(gpImage, image, imagesize); // memcpy(gpImage, image, imagesize);
char *src = nullptr; char *src = nullptr;
char *dst = nullptr; char *dst = nullptr;
@ -1093,11 +1105,13 @@ int DetectorImpl::InsertGapPixels(char *image, char *&gpImage,
break; break;
case 16: case 16:
// neighbouring gap pixels to left // neighbouring gap pixels to left
temp16 = (*((uint16_t *)(dst - pixel1))) / divisionValue; temp16 =
(*((uint16_t *)(dst - pixel1))) / divisionValue;
(*((uint16_t *)dst)) = temp16; (*((uint16_t *)dst)) = temp16;
(*((uint16_t *)(dst - pixel1))) = temp16; (*((uint16_t *)(dst - pixel1))) = temp16;
// neighbouring gap pixels to right // neighbouring gap pixels to right
temp16 = (*((uint16_t *)(dst + 2 * pixel1))) / divisionValue; temp16 =
(*((uint16_t *)(dst + 2 * pixel1))) / divisionValue;
(*((uint16_t *)(dst + pixel1))) = temp16; (*((uint16_t *)(dst + pixel1))) = temp16;
(*((uint16_t *)(dst + 2 * pixel1))) = temp16; (*((uint16_t *)(dst + 2 * pixel1))) = temp16;
break; break;
@ -1111,7 +1125,7 @@ int DetectorImpl::InsertGapPixels(char *image, char *&gpImage,
(*((uint32_t *)(dst + pixel1))) = temp32; (*((uint32_t *)(dst + pixel1))) = temp32;
(*((uint32_t *)(dst + 2 * pixel1))) = temp32; (*((uint32_t *)(dst + 2 * pixel1))) = temp32;
break; break;
} }
dst += nChipGapBytesx; dst += nChipGapBytesx;
} }
// skip inter module gap pixels in x // skip inter module gap pixels in x
@ -1194,8 +1208,6 @@ int DetectorImpl::InsertGapPixels(char *image, char *&gpImage,
return imagesize; return imagesize;
} }
bool DetectorImpl::enableDataStreamingToClient(int enable) { bool DetectorImpl::enableDataStreamingToClient(int enable) {
if (enable >= 0) { if (enable >= 0) {
// destroy data threads // destroy data threads
@ -1298,7 +1310,7 @@ int DetectorImpl::acquire() {
if (acquisition_finished != nullptr) { if (acquisition_finished != nullptr) {
int status = Parallel(&Module::getRunStatus, {}).squash(ERROR); int status = Parallel(&Module::getRunStatus, {}).squash(ERROR);
auto a = Parallel3(&Receiver::getProgress); auto a = Parallel3(&Receiver::getProgress);
int progress = (*std::min_element (a.begin(), a.end())); int progress = (*std::min_element(a.begin(), a.end()));
acquisition_finished((double)progress, status, acqFinished_p); acquisition_finished((double)progress, status, acqFinished_p);
} }
@ -1307,9 +1319,9 @@ int DetectorImpl::acquire() {
clock_gettime(CLOCK_REALTIME, &end); clock_gettime(CLOCK_REALTIME, &end);
LOG(logDEBUG1) << "Elapsed time for acquisition:" LOG(logDEBUG1) << "Elapsed time for acquisition:"
<< ((end.tv_sec - begin.tv_sec) + << ((end.tv_sec - begin.tv_sec) +
(end.tv_nsec - begin.tv_nsec) / 1000000000.0) (end.tv_nsec - begin.tv_nsec) / 1000000000.0)
<< " seconds"; << " seconds";
} catch (...) { } catch (...) {
setAcquiringFlag(false); setAcquiringFlag(false);
throw; throw;
@ -1319,12 +1331,11 @@ int DetectorImpl::acquire() {
} }
void DetectorImpl::printProgress(double progress) { void DetectorImpl::printProgress(double progress) {
std::cout << std::fixed << std::setprecision(2) << std::setw(6) std::cout << std::fixed << std::setprecision(2) << std::setw(6) << progress
<< progress << " \%"; << " \%";
std::cout << '\r' << std::flush; std::cout << '\r' << std::flush;
} }
void DetectorImpl::startProcessingThread() { void DetectorImpl::startProcessingThread() {
dataProcessingThread = std::thread(&DetectorImpl::processData, this); dataProcessingThread = std::thread(&DetectorImpl::processData, this);
} }
@ -1349,7 +1360,9 @@ void DetectorImpl::processData() {
} }
} }
// get and print progress // get and print progress
double temp = (double)Parallel1(&Receiver::getProgress, {0}, {0}).squash(); double temp =
(double)Parallel1(&Receiver::getProgress, {0}, {0})
.squash();
if (temp != progress) { if (temp != progress) {
printProgress(progress); printProgress(progress);
progress = temp; progress = temp;
@ -1358,7 +1371,9 @@ void DetectorImpl::processData() {
// exiting loop // exiting loop
if (getJoinThreadFlag()) { if (getJoinThreadFlag()) {
// print progress one final time before exiting // print progress one final time before exiting
progress = (double)Parallel1(&Receiver::getProgress, {0}, {0}).squash(); progress =
(double)Parallel1(&Receiver::getProgress, {0}, {0})
.squash();
printProgress(progress); printProgress(progress);
break; break;
} }
@ -1518,10 +1533,9 @@ std::vector<char> DetectorImpl::readProgrammingFile(const std::string &fname) {
"Program FPGA: Could not close destination file after converting"); "Program FPGA: Could not close destination file after converting");
} }
unlink(destfname); // delete temporary file unlink(destfname); // delete temporary file
LOG(logDEBUG1) LOG(logDEBUG1) << "Successfully loaded the rawbin file to program memory";
<< "Successfully loaded the rawbin file to program memory";
LOG(logINFO) << "Read file into memory"; LOG(logINFO) << "Read file into memory";
return buffer; return buffer;
} }
}//namespace sls } // namespace sls

View File

@ -1,5 +1,5 @@
#pragma once #pragma once
#include "Container3.h"
#include "Result.h" #include "Result.h"
#include "SharedMemory.h" #include "SharedMemory.h"
#include "logger.h" #include "logger.h"
@ -22,7 +22,7 @@ class detectorData;
#include <future> #include <future>
#include <numeric> #include <numeric>
namespace sls{ namespace sls {
class Module; class Module;
class Receiver; class Receiver;
@ -75,7 +75,7 @@ class DetectorImpl : public virtual slsDetectorDefs {
* @param update true to update last user pid, date etc * @param update true to update last user pid, date etc
*/ */
explicit DetectorImpl(int detector_id = 0, bool verify = true, explicit DetectorImpl(int detector_id = 0, bool verify = true,
bool update = true); bool update = true);
/** /**
* Destructor * Destructor
@ -189,452 +189,84 @@ class DetectorImpl : public virtual slsDetectorDefs {
} }
} }
template <typename RT, typename... CT> template <typename RT, typename... CT>
sls::Result<RT> Parallel1(RT (sls::Receiver::*somefunc)(CT...), sls::Result<RT> Parallel1(RT (sls::Receiver::*somefunc)(CT...),
std::vector<int> dPositions, std::vector<int> dPositions,
std::vector<int> rxPositions, std::vector<int> rxPositions,
typename NonDeduced<CT>::type... Args) { typename NonDeduced<CT>::type... Args) {
if (receivers.size() == 0) return {};
throw sls::RuntimeError("No receivers added");
if (dPositions.empty() ||
(dPositions.size() == 1 && dPositions[0] == -1)) {
dPositions.resize(receivers.size());
std::iota(begin(dPositions), end(dPositions), 0);
}
if (rxPositions.empty() ||
(rxPositions.size() == 1 && rxPositions[0] == -1)) {
rxPositions.resize(receivers[0].size());
std::iota(begin(rxPositions), end(rxPositions), 0);
}
std::vector<std::future<RT>> futures;
futures.reserve(dPositions.size() * rxPositions.size());
for (size_t i : dPositions) {
if (i >= receivers.size())
throw sls::RuntimeError("Detector out of range");
// each entry
for (size_t j : rxPositions) {
futures.push_back(std::async(std::launch::async, somefunc,
receivers[i][j].get(), Args...));
}
}
sls::Result<RT> result;
result.reserve(dPositions.size() * rxPositions.size());
for (auto &i : futures) {
result.push_back(i.get());
}
return result;
} }
template <typename RT, typename... CT> template <typename RT, typename... CT>
sls::Result<RT> Parallel1(RT (sls::Receiver::*somefunc)(CT...) const, sls::Result<RT> Parallel1(RT (sls::Receiver::*somefunc)(CT...) const,
std::vector<int> dPositions, std::vector<int> dPositions,
std::vector<int> rxPositions, std::vector<int> rxPositions,
typename NonDeduced<CT>::type... Args) const { typename NonDeduced<CT>::type... Args) const {
if (receivers.size() == 0) return {};
throw sls::RuntimeError("No receivers added");
if (dPositions.empty() ||
(dPositions.size() == 1 && dPositions[0] == -1)) {
dPositions.resize(receivers.size());
std::iota(begin(dPositions), end(dPositions), 0);
}
if (rxPositions.empty() ||
(rxPositions.size() == 1 && rxPositions[0] == -1)) {
rxPositions.resize(receivers[0].size());
std::iota(begin(rxPositions), end(rxPositions), 0);
}
std::vector<std::future<RT>> futures;
futures.reserve(dPositions.size() * rxPositions.size());
for (size_t i : dPositions) {
if (i >= receivers.size())
throw sls::RuntimeError("Detector out of range");
// each entry
for (size_t j : rxPositions) {
futures.push_back(std::async(std::launch::async, somefunc,
receivers[i][j].get(), Args...));
}
}
sls::Result<RT> result;
result.reserve(dPositions.size() * rxPositions.size());
for (auto &i : futures) {
result.push_back(i.get());
}
return result;
} }
template <typename... CT> template <typename... CT>
void Parallel1(void (sls::Receiver::*somefunc)(CT...), void Parallel1(void (sls::Receiver::*somefunc)(CT...),
std::vector<int> dPositions, std::vector<int> dPositions, std::vector<int> rxPositions,
std::vector<int> rxPositions, typename NonDeduced<CT>::type... Args) {}
typename NonDeduced<CT>::type... Args) {
if (receivers.size() == 0)
throw sls::RuntimeError("No receivers added");
if (dPositions.empty() ||
(dPositions.size() == 1 && dPositions[0] == -1)) {
dPositions.resize(receivers.size());
std::iota(begin(dPositions), end(dPositions), 0);
}
if (rxPositions.empty() ||
(rxPositions.size() == 1 && rxPositions[0] == -1)) {
rxPositions.resize(receivers[0].size());
std::iota(begin(rxPositions), end(rxPositions), 0);
}
std::vector<std::future<void>> futures;
futures.reserve(dPositions.size() * rxPositions.size());
for (size_t i : dPositions) {
if (i >= receivers.size())
throw sls::RuntimeError("Detector out of range");
// each entry
for (size_t j : rxPositions) {
futures.push_back(std::async(std::launch::async, somefunc,
receivers[i][j].get(), Args...));
}
}
for (auto &i : futures) {
i.get();
}
}
template <typename... CT> template <typename... CT>
void Parallel1(void (sls::Receiver::*somefunc)(CT...) const, void Parallel1(void (sls::Receiver::*somefunc)(CT...) const,
std::vector<int> dPositions, std::vector<int> dPositions, std::vector<int> rxPositions,
std::vector<int> rxPositions, typename NonDeduced<CT>::type... Args) const {}
typename NonDeduced<CT>::type... Args) const {
if (receivers.size() == 0)
throw sls::RuntimeError("No receivers added");
if (dPositions.empty() ||
(dPositions.size() == 1 && dPositions[0] == -1)) {
dPositions.resize(receivers.size());
std::iota(begin(dPositions), end(dPositions), 0);
}
if (rxPositions.empty() ||
(rxPositions.size() == 1 && rxPositions[0] == -1)) {
rxPositions.resize(receivers[0].size());
std::iota(begin(rxPositions), end(rxPositions), 0);
}
std::vector<std::future<void>> futures;
futures.reserve(dPositions.size() * rxPositions.size());
for (size_t i : dPositions) {
if (i >= receivers.size())
throw sls::RuntimeError("Detector out of range");
// each entry
for (size_t j : rxPositions) {
futures.push_back(std::async(std::launch::async, somefunc,
receivers[i][j].get(), Args...));
}
}
for (auto &i : futures) {
i.get();
}
}
template <typename RT, typename... CT> template <typename RT, typename... CT>
sls::Result<RT> Parallel2(RT (sls::Receiver::*somefunc)(CT...), sls::Result<RT> Parallel2(RT (sls::Receiver::*somefunc)(CT...),
std::vector<int> dPositions, std::vector<int> dPositions,
std::vector<int> rxPositions, std::vector<int> rxPositions,
typename NonDeduced<CT>::type... Args) { typename NonDeduced<CT>::type... Args) {
if (receivers2.size() == 0) return {};
throw sls::RuntimeError("No receivers2 added");
if (dPositions.empty() ||
(dPositions.size() == 1 && dPositions[0] == -1)) {
dPositions.resize(receivers2.size());
std::iota(begin(dPositions), end(dPositions), 0);
}
if (rxPositions.empty() ||
(rxPositions.size() == 1 && rxPositions[0] == -1)) {
rxPositions.resize(receivers2[0].size());
std::iota(begin(rxPositions), end(rxPositions), 0);
}
std::vector<std::future<RT>> futures;
futures.reserve(dPositions.size() * rxPositions.size());
for (size_t i : dPositions) {
if (i >= receivers2.size())
throw sls::RuntimeError("Detector out of range");
// each entry
for (size_t j : rxPositions) {
futures.push_back(std::async(std::launch::async, somefunc,
receivers2[i][j].get(), Args...));
}
}
sls::Result<RT> result;
result.reserve(dPositions.size() * rxPositions.size());
for (auto &i : futures) {
result.push_back(i.get());
}
return result;
} }
template <typename RT, typename... CT> template <typename RT, typename... CT>
sls::Result<RT> Parallel2(RT (sls::Receiver::*somefunc)(CT...) const, sls::Result<RT> Parallel2(RT (sls::Receiver::*somefunc)(CT...) const,
std::vector<int> dPositions, std::vector<int> dPositions,
std::vector<int> rxPositions, std::vector<int> rxPositions,
typename NonDeduced<CT>::type... Args) const { typename NonDeduced<CT>::type... Args) const {
if (receivers2.size() == 0) return {};
throw sls::RuntimeError("No receivers2 added");
if (dPositions.empty() ||
(dPositions.size() == 1 && dPositions[0] == -1)) {
dPositions.resize(receivers2.size());
std::iota(begin(dPositions), end(dPositions), 0);
}
if (rxPositions.empty() ||
(rxPositions.size() == 1 && rxPositions[0] == -1)) {
rxPositions.resize(receivers2[0].size());
std::iota(begin(rxPositions), end(rxPositions), 0);
}
std::vector<std::future<RT>> futures;
futures.reserve(dPositions.size() * rxPositions.size());
for (size_t i : dPositions) {
if (i >= receivers2.size())
throw sls::RuntimeError("Detector out of range");
// each entry
for (size_t j : rxPositions) {
futures.push_back(std::async(std::launch::async, somefunc,
receivers2[i][j].get(), Args...));
}
}
sls::Result<RT> result;
result.reserve(dPositions.size() * rxPositions.size());
for (auto &i : futures) {
result.push_back(i.get());
}
return result;
} }
template <typename... CT> template <typename... CT>
void Parallel2(void (sls::Receiver::*somefunc)(CT...), void Parallel2(void (sls::Receiver::*somefunc)(CT...),
std::vector<int> dPositions, std::vector<int> dPositions, std::vector<int> rxPositions,
std::vector<int> rxPositions, typename NonDeduced<CT>::type... Args) {}
typename NonDeduced<CT>::type... Args) {
if (receivers2.size() == 0)
throw sls::RuntimeError("No receivers2 added");
if (dPositions.empty() ||
(dPositions.size() == 1 && dPositions[0] == -1)) {
dPositions.resize(receivers2.size());
std::iota(begin(dPositions), end(dPositions), 0);
}
if (rxPositions.empty() ||
(rxPositions.size() == 1 && rxPositions[0] == -1)) {
rxPositions.resize(receivers2[0].size());
std::iota(begin(rxPositions), end(rxPositions), 0);
}
std::vector<std::future<void>> futures;
futures.reserve(dPositions.size() * rxPositions.size());
for (size_t i : dPositions) {
if (i >= receivers2.size())
throw sls::RuntimeError("Detector out of range");
// each entry
for (size_t j : rxPositions) {
futures.push_back(std::async(std::launch::async, somefunc,
receivers2[i][j].get(), Args...));
}
}
for (auto &i : futures) {
i.get();
}
}
template <typename... CT> template <typename... CT>
void Parallel2(void (sls::Receiver::*somefunc)(CT...) const, void Parallel2(void (sls::Receiver::*somefunc)(CT...) const,
std::vector<int> dPositions, std::vector<int> dPositions, std::vector<int> rxPositions,
std::vector<int> rxPositions, typename NonDeduced<CT>::type... Args) const {}
typename NonDeduced<CT>::type... Args) const {
if (receivers2.size() == 0)
throw sls::RuntimeError("No receivers2 added");
if (dPositions.empty() ||
(dPositions.size() == 1 && dPositions[0] == -1)) {
dPositions.resize(receivers2.size());
std::iota(begin(dPositions), end(dPositions), 0);
}
if (rxPositions.empty() ||
(rxPositions.size() == 1 && rxPositions[0] == -1)) {
rxPositions.resize(receivers2[0].size());
std::iota(begin(rxPositions), end(rxPositions), 0);
}
std::vector<std::future<void>> futures;
futures.reserve(dPositions.size() * rxPositions.size());
for (size_t i : dPositions) {
if (i >= receivers2.size())
throw sls::RuntimeError("Detector out of range");
// each entry
for (size_t j : rxPositions) {
futures.push_back(std::async(std::launch::async, somefunc,
receivers2[i][j].get(), Args...));
}
}
for (auto &i : futures) {
i.get();
}
}
// for all , but dont complain if receiver2 doesnt exist // for all , but dont complain if receiver2 doesnt exist
template <typename RT, typename... CT> template <typename RT, typename... CT>
sls::Result<RT> Parallel3(RT (sls::Receiver::*somefunc)(CT...), sls::Result<RT> Parallel3(RT (sls::Receiver::*somefunc)(CT...),
typename NonDeduced<CT>::type... Args) { typename NonDeduced<CT>::type... Args) {
if (receivers.size() == 0) return {};
throw sls::RuntimeError("No receivers added");
std::vector<int> dPositions;
dPositions.resize(receivers.size());
std::iota(begin(dPositions), end(dPositions), 0);
std::vector<int> rxPositions;
rxPositions.resize(receivers[0].size());
std::iota(begin(rxPositions), end(rxPositions), 0);
// multiply by 2 if receivers2 exists
size_t futureSize = dPositions.size() * rxPositions.size() *
(receivers2.size() > 0 ? 2 : 1);
std::vector<std::future<RT>> futures;
futures.reserve(futureSize);
for (size_t i : dPositions) {
// each entry
for (size_t j : rxPositions) {
futures.push_back(std::async(std::launch::async, somefunc,
receivers[i][j].get(), Args...));
if (receivers2.size()) {
futures.push_back(std::async(std::launch::async, somefunc,
receivers2[i][j].get(), Args...));
}
}
}
sls::Result<RT> result;
result.reserve(futureSize);
for (auto &i : futures) {
result.push_back(i.get());
}
return result;
} }
template <typename RT, typename... CT> template <typename RT, typename... CT>
sls::Result<RT> Parallel3(RT (sls::Receiver::*somefunc)(CT...) const, sls::Result<RT> Parallel3(RT (sls::Receiver::*somefunc)(CT...) const,
typename NonDeduced<CT>::type... Args) const { typename NonDeduced<CT>::type... Args) const {
if (receivers.size() == 0) return {};
throw sls::RuntimeError("No receivers added");
std::vector<int> dPositions;
dPositions.resize(receivers.size());
std::iota(begin(dPositions), end(dPositions), 0);
std::vector<int> rxPositions;
rxPositions.resize(receivers[0].size());
std::iota(begin(rxPositions), end(rxPositions), 0);
// multiply by 2 if receivers2 exists
size_t futureSize = dPositions.size() * rxPositions.size() *
(receivers2.size() > 0 ? 2 : 1);
std::vector<std::future<RT>> futures;
futures.reserve(futureSize);
for (size_t i : dPositions) {
// each entry
for (size_t j : rxPositions) {
futures.push_back(std::async(std::launch::async, somefunc,
receivers[i][j].get(), Args...));
if (receivers2.size()) {
futures.push_back(std::async(std::launch::async, somefunc,
receivers2[i][j].get(), Args...));
}
}
}
sls::Result<RT> result;
result.reserve(futureSize);
for (auto &i : futures) {
result.push_back(i.get());
}
return result;
} }
template <typename... CT> template <typename... CT>
void Parallel3(void (sls::Receiver::*somefunc)(CT...), void Parallel3(void (sls::Receiver::*somefunc)(CT...),
typename NonDeduced<CT>::type... Args) { typename NonDeduced<CT>::type... Args) {}
if (receivers.size() == 0)
throw sls::RuntimeError("No receivers added");
std::vector<int> dPositions;
dPositions.resize(receivers.size());
std::iota(begin(dPositions), end(dPositions), 0);
std::vector<int> rxPositions;
rxPositions.resize(receivers[0].size());
std::iota(begin(rxPositions), end(rxPositions), 0);
// multiply by 2 if receivers2 exists
size_t futureSize = dPositions.size() * rxPositions.size() *
(receivers2.size() > 0 ? 2 : 1);
std::vector<std::future<void>> futures;
futures.reserve(futureSize);
for (size_t i : dPositions) {
// each entry
for (size_t j : rxPositions) {
futures.push_back(std::async(std::launch::async, somefunc,
receivers[i][j].get(), Args...));
if (receivers2.size()) {
futures.push_back(std::async(std::launch::async, somefunc,
receivers2[i][j].get(), Args...));
}
}
}
for (auto &i : futures) {
i.get();
}
}
template <typename... CT> template <typename... CT>
void Parallel3(void (sls::Receiver::*somefunc)(CT...) const, void Parallel3(void (sls::Receiver::*somefunc)(CT...) const,
typename NonDeduced<CT>::type... Args) const { typename NonDeduced<CT>::type... Args) const {}
if (receivers.size() == 0)
throw sls::RuntimeError("No receivers added");
std::vector<int> dPositions;
dPositions.resize(receivers.size());
std::iota(begin(dPositions), end(dPositions), 0);
std::vector<int> rxPositions;
rxPositions.resize(receivers[0].size());
std::iota(begin(rxPositions), end(rxPositions), 0);
// multiply by 2 if receivers2 exists
size_t futureSize = dPositions.size() * rxPositions.size() *
(receivers2.size() > 0 ? 2 : 1);
std::vector<std::future<void>> futures;
futures.reserve(futureSize);
for (size_t i : dPositions) {
// each entry
for (size_t j : rxPositions) {
futures.push_back(std::async(std::launch::async, somefunc,
receivers[i][j].get(), Args...));
if (receivers2.size()) {
futures.push_back(std::async(std::launch::async, somefunc,
receivers2[i][j].get(), Args...));
}
}
}
for (auto &i : futures) {
i.get();
}
}
/** set acquiring flag in shared memory */ /** set acquiring flag in shared memory */
void setAcquiringFlag(bool flag); void setAcquiringFlag(bool flag);
@ -642,10 +274,12 @@ class DetectorImpl : public virtual slsDetectorDefs {
/** return detector shared memory ID */ /** return detector shared memory ID */
int getDetectorId() const; int getDetectorId() const;
/** Free specific shared memory from the command line without creating object */ /** Free specific shared memory from the command line without creating
* object */
static void freeSharedMemory(int detectorId, int moduleId = -1); static void freeSharedMemory(int detectorId, int moduleId = -1);
/** Free all modules from current multi Id shared memory and delete members */ /** Free all modules from current multi Id shared memory and delete members
*/
void freeSharedMemory(); void freeSharedMemory();
/** Get user details of shared memory */ /** Get user details of shared memory */
@ -666,16 +300,16 @@ class DetectorImpl : public virtual slsDetectorDefs {
void setHostname(const std::vector<std::string> &name); void setHostname(const std::vector<std::string> &name);
void setHostname(const std::vector<std::string> &name, void setHostname(const std::vector<std::string> &name,
const std::vector<int> &port); const std::vector<int> &port);
int getNumberofReceiversPerModule() const; int getNumberofReceiversPerModule() const;
void initReceiver(const int udpInterface); void initReceiver(const int udpInterface);
bool isReceiverInitialized(const int udpInterface); bool isReceiverInitialized(const int udpInterface);
void removeReceivers(const int udpInterface); void removeReceivers(const int udpInterface);
void configureReceiver(const int udpInterface, Positions pos, void configureReceiver(const int udpInterface, Positions pos,
const std::string &hostname); const std::string &hostname);
void configureReceiver(const int udpInterface, int module_id, void configureReceiver(const int udpInterface, int module_id,
const std::string &hostname, const int port); const std::string &hostname, const int port);
/** Gets the total number of detectors */ /** Gets the total number of detectors */
int size() const; int size() const;
@ -809,7 +443,7 @@ class DetectorImpl : public virtual slsDetectorDefs {
* @returns total data bytes for updated image * @returns total data bytes for updated image
*/ */
int InsertGapPixels(char *image, char *&gpImage, bool quadEnable, int dr, int InsertGapPixels(char *image, char *&gpImage, bool quadEnable, int dr,
int &nPixelsx, int &nPixelsy); int &nPixelsx, int &nPixelsy);
void printProgress(double progress); void printProgress(double progress);
@ -843,10 +477,13 @@ class DetectorImpl : public virtual slsDetectorDefs {
std::vector<std::unique_ptr<sls::Module>> detectors; std::vector<std::unique_ptr<sls::Module>> detectors;
/** pointers to the Receiver structures, each row for a module */ /** pointers to the Receiver structures, each row for a module */
std::vector<std::vector<std::unique_ptr<sls::Receiver>>> receivers; // std::vector<std::vector<std::unique_ptr<sls::Receiver>>> receivers;
/** for the second udp port [Eiger][Jungfrau] */ /** for the second udp port [Eiger][Jungfrau] */
std::vector<std::vector<std::unique_ptr<sls::Receiver>>> receivers2; std::vector<std::vector<std::unique_ptr<sls::Receiver>>> receivers2;
sls::Container3<std::unique_ptr<sls::Receiver>> receivers;
// sls::Container3<Receiver> receivers;
/** data streaming (down stream) enabled in client (zmq sckets created) */ /** data streaming (down stream) enabled in client (zmq sckets created) */
bool client_downstream{false}; bool client_downstream{false};
@ -881,4 +518,4 @@ class DetectorImpl : public virtual slsDetectorDefs {
void *pCallbackArg{nullptr}; void *pCallbackArg{nullptr};
}; };
}//namespace sls } // namespace sls

View File

@ -0,0 +1,53 @@
#pragma once
#include "Container3.h"
#include <initializer_list>
#include <vector>
namespace sls{
class MaskGenerator {
enum class OperationMode { ALL, ROW, SINGLE };
OperationMode mode_{OperationMode::ALL};
std::vector<size_t> idx0;
size_t x_{0};
size_t y_{0};
size_t z_{0};
public:
MaskGenerator(){};
explicit MaskGenerator(size_t i) : mode_(OperationMode::SINGLE), x_(i) {}
MaskGenerator(size_t i, size_t j)
: mode_(OperationMode::SINGLE), x_(i), y_(j) {}
MaskGenerator(size_t i, size_t j, size_t k)
: mode_(OperationMode::SINGLE), x_(i), y_(j), z_(k) {}
explicit MaskGenerator(const std::vector<size_t> vec)
: mode_(OperationMode::ROW), idx0(vec) {}
template <typename T> Container3<bool> mask(const Container3<T>& cont) {
return mask(cont.shape());
}
Container3<bool> mask(std::array<size_t, 3> shape) {
Container3<bool> m(shape);
switch (mode_) {
case OperationMode::ALL:
for (auto &item : m)
item = true;
break;
case OperationMode::ROW:
for (auto i : idx0) {
m(i, 0, 0) = true;
}
break;
case OperationMode::SINGLE:
m(x_, y_, z_) = true;
break;
}
return m;
}
Container3<bool> mask() { return {}; }
};
} // namespace sls

View File

@ -0,0 +1,81 @@
#pragma once
#include "Container3.h"
#include "Result.h"
#include <future>
#include <vector>
/*
Can't use std::forward<CT>(Args)...) in parallel call since it would
end up moving temporary objects into the first called function
leaving the other ones with moved from args.
*/
namespace experimental{
template <class CT> struct NonDeduced { using type = CT; };
template <typename RT, typename Class, typename... CT>
sls::Result<RT>
Parallel(RT (Class::*func)(CT...) const, const Container3<Class> &objects,
const Container3<bool> &mask, typename NonDeduced<CT>::type... Args) {
std::vector<std::future<RT>> futures;
for (size_t i = 0; i < objects.size(); ++i) {
if (mask[i])
futures.push_back(
std::async(std::launch::async, func, &objects[i], Args...));
}
sls::Result<RT> result;
for (auto &f : futures) {
result.push_back(f.get());
}
return result;
}
template <typename RT, typename Class, typename... CT>
sls::Result<RT>
Parallel(RT (Class::*func)(CT...), const Container3<Class> &objects,
const Container3<bool> &mask, typename NonDeduced<CT>::type... Args) {
std::vector<std::future<RT>> futures;
for (size_t i = 0; i < objects.size(); ++i) {
if (mask[i])
futures.push_back(
std::async(std::launch::async, func, &objects[i], Args...));
}
sls::Result<RT> result;
for (auto &f : futures) {
result.push_back(f.get());
}
return result;
}
template <typename Class, typename... CT>
void Parallel(void (Class::*func)(CT...) const,
const Container3<Class> &objects, const Container3<bool> &mask,
typename NonDeduced<CT>::type... Args) {
std::vector<std::future<void>> futures;
for (size_t i = 0; i < objects.size(); ++i) {
if (mask[i])
futures.push_back(
std::async(std::launch::async, func, &objects[i], Args...));
}
for (auto &f : futures) {
f.get();
}
}
template <typename Class, typename... CT>
void Parallel(void (Class::*func)(CT...), const Container3<Class> &objects,
const Container3<bool> &mask,
typename NonDeduced<CT>::type... Args) {
std::vector<std::future<void>> futures;
for (size_t i = 0; i < objects.size(); ++i) {
if (mask[i])
futures.push_back(
std::async(std::launch::async, func, &objects[i], Args...));
}
for (auto &f : futures)
f.get();
}
}

View File

@ -1,8 +1,8 @@
#pragma once #pragma once
#include "SharedMemory.h" #include "SharedMemory.h"
#include "logger.h" #include "logger.h"
#include "sls_detector_defs.h"
#include "network_utils.h" #include "network_utils.h"
#include "sls_detector_defs.h"
#include <map> #include <map>
@ -11,45 +11,52 @@
namespace sls { namespace sls {
struct sharedReceiver { struct sharedReceiver {
/* FIXED PATTERN FOR STATIC FUNCTIONS. DO NOT CHANGE, ONLY APPEND ------*/ /* FIXED PATTERN FOR STATIC FUNCTIONS. DO NOT CHANGE, ONLY APPEND ------*/
int shmversion; int shmversion;
char hostname[MAX_STR_LENGTH]; char hostname[MAX_STR_LENGTH];
int tcpPort; int tcpPort;
/** END OF FIXED PATTERN -----------------------------------------------*/ /** END OF FIXED PATTERN -----------------------------------------------*/
int stoppedFlag;
int zmqPort;
sls::IpAddr zmqIp;
int stoppedFlag;
int zmqPort;
sls::IpAddr zmqIp;
}; };
class Receiver : public virtual slsDetectorDefs { class Receiver : public virtual slsDetectorDefs {
public: const int receiverId{0};
const int interfaceId{0};
const int moduleId{0};
std::string indexString;
mutable sls::SharedMemory<sharedReceiver> shm{0, 0, 0, 0};
public:
static size_t getNumReceivers(); static size_t getNumReceivers();
// create shm // create shm
explicit Receiver(int detector_id, int module_id, int interface_id, explicit Receiver(int detector_id, int module_id, int interface_id,
int receiver_id, int tcp_port = 0, std::string hostname = "", int receiver_id, int tcp_port = 0,
int zmq_port = 0); std::string hostname = "", int zmq_port = 0);
// open shm // open shm
explicit Receiver(int detector_id, int module_id, int interface_id, explicit Receiver(int detector_id, int module_id, int interface_id,
int receiver_id, bool verify); int receiver_id, bool verify);
virtual ~Receiver(); virtual ~Receiver();
void createIndexString(); void createIndexString();
/************************************************** /**************************************************
* * * *
* Configuration * * Configuration *
* * * *
* ************************************************/ * ************************************************/
/** /**
* Free shared memory and delete shared memory structure * Free shared memory and delete shared memory structure
* occupied by the sharedReceiver structure * occupied by the sharedReceiver structure
* Is only safe to call if one deletes the Receiver object afterward * Is only safe to call if one deletes the Receiver object afterward
* and frees multi shared memory/updates * and frees multi shared memory/updates
* thisMultiDetector->numberOfReceivers * thisMultiDetector->numberOfReceivers
*/ */
void freeSharedMemory(); void freeSharedMemory();
std::string getHostname() const; std::string getHostname() const;
void setHostname(const std::string &hostname); void setHostname(const std::string &hostname);
@ -60,10 +67,10 @@ class Receiver : public virtual slsDetectorDefs {
int64_t getSoftwareVersion() const; int64_t getSoftwareVersion() const;
/************************************************** /**************************************************
* * * *
* Acquisition * * Acquisition *
* * * *
* ************************************************/ * ************************************************/
void start(); void start();
void stop(); void stop();
slsDetectorDefs::runStatus getStatus() const; slsDetectorDefs::runStatus getStatus() const;
@ -75,10 +82,10 @@ class Receiver : public virtual slsDetectorDefs {
uint64_t getCurrentFrameIndex() const; uint64_t getCurrentFrameIndex() const;
/************************************************** /**************************************************
* * * *
* Network Configuration (Detector<->Receiver) * * Network Configuration (Detector<->Receiver) *
* * * *
* ************************************************/ * ************************************************/
sls::MacAddr setUDPIP(const sls::IpAddr ip); sls::MacAddr setUDPIP(const sls::IpAddr ip);
void setUDPPort(const int udpport); void setUDPPort(const int udpport);
int64_t getUDPSocketBufferSize() const; int64_t getUDPSocketBufferSize() const;
@ -86,10 +93,10 @@ class Receiver : public virtual slsDetectorDefs {
int64_t getRealUDPSocketBufferSize() const; int64_t getRealUDPSocketBufferSize() const;
/************************************************** /**************************************************
* * * *
* ZMQ Streaming Parameters (Receiver<->Client)* * ZMQ Streaming Parameters (Receiver<->Client)*
* * * *
* ************************************************/ * ************************************************/
bool getZmq() const; bool getZmq() const;
void setZmq(const bool enable); void setZmq(const bool enable);
int getZmqFrequency() const; int getZmqFrequency() const;
@ -106,13 +113,11 @@ class Receiver : public virtual slsDetectorDefs {
sls::IpAddr getClientZmqIP() const; sls::IpAddr getClientZmqIP() const;
void setClientZmqIP(const sls::IpAddr ip); void setClientZmqIP(const sls::IpAddr ip);
/************************************************** /**************************************************
* * * *
* Receiver Parameters * * Receiver Parameters *
* * * *
* ************************************************/ * ************************************************/
bool getLock() const; bool getLock() const;
void setLock(const bool lock); void setLock(const bool lock);
sls::IpAddr getLastClientIP() const; sls::IpAddr getLastClientIP() const;
@ -132,10 +137,10 @@ class Receiver : public virtual slsDetectorDefs {
void setSilentMode(const bool value); void setSilentMode(const bool value);
/************************************************** /**************************************************
* * * *
* File * * File *
* * * *
* ************************************************/ * ************************************************/
std::string getFilePath() const; std::string getFilePath() const;
void setFilePath(const std::string &path); void setFilePath(const std::string &path);
std::string getFileName() const; std::string getFileName() const;
@ -156,10 +161,10 @@ class Receiver : public virtual slsDetectorDefs {
void setFileOverWrite(const bool value); void setFileOverWrite(const bool value);
/************************************************** /**************************************************
* * * *
* Detector Parameters * * Detector Parameters *
* * * *
* ************************************************/ * ************************************************/
void setNumberOfFrames(const int64_t value); void setNumberOfFrames(const int64_t value);
void setNumberOfTriggers(const int64_t value); void setNumberOfTriggers(const int64_t value);
void setNumberOfBursts(const int64_t value); void setNumberOfBursts(const int64_t value);
@ -181,7 +186,7 @@ class Receiver : public virtual slsDetectorDefs {
void clearROI(); void clearROI();
std::vector<int> getDbitList() const; std::vector<int> getDbitList() const;
/** digital data bits enable (CTB only) */ /** digital data bits enable (CTB only) */
void setDbitList(const std::vector<int>& list); void setDbitList(const std::vector<int> &list);
int getDbitOffset() const; int getDbitOffset() const;
/** Set digital data offset in bytes (CTB only) */ /** Set digital data offset in bytes (CTB only) */
void setDbitOffset(const int value); void setDbitOffset(const int value);
@ -190,22 +195,22 @@ class Receiver : public virtual slsDetectorDefs {
void setCounterMask(const uint32_t mask); void setCounterMask(const uint32_t mask);
/************************************************** /**************************************************
* * * *
* Json * * Json *
* * * *
* ************************************************/ * ************************************************/
std::map<std::string, std::string> getAdditionalJsonHeader() const; std::map<std::string, std::string> getAdditionalJsonHeader() const;
/** empty vector deletes entire additional json header */ /** empty vector deletes entire additional json header */
void setAdditionalJsonHeader(const std::map<std::string, std::string> &jsonHeader); void setAdditionalJsonHeader(
const std::map<std::string, std::string> &jsonHeader);
std::string getAdditionalJsonParameter(const std::string &key) const; std::string getAdditionalJsonParameter(const std::string &key) const;
/** Sets the value for the additional json header parameter key if found, /** Sets the value for the additional json header parameter key if found,
else append it. If value empty, then deletes parameter */ else append it. If value empty, then deletes parameter */
void setAdditionalJsonParameter(const std::string &key, const std::string &value); void setAdditionalJsonParameter(const std::string &key,
const std::string &value);
private:
private:
void sendToReceiver(int fnum, const void *args, size_t args_size, void sendToReceiver(int fnum, const void *args, size_t args_size,
void *retval, size_t retval_size); void *retval, size_t retval_size);
@ -230,11 +235,9 @@ class Receiver : public virtual slsDetectorDefs {
template <typename Ret> template <typename Ret>
void sendToReceiver(int fnum, std::nullptr_t, Ret &retval) const; void sendToReceiver(int fnum, std::nullptr_t, Ret &retval) const;
template <typename Ret> template <typename Ret> Ret sendToReceiver(int fnum);
Ret sendToReceiver(int fnum);
template <typename Ret> template <typename Ret> Ret sendToReceiver(int fnum) const;
Ret sendToReceiver(int fnum) const;
template <typename Ret, typename Arg> template <typename Ret, typename Arg>
Ret sendToReceiver(int fnum, const Arg &args); Ret sendToReceiver(int fnum, const Arg &args);
@ -243,11 +246,6 @@ class Receiver : public virtual slsDetectorDefs {
Ret sendToReceiver(int fnum, const Arg &args) const; Ret sendToReceiver(int fnum, const Arg &args) const;
void checkVersionCompatibility(); void checkVersionCompatibility();
const int receiverId{0};
const int interfaceId{0};
const int moduleId{0};
std::string indexString;
mutable sls::SharedMemory<sharedReceiver> shm{0, 0, 0, 0};
}; };
} // sls } // namespace sls

View File

@ -13,6 +13,9 @@ target_sources(tests PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/test-CmdProxy-global.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test-CmdProxy-global.cpp
${CMAKE_CURRENT_SOURCE_DIR}/test-Result.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test-Result.cpp
${CMAKE_CURRENT_SOURCE_DIR}/test-CmdParser.cpp ${CMAKE_CURRENT_SOURCE_DIR}/test-CmdParser.cpp
${CMAKE_CURRENT_SOURCE_DIR}/test-Container3.cpp
${CMAKE_CURRENT_SOURCE_DIR}/test-MaskGenerator.cpp
${CMAKE_CURRENT_SOURCE_DIR}/test-Receiver.cpp
) )
target_include_directories(tests PUBLIC "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../src>") target_include_directories(tests PUBLIC "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../src>")

View File

@ -144,10 +144,10 @@ TEST_CASE("rx_printconfig", "[.cmd][.rx][.new]") {
/* Receiver Config */ /* Receiver Config */
TEST_CASE("rx_hostname", "[.cmd][.rx][.new]") { // TEST_CASE("rx_hostname", "[.cmd][.rx][.new]") {
Detector det; // Detector det;
CmdProxy proxy(&det); // CmdProxy proxy(&det);
auto prev_val = det.getRxHostname(); // auto prev_val = det.getRxHostname();
// Cannot set rx_hostname (will reset parameters in rxr and no shm variables to update) // Cannot set rx_hostname (will reset parameters in rxr and no shm variables to update)
// { // {
@ -168,37 +168,37 @@ TEST_CASE("rx_hostname", "[.cmd][.rx][.new]") {
// for (int i = 0; i != det.size(); ++i) { // for (int i = 0; i != det.size(); ++i) {
// det.setRxHostname(prev_val[i], {i}); // det.setRxHostname(prev_val[i], {i});
// } // }
{ // {
std::ostringstream oss; // std::ostringstream oss;
proxy.Call("rx_hostname", {}, 0, GET, oss); // proxy.Call("rx_hostname", {}, 0, GET, oss);
REQUIRE(oss.str() == "rx_hostname " + prev_val[0] + "\n"); // REQUIRE(oss.str() == "rx_hostname " + prev_val[0] + "\n");
} // }
} // }
TEST_CASE("rx_tcpport", "[.cmd][.rx][.new]") { // TEST_CASE("rx_tcpport", "[.cmd][.rx][.new]") {
Detector det; // Detector det;
CmdProxy proxy(&det); // CmdProxy proxy(&det);
auto prev_val = det.getRxPort(); // auto prev_val = det.getRxPort();
int port = 3500; // int port = 3500;
proxy.Call("rx_tcpport", {std::to_string(port)}, -1, PUT); // proxy.Call("rx_tcpport", {std::to_string(port)}, -1, PUT);
for (int i = 0; i != det.size(); ++i) { // for (int i = 0; i != det.size(); ++i) {
std::ostringstream oss; // std::ostringstream oss;
proxy.Call("rx_tcpport", {}, i, GET, oss); // proxy.Call("rx_tcpport", {}, i, GET, oss);
REQUIRE(oss.str() == "rx_tcpport " + std::to_string(port + i) + '\n'); // REQUIRE(oss.str() == "rx_tcpport " + std::to_string(port + i) + '\n');
} // }
REQUIRE_THROWS(proxy.Call("rx_tcpport", {"15"}, -1, PUT)); // REQUIRE_THROWS(proxy.Call("rx_tcpport", {"15"}, -1, PUT));
port = 5754; // port = 5754;
proxy.Call("rx_tcpport", {std::to_string(port)}, -1, PUT); // proxy.Call("rx_tcpport", {std::to_string(port)}, -1, PUT);
for (int i = 0; i != det.size(); ++i) { // for (int i = 0; i != det.size(); ++i) {
std::ostringstream oss; // std::ostringstream oss;
proxy.Call("rx_tcpport", {}, i, GET, oss); // proxy.Call("rx_tcpport", {}, i, GET, oss);
REQUIRE(oss.str() == "rx_tcpport " + std::to_string(port + i) + '\n'); // REQUIRE(oss.str() == "rx_tcpport " + std::to_string(port + i) + '\n');
} // }
for (int i = 0; i != det.size(); ++i) { // for (int i = 0; i != det.size(); ++i) {
det.setRxPort(prev_val[i], i); // det.setRxPort(prev_val[i], i);
} // }
} // }
TEST_CASE("rx_fifodepth", "[.cmd][.rx][.new]") { TEST_CASE("rx_fifodepth", "[.cmd][.rx][.new]") {
Detector det; Detector det;

View File

@ -0,0 +1,330 @@
#include "catch.hpp"
#include "Container3.h"
using sls::Container3;
TEST_CASE("Default construction gives container of size 0") {
Container3<int> c;
CHECK(c.size() == 0);
CHECK(c.size(0) == 0);
CHECK(c.size(1) == 0);
CHECK(c.size(2) == 0);
}
TEST_CASE("Construct container with size") {
Container3<int> c(3, 4, 5);
CHECK(c.size() == 3 * 4 * 5);
CHECK(c.size(0) == 3);
CHECK(c.size(1) == 4);
CHECK(c.size(2) == 5);
}
TEST_CASE("Constructor with default value") {
constexpr int val = 7;
Container3<int> c({1, 1, 5}, val);
for (size_t i = 0; i < c.size(); ++i) {
CHECK(c[i] == val);
}
}
TEST_CASE("Container3 can be iterated with range for") {
constexpr int val = 7;
Container3<int> c({1, 1, 5}, val);
for (const auto& item : c) {
CHECK(item == val);
}
}
TEST_CASE(
"() gives access to an element for both const and non const objects") {
Container3<int> c{1, 1, 1};
CHECK(c(0, 0, 0) == 0);
const Container3<int> c2{1, 1, 1};
CHECK(c2(0, 0, 0) == 0);
}
TEST_CASE("() can be used to modify object") {
Container3<int> c{1, 1, 1};
c(0, 0, 0) = 7;
CHECK(c(0, 0, 0) == 7);
}
TEST_CASE("at() can be used to modify object") {
Container3<int> c{1, 1, 1};
c.at(0, 0, 0) = 7;
CHECK(c(0, 0, 0) == 7);
}
TEST_CASE("at throws outsize range for both const and non const objects") {
Container3<int> c{1, 1, 1};
const Container3<double> c2{1, 1, 1};
CHECK_THROWS(c.at(5, 5, 5));
CHECK_THROWS(c2.at(5, 5, 5));
}
TEST_CASE("Set values") {
Container3<int> c(2, 3, 4);
size_t count = 0;
for (size_t i = 0; i < c.size(0); ++i) {
for (size_t j = 0; j < c.size(1); ++j) {
for (size_t k = 0; k < c.size(2); ++k) {
c(i, j, k) = count;
CHECK(c(i, j, k) == count);
CHECK(c[count] == count);
++count;
}
}
}
}
TEST_CASE("Check if index is valid") {
Container3<int> c(2, 3, 4);
CHECK(c.is_valid_index(1,1,1));
CHECK(c.is_valid_index(1,2,3));
CHECK(c.is_valid_index(1,2,3));
CHECK_FALSE(c.is_valid_index(1,7,1));
CHECK_FALSE(c.is_valid_index(1,1,4));
CHECK_FALSE(c.is_valid_index(3,1,1));
}
TEST_CASE("Copy data from one container to another") {
Container3<int> c(2, 1, 2);
for (size_t i = 0; i < c.size(); ++i) {
c[i] = i;
}
Container3<int> c2(3, 3, 3);
c2.copy_data(c);
for (size_t i = 0; i < c.size(0); ++i) {
for (size_t j = 0; j < c.size(1); ++j) {
for (size_t k = 0; k < c.size(2); ++k) {
CHECK(c2(i, j, k) == c(i, j, k));
}
}
}
}
TEST_CASE("Copy assignment copies values") {
Container3<int> c(2, 3, 4);
size_t count = 0;
for (size_t i = 0; i < c.size(0); ++i) {
for (size_t j = 0; j < c.size(1); ++j) {
for (size_t k = 0; k < c.size(2); ++k) {
c(i, j, k) = count;
CHECK(c(i, j, k) == count);
CHECK(c[count] == count);
++count;
}
}
}
Container3<int> c2;
c2 = c;
count = 0;
for (size_t i = 0; i < c.size(0); ++i) {
for (size_t j = 0; j < c.size(1); ++j) {
for (size_t k = 0; k < c.size(2); ++k) {
c2(i, j, k) = count;
CHECK(c(i, j, k) == count);
CHECK(c[count] == count);
++count;
}
}
}
}
TEST_CASE("Copy constructor copies values") {
Container3<int> c(18, 23, 4);
size_t count = 0;
for (size_t i = 0; i < c.size(0); ++i) {
for (size_t j = 0; j < c.size(1); ++j) {
for (size_t k = 0; k < c.size(2); ++k) {
c(i, j, k) = count;
CHECK(c(i, j, k) == count);
CHECK(c[count] == count);
++count;
}
}
}
Container3<int> c2 = c;
count = 0;
for (size_t i = 0; i < c.size(0); ++i) {
for (size_t j = 0; j < c.size(1); ++j) {
for (size_t k = 0; k < c.size(2); ++k) {
c2(i, j, k) = count;
CHECK(c(i, j, k) == count);
CHECK(c[count] == count);
++count;
}
}
}
}
TEST_CASE("Copy assignment create disjoint objects") {
Container3<int> c(2, 3, 4);
Container3<int> c2;
c2 = c;
c2(1, 1, 1) = 72;
CHECK(c2(1, 1, 1) == 72);
CHECK(c(1, 1, 1) != 72);
}
TEST_CASE("Move constructor") {
Container3<int> c(2, 3, 4);
// explicit move only for testing
Container3<int> c2(std::move(c));
// Moved from object is in an ok state
CHECK(c.data() == nullptr);
for (size_t i = 0; i < 3; ++i) {
CHECK(c.size(i) == 0);
}
// new object has the correct size and owns some data
CHECK(c2.data() != nullptr);
CHECK(c2.size(0) == 2);
CHECK(c2.size(1) == 3);
CHECK(c2.size(2) == 4);
}
TEST_CASE("Move assignment ") {
Container3<int> c(2, 3, 4);
Container3<int> c2(5, 5, 5);
c2 = std::move(c);
// Moved from object is in an ok state
CHECK(c.data() == nullptr);
for (size_t i = 0; i < 3; ++i) {
CHECK(c.size(i) == 0);
}
// new object has the correct size and owns some data
CHECK(c2.data() != nullptr);
CHECK(c2.size(0) == 2);
CHECK(c2.size(1) == 3);
CHECK(c2.size(2) == 4);
}
TEST_CASE("Resize to a larger size") {
Container3<int> c(2, 3, 4);
// Assign values
auto shape = c.shape();
CHECK(shape == std::array<size_t, 3>{2,3,4});
size_t count = 0;
for (size_t i = 0; i < shape[0]; ++i) {
for (size_t j = 0; j < shape[1]; ++j) {
for (size_t k = 0; k < shape[2]; ++k) {
c(i, j, k) = count;
CHECK(c(i, j, k) == count);
++count;
}
}
}
c.resize(3, 4, 5);
CHECK(c.shape() == std::array<size_t, 3>{3,4,5});
// Values should remain the same in the old region
count = 0;
for (size_t i = 0; i < shape[0]; ++i) {
for (size_t j = 0; j < shape[1]; ++j) {
for (size_t k = 0; k < shape[2]; ++k) {
CHECK(c(i, j, k) == count);
++count;
}
}
}
// Default constructed values outsize
CHECK(c(2, 2, 2) == 0);
CHECK(c(2, 3, 2) == 0);
}
TEST_CASE("Inserting values outside range with a empty receiver") {
Container3<int> c;
c.at_can_grow(0, 0, 0) = 5;
CHECK(c(0, 0, 0) == 5);
CHECK(c.size() == 1);
CHECK(c.size(0) == 1);
CHECK(c.size(1) == 1);
CHECK(c.size(2) == 1);
c.at_can_grow(0, 0, 1) = 6;
CHECK(c.size() == 2);
CHECK(c.size(0) == 1);
CHECK(c.size(1) == 1);
CHECK(c.size(2) == 2);
}
TEST_CASE("Inserting a value outside of the current size") {
Container3<int> c{1, 2, 3};
for (size_t i = 0; i < c.size(); ++i) {
c[i] = i;
}
Container3<int> copy;
copy = c;
c.at_can_grow(2, 2, 2) = 7;
CHECK(c.size(0) == 3);
CHECK(c.size(1) == 3);
CHECK(c.size(2) == 3);
for (size_t i = 0; i < copy.size(0); ++i) {
for (size_t j = 0; j < copy.size(0); ++j) {
for (size_t k = 0; k < copy.size(0); ++k) {
CHECK(copy(i, j, k) == c(i, j, k));
}
}
}
}
TEST_CASE("Clear sets size to zero and clears memory"){
Container3<int> c(5,5,5);
CHECK(c.shape() == std::array<size_t, 3>{5,5,5});
c.clear();
CHECK(c.shape() == std::array<size_t, 3>{0,0,0});
CHECK(c.size() == 0);
}
TEST_CASE("Put unique pointer in Container3"){
Container3<std::unique_ptr<int>> c(3,1,1);
c(0,0,0) = std::unique_ptr<int>(new int);
CHECK(c(0,0,0) != nullptr);
CHECK(c(1,0,0) == nullptr);
CHECK(c(2,0,0) == nullptr);
*c(0,0,0) = 5;
CHECK(*c(0,0,0) == 5);
}
TEST_CASE("Resize with unique ptr"){
Container3<std::unique_ptr<int>> c(2,1,1);
c(1,0,0) = std::unique_ptr<int>(new int);
*c(1,0,0) = 7;
c.resize(3,1,1);
CHECK(c.size() == 3);
CHECK(*c(1,0,0) == 7);
}

View File

@ -0,0 +1,84 @@
#include "catch.hpp"
#include "MaskGenerator.h"
using sls::MaskGenerator;
using sls::Container3;
TEST_CASE("Default construction gives an mask of size 0") {
auto m = MaskGenerator().mask();
CHECK(m.shape() == std::array<size_t, 3>{0, 0, 0});
CHECK(m.size() == 0);
}
TEST_CASE("Default behaviour with shape is all true and same shape") {
Container3<int> c{1, 2, 3};
auto m = MaskGenerator().mask(c.shape());
CHECK(m.shape() == std::array<size_t, 3>{1, 2, 3});
for (auto &i : m)
CHECK(i == true);
}
TEST_CASE("With std::vector we give back the first index and 0, 0") {
Container3<int> rec{14, 1, 3};
auto m = MaskGenerator(std::vector<size_t>{0, 3, 5}).mask(rec.shape());
CHECK(m.shape() == std::array<size_t, 3>{14, 1, 3});
CHECK(m(0, 0, 0) == true);
CHECK(m(3, 0, 0) == true);
CHECK(m(5, 0, 0) == true);
std::vector<size_t> positions(rec.size(0));
std::iota(begin(positions), end(positions), 0);
positions.erase(std::remove(positions.begin(), positions.end(), 0),
positions.end());
positions.erase(std::remove(positions.begin(), positions.end(), 3),
positions.end());
positions.erase(std::remove(positions.begin(), positions.end(), 5),
positions.end());
for (auto i : positions) {
for (size_t j = 0; j < rec.size(1); ++j) {
for (size_t k = 0; k < rec.size(2); ++k) {
REQUIRE(m(i, j, k) == false);
}
}
}
}
TEST_CASE("With single number we get that detector x,0,0") {
Container3<int> rec{2, 2, 1};
auto m = MaskGenerator(1).mask(rec);
CHECK(m(1, 0, 0) == true);
CHECK(m(1, 1, 0) == false);
CHECK(m(0, 1, 0) == false);
CHECK(m(0, 0, 0) == false);
}
TEST_CASE("With two numbers we get x,y,0") {
Container3<int> rec{2, 2, 1};
auto m = MaskGenerator(1, 1).mask(rec);
CHECK(m(1, 1, 0) == true);
CHECK(m(1, 0, 0) == false);
CHECK(m(0, 1, 0) == false);
CHECK(m(0, 0, 0) == false);
}
TEST_CASE("With three numbers we get x,y,z") {
Container3<int> rec{9, 7, 5};
auto m = MaskGenerator(3, 4, 1).mask(rec);
REQUIRE(m.shape() == rec.shape());
REQUIRE(m(3, 4, 1) == true);
for (size_t i = 0; i < rec.size(0); ++i) {
for (size_t j = 0; j < rec.size(1); ++j) {
for (size_t k = 0; k < rec.size(2); ++k) {
if (!(i == 3 && j == 4 && k == 1)) {
REQUIRE(m(i, j, k) == false);
}
}
}
}
}

View File

@ -0,0 +1,10 @@
#include "catch.hpp"
#include "Container3.h"
#include "Receiver.h"
using sls::Receiver;
// TEST_CASE("Receiver can be default constructed"){
// }