* row and column for jungfrau mixed up

* multi module jungfrau sync must do slaves first then master for start acquisition and send software trigger, and master first and then slaves for stopacquisition

* non blocking to slaves first and only then blocking/nonblocking to the master for sending software trigger(jungfrau multi mod sync)

* fixed get/set timing jungfrau when sync enabled, getsync during blocking acquire (for trigger or stop) will get stuck as it should ask the stop server

* switching between 1 and 2 interfaces did not set gui/client zmq port properly. Resulted in dummy streaming forever. fixed

* formatting, refactoring: const & for positions, multi mod M3 stop first master first

* adding missing cstdint for gcc 13

* Refactoring handle sync out, handling synchronization also for softwaretrigger for m3, for start/sync/stop for g2/g1

---------

Co-authored-by: Erik Frojdh <erik.frojdh@gmail.com>
This commit is contained in:
2023-05-08 12:11:19 +02:00
committed by GitHub
parent 77c558a7be
commit 8833ccf5cc
12 changed files with 164 additions and 104 deletions

View File

@ -855,7 +855,7 @@ void Detector::stopDetector(Positions pos) {
throw RuntimeError(
"Could not stop detector. Returned error status.");
}
pimpl->Parallel(&Module::stopAcquisition, pos);
pimpl->stopDetector(pos);
status = getDetectorStatus().squash(defs::runStatus::RUNNING);
++retries;
@ -914,7 +914,7 @@ void Detector::setNextFrameNumber(uint64_t value, Positions pos) {
}
void Detector::sendSoftwareTrigger(const bool block, Positions pos) {
pimpl->Parallel(&Module::sendSoftwareTrigger, pos, block);
pimpl->sendSoftwareTrigger(block, pos);
}
Result<defs::scanParameters> Detector::getScan(Positions pos) const {
@ -951,18 +951,23 @@ void Detector::setNumberofUDPInterfaces(int n, Positions pos) {
}
void Detector::setNumberofUDPInterfaces_(int n, Positions pos) {
if (!size()) {
throw RuntimeError("No modules added.");
}
bool previouslyClientStreaming = pimpl->getDataStreamingToClient();
int clientStartingPort = getClientZmqPort({0}).squash(0);
bool useReceiver = getUseReceiverFlag().squash(false);
bool previouslyReceiverStreaming = false;
int startingPort = 0;
int rxStartingPort = 0;
if (useReceiver) {
previouslyReceiverStreaming = getRxZmqDataStream(pos).squash(true);
startingPort = getRxZmqPort({0}).squash(0);
rxStartingPort = getRxZmqPort({0}).squash(0);
}
pimpl->Parallel(&Module::setNumberofUDPInterfaces, pos, n);
// ensure receiver zmq socket ports are multiplied by 2 (2 interfaces)
if (getUseReceiverFlag().squash(false) && size()) {
setRxZmqPort(startingPort, -1);
setClientZmqPort(clientStartingPort, -1);
if (getUseReceiverFlag().squash(false)) {
setRxZmqPort(rxStartingPort, -1);
}
// redo the zmq sockets if enabled
if (previouslyClientStreaming) {

View File

@ -769,7 +769,7 @@ void DetectorImpl::readFrameFromReceiver() {
int nDetActualPixelsY = nDetPixelsY;
if (gapPixels) {
int n = InsertGapPixels(multiframe.get(), multigappixels,
int n = insertGapPixels(multiframe.get(), multigappixels,
quadEnable, dynamicRange,
nDetActualPixelsX, nDetActualPixelsY);
callbackImage = multigappixels;
@ -808,7 +808,7 @@ void DetectorImpl::readFrameFromReceiver() {
delete[] multigappixels;
}
int DetectorImpl::InsertGapPixels(char *image, char *&gpImage, bool quadEnable,
int DetectorImpl::insertGapPixels(char *image, char *&gpImage, bool quadEnable,
int dr, int &nPixelsx, int &nPixelsy) {
LOG(logDEBUG) << "Insert Gap pixels:"
@ -1256,43 +1256,104 @@ int DetectorImpl::acquire() {
return OK;
}
void DetectorImpl::startAcquisition(bool blocking, std::vector<int> positions) {
// handle Mythen3 synchronization
if (shm()->detType == defs::MYTHEN3 && size() > 1) {
std::vector<int> master;
std::vector<int> slaves;
if (positions.empty() ||
(positions.size() == 1 && positions[0] == -1)) {
positions.resize(modules.size());
std::iota(begin(positions), end(positions), 0);
}
// could be all slaves in positions
slaves.reserve(positions.size());
auto is_master = Parallel(&Module::isMaster, positions);
for (size_t i : positions) {
if (is_master[i])
master.push_back(i);
else
slaves.push_back(i);
bool DetectorImpl::handleSynchronization(Positions pos) {
bool handleSync = false;
// multi module m3 or multi module sync enabled jungfrau
if (size() > 1) {
switch (shm()->detType) {
case defs::MYTHEN3:
case defs::GOTTHARD2:
case defs::GOTTHARD:
handleSync = true;
break;
case defs::JUNGFRAU:
if (Parallel(&Module::getSynchronizationFromStopServer, pos)
.tsquash("Inconsistent synchronization among modules")) {
handleSync = true;
}
break;
default:
break;
}
}
return handleSync;
}
void DetectorImpl::getMasterSlaveList(std::vector<int> positions,
std::vector<int> &masters,
std::vector<int> &slaves) {
// expand positions list
if (positions.empty() || (positions.size() == 1 && positions[0] == -1)) {
positions.resize(modules.size());
std::iota(begin(positions), end(positions), 0);
}
// could be all slaves in positions
slaves.reserve(positions.size());
auto is_master = Parallel(&Module::isMaster, positions);
for (size_t i : positions) {
if (is_master[i])
masters.push_back(i);
else
slaves.push_back(i);
}
}
void DetectorImpl::startAcquisition(const bool blocking, Positions pos) {
// slaves first
if (handleSynchronization(pos)) {
std::vector<int> masters;
std::vector<int> slaves;
getMasterSlaveList(pos, masters, slaves);
if (!slaves.empty()) {
Parallel(&Module::startAcquisition, slaves);
}
if (!master.empty()) {
if (blocking) {
Parallel(&Module::startAndReadAll, master);
} else {
Parallel(&Module::startAcquisition, master);
}
}
} else {
if (blocking) {
Parallel(&Module::startAndReadAll, positions);
} else {
Parallel(&Module::startAcquisition, positions);
if (!masters.empty()) {
Parallel((blocking ? &Module::startAndReadAll
: &Module::startAcquisition),
pos);
}
}
// all in parallel
else {
Parallel(
(blocking ? &Module::startAndReadAll : &Module::startAcquisition),
pos);
}
}
void DetectorImpl::sendSoftwareTrigger(const bool block, Positions pos) {
// slaves first
if (handleSynchronization(pos)) {
std::vector<int> masters;
std::vector<int> slaves;
getMasterSlaveList(pos, masters, slaves);
if (!slaves.empty())
Parallel(&Module::sendSoftwareTrigger, slaves, false);
if (!masters.empty())
Parallel(&Module::sendSoftwareTrigger, masters, block);
}
// all in parallel
else {
Parallel(&Module::sendSoftwareTrigger, pos, block);
}
}
void DetectorImpl::stopDetector(Positions pos) {
// masters first
if (handleSynchronization(pos)) {
std::vector<int> masters;
std::vector<int> slaves;
getMasterSlaveList(pos, masters, slaves);
if (!masters.empty())
Parallel(&Module::stopAcquisition, masters);
if (!slaves.empty())
Parallel(&Module::stopAcquisition, slaves);
}
// all in parallel
else {
Parallel(&Module::stopAcquisition, pos);
}
}
void DetectorImpl::printProgress(double progress) {
@ -1397,7 +1458,8 @@ std::vector<char> DetectorImpl::readProgrammingFile(const std::string &fname) {
default:
throw RuntimeError(
"Unknown detector type. Did the 'hostname' command execute "
"successfully? Or use update mode in the detector server side.");
"successfully? Or use update mode in the detector server "
"side.");
}
LOG(logINFO) << "This can take awhile. Please be patient.";
@ -1425,10 +1487,9 @@ std::vector<char> DetectorImpl::readProgrammingFile(const std::string &fname) {
int dst = mkstemp(destfname); // create temporary file and open it in r/w
if (dst == -1) {
fclose(src);
throw RuntimeError(
std::string(
"Could not create destination file in /tmp for programming: ") +
destfname);
throw RuntimeError(std::string("Could not create destination file "
"in /tmp for programming: ") +
destfname);
}
// convert src to dst rawbin
@ -1480,8 +1541,8 @@ std::vector<char> DetectorImpl::readProgrammingFile(const std::string &fname) {
}
// validate pof: read less than footer offset
if (isPof && dstFilePos < pofFooterOfst) {
throw RuntimeError(
"Could not convert programming file. EOF before end of flash");
throw RuntimeError("Could not convert programming file. EOF "
"before end of flash");
}
}
if (fclose(src) != 0) {

View File

@ -278,7 +278,13 @@ class DetectorImpl : public virtual slsDetectorDefs {
int acquire();
/** also takes care of master and slave for multi module mythen */
void startAcquisition(bool blocking, std::vector<int> positions);
void startAcquisition(const bool blocking, Positions pos);
/** also takes care of master and slave for multi module mythen */
void sendSoftwareTrigger(const bool block, Positions pos);
/** also takes care of master and slave for multi module mythen */
void stopDetector(Positions pos);
/**
* Combines data from all readouts and gives it to the gui
@ -368,9 +374,14 @@ class DetectorImpl : public virtual slsDetectorDefs {
* @param nPixelsy number of pixels in Y axis (updated)
* @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);
bool handleSynchronization(Positions pos);
void getMasterSlaveList(std::vector<int> positions,
std::vector<int> &masters,
std::vector<int> &slaves);
void printProgress(double progress);
void startProcessingThread(bool receiver);

View File

@ -538,8 +538,15 @@ bool Module::getSynchronization() const {
return sendToDetector<int>(F_GET_SYNCHRONIZATION);
}
bool Module::getSynchronizationFromStopServer() const {
return sendToDetectorStop<int>(F_GET_SYNCHRONIZATION);
}
void Module::setSynchronization(const bool value) {
sendToDetector(F_SET_SYNCHRONIZATION, static_cast<int>(value), nullptr);
// to deal with virtual servers as well
// (get sync from stop server during blocking acquisition)
sendToDetectorStop(F_SET_SYNCHRONIZATION, static_cast<int>(value), nullptr);
}
std::vector<int> Module::getBadChannels() const {

View File

@ -129,6 +129,7 @@ class Module : public virtual slsDetectorDefs {
bool isMaster() const;
void setMaster(const bool master);
bool getSynchronization() const;
bool getSynchronizationFromStopServer() const;
void setSynchronization(const bool value);
std::vector<int> getBadChannels() const;
void setBadChannels(std::vector<int> list);