diff --git a/slsDetectorSoftware/include/sls/Detector.h b/slsDetectorSoftware/include/sls/Detector.h index 10a3acba6..86e8d2372 100644 --- a/slsDetectorSoftware/include/sls/Detector.h +++ b/slsDetectorSoftware/include/sls/Detector.h @@ -714,7 +714,7 @@ class Detector { * restarts client and receiver zmq sockets if zmq streaming enabled. \n * [Gotthard2] second interface enabled to send veto information via 10Gbps * for debugging. By default, if veto enabled, it is sent via 2.5 gbps - * interface. */ + * interface. \nSetting this resets the receiver roi */ void setNumberofUDPInterfaces(int n, Positions pos = {}); /** [Jungfrau][Moench] */ @@ -995,7 +995,8 @@ class Detector { /** Returns port level ROIs. Max 2 ports and hence max 2 elements per readout */ std::vector getRxROI(int module_id) const; - /** only at multi module level without gap pixels. At most, 1 ROI per UDP port */ + /** only at multi module level without gap pixels. At most, 1 ROI per UDP + * port. Setting number of udp interfaces will clear the roi */ void setRxROI(const std::vector &args); void clearRxROI(); diff --git a/slsDetectorSoftware/src/CallerSpecial.cpp b/slsDetectorSoftware/src/CallerSpecial.cpp index 946f92570..4d921ef3a 100644 --- a/slsDetectorSoftware/src/CallerSpecial.cpp +++ b/slsDetectorSoftware/src/CallerSpecial.cpp @@ -734,7 +734,8 @@ std::string Caller::rx_roi(int action) { "Only allowed to set at multi module level and without gap " "ixels.\n\n\t" + "One can get rx_roi also at port level, by specifying the module id " - "and it will return the roi for each port.\n"; + "and it will return the roi for each port.\n" + "Setting number of udp interfaces will clear the rx_roi\n"; if (action == defs::HELP_ACTION) { os << helpMessage; } else if (action == defs::GET_ACTION) { diff --git a/slsDetectorSoftware/src/Module.cpp b/slsDetectorSoftware/src/Module.cpp index 6ee96af9e..c1c65add3 100644 --- a/slsDetectorSoftware/src/Module.cpp +++ b/slsDetectorSoftware/src/Module.cpp @@ -1534,8 +1534,10 @@ std::vector Module::getRxROI() const { std::vector retval(nPorts); if (nPorts > 0) client.Receive(retval); - if (nPorts > shm()->numUDPInterfaces) { - throw RuntimeError("Invalid number of rois: " + std::to_string(nPorts) + ". Max: " + std::to_string(shm()->numUDPInterfaces)); + if (nPorts != shm()->numUDPInterfaces) { + throw RuntimeError( + "Invalid number of rois: " + std::to_string(nPorts) + + ". Expected: " + std::to_string(shm()->numUDPInterfaces)); } LOG(logDEBUG1) << "ROI of Receiver" << moduleIndex << ": " << ToString(retval); @@ -1548,11 +1550,11 @@ void Module::setRxROI(const std::vector &portRois) { if (!shm()->useReceiverFlag) { throw RuntimeError("No receiver to set ROI."); } - if ((int)portRois.size() > shm()->numUDPInterfaces) { - throw RuntimeError("Invalid number of ROIs: " + - std::to_string(portRois.size()) + - ". Max: " + std::to_string(shm()->numUDPInterfaces)); - } + if ((int)portRois.size() != shm()->numUDPInterfaces) { + throw RuntimeError( + "Invalid number of ROIs: " + std::to_string(portRois.size()) + + ". Expected: " + std::to_string(shm()->numUDPInterfaces)); + } // check number of ports auto client = ReceiverSocket(shm()->rxHostname, shm()->rxTCPPort); client.Send(F_RECEIVER_SET_RECEIVER_ROI); @@ -1577,6 +1579,10 @@ void Module::setRxROIMetadata(const std::vector &args) { receiver.Send(size); if (size > 0) receiver.Send(args); + if (size < 1) { + throw RuntimeError("Invalid number of ROI metadata: " + + std::to_string(size) + ". Min: 1."); + } if (receiver.Receive() == FAIL) { throw ReceiverError("Receiver " + std::to_string(moduleIndex) + " returned error: " + receiver.readErrorMessage()); diff --git a/slsReceiverSoftware/src/ClientInterface.cpp b/slsReceiverSoftware/src/ClientInterface.cpp index 37611ad5d..d0336ba49 100644 --- a/slsReceiverSoftware/src/ClientInterface.cpp +++ b/slsReceiverSoftware/src/ClientInterface.cpp @@ -1696,6 +1696,11 @@ int ClientInterface::get_receiver_roi(Interface &socket) { auto retvals = impl()->getPortROIs(); LOG(logDEBUG1) << "Receiver roi retval:" << ToString(retvals); auto size = static_cast(retvals.size()); + if (size != impl()->getNumberofUDPInterfaces()) { + throw RuntimeError("Invalid number of ROIs received: " + + std::to_string(size) + ". Expected: " + + std::to_string(impl()->getNumberofUDPInterfaces())); + } socket.Send(size); if (size > 0) socket.Send(retvals); @@ -1708,9 +1713,9 @@ int ClientInterface::set_receiver_roi(Interface &socket) { if (roiSize > 0) { socket.Receive(args); } - if (roiSize > impl()->getNumberofUDPInterfaces()) { + if (roiSize != impl()->getNumberofUDPInterfaces()) { throw RuntimeError("Invalid number of ROIs received: " + - std::to_string(roiSize) + ". Max: " + + std::to_string(roiSize) + ". Expected: " + std::to_string(impl()->getNumberofUDPInterfaces())); } if (detType == CHIPTESTBOARD || detType == XILINX_CHIPTESTBOARD) @@ -1730,6 +1735,10 @@ int ClientInterface::set_receiver_roi(Interface &socket) { int ClientInterface::set_receiver_roi_metadata(Interface &socket) { auto roiSize = socket.Receive(); LOG(logDEBUG1) << "Number of ReceiverROI metadata: " << roiSize; + if (roiSize < 1) { + throw RuntimeError("Invalid number of ROIs received: " + + std::to_string(roiSize) + ". Min: 1."); + } std::vector rois(roiSize); if (roiSize > 0) { socket.Receive(rois); diff --git a/slsReceiverSoftware/src/DataProcessor.cpp b/slsReceiverSoftware/src/DataProcessor.cpp index 64ae23547..1beac1bcc 100644 --- a/slsReceiverSoftware/src/DataProcessor.cpp +++ b/slsReceiverSoftware/src/DataProcessor.cpp @@ -208,10 +208,10 @@ std::string DataProcessor::CreateVirtualFile( const int modulePos, const int numModX, const int numModY, std::mutex *hdf5LibMutex) { - if (!multiRoiMetadata.empty() && generalData->dynamicRange == 4) { + /*if (!multiRoiMetadata.empty() && generalData->dynamicRange == 4) { throw std::runtime_error("Skipping virtual hdf5 file since rx_roi is " "enabled in 4 bit mode."); - } + }*/ bool gotthard25um = ((generalData->detType == GOTTHARD || generalData->detType == GOTTHARD2) && @@ -240,10 +240,10 @@ void DataProcessor::LinkFileInMaster(const std::string &masterFileName, const bool silentMode, std::mutex *hdf5LibMutex) { - if (!multiRoiMetadata.empty()) { + /*if (!multiRoiMetadata.empty()) { throw std::runtime_error( "Should not be here, roi with hdf5 virtual should throw."); - } + }*/ std::string fname{virtualFileName}, masterfname{masterFileName}; // if no virtual file, link data file if (virtualFileName.empty()) { diff --git a/slsReceiverSoftware/src/Implementation.cpp b/slsReceiverSoftware/src/Implementation.cpp index 10f5aead7..8a9dcdd4b 100644 --- a/slsReceiverSoftware/src/Implementation.cpp +++ b/slsReceiverSoftware/src/Implementation.cpp @@ -184,7 +184,7 @@ void Implementation::SetupListener(int i) { listener[i]->SetUdpPortNumber(udpPortNum[i]); listener[i]->SetEthernetInterface(eth[i]); listener[i]->SetActivate(activated); - listener[i]->SetIsOutsideRoi(i >= (int)portRois.size()); + listener[i]->SetIsOutsideRoi(portRois[i].noRoi()); listener[i]->SetDetectorDatastream(detectorDataStream[i]); listener[i]->SetSilentMode(silentMode); } @@ -194,12 +194,7 @@ void Implementation::SetupDataProcessor(int i) { dataProcessor[i]->SetGeneralData(generalData); dataProcessor[i]->SetUdpPortNumber(udpPortNum[i]); dataProcessor[i]->SetActivate(activated); - if (i >= (int)portRois.size()) { - ROI roi{0, 0, 0, 0}; - dataProcessor[i]->SetPortROI(roi); - } else { - dataProcessor[i]->SetPortROI(portRois[i]); - } + dataProcessor[i]->SetPortROI(portRois[i]); if (i == 0) dataProcessor[0]->setMultiROIMetadata(multiRoiMetadata); dataProcessor[i]->SetDataStreamEnable(dataStreamEnable); @@ -223,12 +218,7 @@ void Implementation::SetupDataStreamer(int i) { dataStreamer[i]->SetFlipRows(flipRows); dataStreamer[i]->SetNumberofPorts(numPorts); dataStreamer[i]->SetNumberofTotalFrames(numberOfTotalFrames); - if (i >= (int)portRois.size()) { - ROI roi{0, 0, 0, 0}; - dataStreamer[i]->SetPortROI(roi); - } else { - dataStreamer[i]->SetPortROI(portRois[i]); - } + dataStreamer[i]->SetPortROI(portRois[i]); } slsDetectorDefs::xy Implementation::getDetectorSize() const { @@ -415,24 +405,14 @@ void Implementation::setPortROIs(const std::vector &args) { portRois = args; for (size_t i = 0; i != listener.size(); ++i) - listener[i]->SetIsOutsideRoi(i >= portRois.size()); + listener[i]->SetIsOutsideRoi(portRois[i].noRoi()); for (size_t i = 0; i != dataProcessor.size(); ++i) { - if (i >= portRois.size()) { - ROI roi{0, 0, 0, 0}; - dataProcessor[i]->SetPortROI(roi); - } else { - dataProcessor[i]->SetPortROI(portRois[i]); - } + dataProcessor[i]->SetPortROI(portRois[i]); } if (dataProcessor.size() > 0) dataProcessor[0]->setMultiROIMetadata(multiRoiMetadata); for (size_t i = 0; i != dataStreamer.size(); ++i) { - if (i >= portRois.size()) { - ROI roi{0, 0, 0, 0}; - dataStreamer[i]->SetPortROI(roi); - } else { - dataStreamer[i]->SetPortROI(portRois[i]); - } + dataStreamer[i]->SetPortROI(portRois[i]); } LOG(logINFO) << "Rois (per port): " << ToString(portRois); } @@ -737,7 +717,7 @@ void Implementation::stopReceiver() { } else if (!detectorDataStream[i]) { summary = (i == 0 ? "\n\tDeactivated Left Port" : "\n\tDeactivated Right Port"); - } else if (i >= (int)portRois.size()) { + } else if (portRois[i].noRoi()) { summary = "\n\tNo Roi on Port[" + std::to_string(i) + ']'; } else { std::ostringstream os; @@ -909,7 +889,8 @@ void Implementation::StartMasterWriter() { masterAttributes.scanParams = scanParams; masterAttributes.totalFrames = numberOfTotalFrames; // complete ROI (for each port TODO?) - if (multiRoiMetadata.empty()) { + if (multiRoiMetadata.size() == 1 && + multiRoiMetadata[0].completeRoi()) { int nTotalPixelsX = (generalData->nPixelsX * numPorts.x); int nTotalPixelsY = (generalData->nPixelsY * numPorts.y); if (nTotalPixelsY == 1) { @@ -1049,8 +1030,13 @@ void Implementation::setNumberofUDPInterfaces(const int n) { // fifo SetupFifoStructure(); + + // roi cleared - complete detector + std::vector rois(n); + std::vector multiRoi(1); // recalculate port rois booleans for listener, processor and streamer - setPortROIs(portRois); + setPortROIs(rois); + setMultiROIMetadata(multiRoi); // create threads for (int i = 0; i < generalData->numUDPInterfaces; ++i) { diff --git a/slsReceiverSoftware/src/Implementation.h b/slsReceiverSoftware/src/Implementation.h index 6f25287fd..099454441 100644 --- a/slsReceiverSoftware/src/Implementation.h +++ b/slsReceiverSoftware/src/Implementation.h @@ -307,8 +307,8 @@ class Implementation : private virtual slsDetectorDefs { bool framePadding{true}; pid_t parentThreadId; pid_t tcpThreadId; - std::vector portRois{}; - std::vector multiRoiMetadata{}; + std::vector portRois{1}; + std::vector multiRoiMetadata{1}; // file parameters fileFormat fileFormatType{BINARY}; diff --git a/slsReceiverSoftware/src/MasterFileUtility.cpp b/slsReceiverSoftware/src/MasterFileUtility.cpp index 6e0c7903b..529dbde33 100644 --- a/slsReceiverSoftware/src/MasterFileUtility.cpp +++ b/slsReceiverSoftware/src/MasterFileUtility.cpp @@ -208,150 +208,149 @@ std::string CreateVirtualHDF5File( attribute.write(H5::PredType::NATIVE_DOUBLE, &dValue); // complete detector in roi - if (multiRoi.empty()) { - int ny = nPixelsY * numModY; - int nx = nPixelsX * numModX; - if (nPixelsY == 1) { - multiRoi.push_back(defs::ROI{0, nx - 1}); - } else { - multiRoi.push_back(defs::ROI{0, nx - 1, 0, ny - 1}); - } + /*if (multiRoi.empty()) { + int ny = nPixelsY * numModY; + int nx = nPixelsX * numModX; + if (nPixelsY == 1) { + multiRoi.push_back(defs::ROI{0, nx - 1}); + } else { + multiRoi.push_back(defs::ROI{0, nx - 1, 0, ny - 1}); + } + }*/ + + // for (size_t iRoi = 0; iRoi != multiRoi.size(); ++iRoi) { + + // dataspace + hsize_t vdsDims[DATA_RANK] = {numImagesCaught, numModY * nDimy, + numModZ * nDimz}; + hsize_t vdsDimsPara[VDS_PARA_RANK] = {numImagesCaught, + numModY * numModZ}; + H5::DataSpace vdsDataSpace(DATA_RANK, vdsDims, nullptr); + H5::DataSpace vdsDataSpacePara(VDS_PARA_RANK, vdsDimsPara, nullptr); + + // property list + H5::DSetCreatPropList plist; + uint64_t fill_value = -1; + plist.setFillValue(dataType, &fill_value); + std::vector plistPara(paraSize); + // ignoring last fill (string) + for (unsigned int i = 0; i != plistPara.size() - 1; ++i) { + plistPara[i].setFillValue(parameterDataTypes[i], &fill_value); } - for (size_t iRoi = 0; iRoi != multiRoi.size(); ++iRoi) { + // hyperslab (files) + int numFiles = numImagesCaught / maxFramesPerFile; + if (numImagesCaught % maxFramesPerFile) + ++numFiles; + uint64_t framesSaved = 0; + for (int iFile = 0; iFile < numFiles; ++iFile) { - // dataspace - hsize_t vdsDims[DATA_RANK] = {numImagesCaught, numModY * nDimy, - numModZ * nDimz}; - hsize_t vdsDimsPara[VDS_PARA_RANK] = {numImagesCaught, - numModY * numModZ}; - H5::DataSpace vdsDataSpace(DATA_RANK, vdsDims, nullptr); - H5::DataSpace vdsDataSpacePara(VDS_PARA_RANK, vdsDimsPara, nullptr); + uint64_t nDimx = + ((numImagesCaught - framesSaved) > maxFramesPerFile) + ? maxFramesPerFile + : (numImagesCaught - framesSaved); - // property list - H5::DSetCreatPropList plist; - uint64_t fill_value = -1; - plist.setFillValue(dataType, &fill_value); - std::vector plistPara(paraSize); - // ignoring last fill (string) - for (unsigned int i = 0; i != plistPara.size() - 1; ++i) { - plistPara[i].setFillValue(parameterDataTypes[i], &fill_value); + hsize_t startLocation[DATA_RANK] = {framesSaved, 0, 0}; + hsize_t strideBetweenBlocks[DATA_RANK] = {1, 1, 1}; + hsize_t numBlocks[DATA_RANK] = {nDimx, nDimy, nDimz}; + hsize_t blockSize[DATA_RANK] = {1, 1, 1}; + + hsize_t startLocationPara[VDS_PARA_RANK] = {framesSaved, 0}; + hsize_t strideBetweenBlocksPara[VDS_PARA_RANK] = {1, 1}; + hsize_t numBlocksPara[VDS_PARA_RANK] = {nDimx, 1}; + hsize_t blockSizePara[VDS_PARA_RANK] = {1, 1}; + + // interleaving for g2 + if (gotthard25um) { + strideBetweenBlocks[2] = 2; } - // hyperslab (files) - int numFiles = numImagesCaught / maxFramesPerFile; - if (numImagesCaught % maxFramesPerFile) - ++numFiles; - uint64_t framesSaved = 0; - for (int iFile = 0; iFile < numFiles; ++iFile) { + for (unsigned int iReadout = 0; iReadout < numModY * numModZ; + ++iReadout) { - uint64_t nDimx = - ((numImagesCaught - framesSaved) > maxFramesPerFile) - ? maxFramesPerFile - : (numImagesCaught - framesSaved); - - hsize_t startLocation[DATA_RANK] = {framesSaved, 0, 0}; - hsize_t strideBetweenBlocks[DATA_RANK] = {1, 1, 1}; - hsize_t numBlocks[DATA_RANK] = {nDimx, nDimy, nDimz}; - hsize_t blockSize[DATA_RANK] = {1, 1, 1}; - - hsize_t startLocationPara[VDS_PARA_RANK] = {framesSaved, 0}; - hsize_t strideBetweenBlocksPara[VDS_PARA_RANK] = {1, 1}; - hsize_t numBlocksPara[VDS_PARA_RANK] = {nDimx, 1}; - hsize_t blockSizePara[VDS_PARA_RANK] = {1, 1}; - - // interleaving for g2 + // interleaving for g2 (startLocation is 0 and 1) if (gotthard25um) { - strideBetweenBlocks[2] = 2; + startLocation[2] = iReadout; } - for (unsigned int iReadout = 0; iReadout < numModY * numModZ; - ++iReadout) { + vdsDataSpace.selectHyperslab(H5S_SELECT_SET, numBlocks, + startLocation, strideBetweenBlocks, + blockSize); - // interleaving for g2 (startLocation is 0 and 1) - if (gotthard25um) { - startLocation[2] = iReadout; - } + vdsDataSpacePara.selectHyperslab( + H5S_SELECT_SET, numBlocksPara, startLocationPara, + strideBetweenBlocksPara, blockSizePara); - vdsDataSpace.selectHyperslab( - H5S_SELECT_SET, numBlocks, startLocation, - strideBetweenBlocks, blockSize); + // source file name + std::ostringstream os; + os << filePath << "/" << fileNamePrefix << "_d" + << (modulePos * numUnitsPerReadout + iReadout) << "_f" + << iFile << '_' << fileIndex << ".h5"; + std::string srcFileName = os.str(); + LOG(logDEBUG1) << srcFileName; - vdsDataSpacePara.selectHyperslab( - H5S_SELECT_SET, numBlocksPara, startLocationPara, - strideBetweenBlocksPara, blockSizePara); - - // source file name - std::ostringstream os; - os << filePath << "/" << fileNamePrefix << "_d" - << (modulePos * numUnitsPerReadout + iReadout) << "_f" - << iFile << '_' << fileIndex << ".h5"; - std::string srcFileName = os.str(); - LOG(logDEBUG1) << srcFileName; - - // find relative path - std::string relative_srcFileName = srcFileName; - { - size_t p = srcFileName.rfind('/', srcFileName.length()); - if (p != std::string::npos) - relative_srcFileName = (srcFileName.substr( - p + 1, srcFileName.length() - p)); - } - - // source dataspace - hsize_t srcDims[DATA_RANK] = {nDimx, nDimy, nDimz}; - hsize_t srcDimsMax[DATA_RANK] = {H5S_UNLIMITED, nDimy, - nDimz}; - H5::DataSpace srcDataSpace(DATA_RANK, srcDims, srcDimsMax); - hsize_t srcDimsPara[PARA_RANK] = {nDimx}; - hsize_t srcDimsMaxPara[PARA_RANK] = {H5S_UNLIMITED}; - H5::DataSpace srcDataSpacePara(PARA_RANK, srcDimsPara, - srcDimsMaxPara); - // temporary fixfor corner case bug: - // (framescaught not multiple of framesperfile, - // virtual parameter datasets error loading (bad scalar - // value)) - if (nDimx != maxFramesPerFile) { - hsize_t count[1] = {nDimx}; - hsize_t start[1] = {0}; - srcDataSpacePara.selectHyperslab( - H5S_SELECT_SET, count, start, - strideBetweenBlocksPara, blockSizePara); - } - - // mapping of property list - plist.setVirtual(vdsDataSpace, relative_srcFileName.c_str(), - DATASET_NAME, srcDataSpace); - for (unsigned int p = 0; p < paraSize; ++p) { - plistPara[p].setVirtual( - vdsDataSpacePara, relative_srcFileName.c_str(), - parameterNames[p].c_str(), srcDataSpacePara); - } - - // H5Sclose(srcDataspace); - // H5Sclose(srcDataspace_para); - - if (!gotthard25um) { - startLocation[2] += nDimz; - if (startLocation[2] >= (numModZ * nDimz)) { - startLocation[2] = 0; - startLocation[1] += nDimy; - } - } - ++startLocationPara[1]; + // find relative path + std::string relative_srcFileName = srcFileName; + { + size_t p = srcFileName.rfind('/', srcFileName.length()); + if (p != std::string::npos) + relative_srcFileName = (srcFileName.substr( + p + 1, srcFileName.length() - p)); } - framesSaved += nDimx; - } - // datasets - H5::DataSet vdsDataSet( - fd->createDataSet(DATASET_NAME, dataType, vdsDataSpace, plist)); - for (unsigned int p = 0; p < paraSize; ++p) { - H5::DataSet vdsDataSetPara(fd->createDataSet( - parameterNames[p].c_str(), parameterDataTypes[p], - vdsDataSpacePara, plistPara[p])); + // source dataspace + hsize_t srcDims[DATA_RANK] = {nDimx, nDimy, nDimz}; + hsize_t srcDimsMax[DATA_RANK] = {H5S_UNLIMITED, nDimy, nDimz}; + H5::DataSpace srcDataSpace(DATA_RANK, srcDims, srcDimsMax); + hsize_t srcDimsPara[PARA_RANK] = {nDimx}; + hsize_t srcDimsMaxPara[PARA_RANK] = {H5S_UNLIMITED}; + H5::DataSpace srcDataSpacePara(PARA_RANK, srcDimsPara, + srcDimsMaxPara); + // temporary fixfor corner case bug: + // (framescaught not multiple of framesperfile, + // virtual parameter datasets error loading (bad scalar + // value)) + if (nDimx != maxFramesPerFile) { + hsize_t count[1] = {nDimx}; + hsize_t start[1] = {0}; + srcDataSpacePara.selectHyperslab( + H5S_SELECT_SET, count, start, strideBetweenBlocksPara, + blockSizePara); + } + + // mapping of property list + plist.setVirtual(vdsDataSpace, relative_srcFileName.c_str(), + DATASET_NAME, srcDataSpace); + for (unsigned int p = 0; p < paraSize; ++p) { + plistPara[p].setVirtual( + vdsDataSpacePara, relative_srcFileName.c_str(), + parameterNames[p].c_str(), srcDataSpacePara); + } + + // H5Sclose(srcDataspace); + // H5Sclose(srcDataspace_para); + + if (!gotthard25um) { + startLocation[2] += nDimz; + if (startLocation[2] >= (numModZ * nDimz)) { + startLocation[2] = 0; + startLocation[1] += nDimy; + } + } + ++startLocationPara[1]; } + framesSaved += nDimx; } + // datasets + H5::DataSet vdsDataSet( + fd->createDataSet(DATASET_NAME, dataType, vdsDataSpace, plist)); + + for (unsigned int p = 0; p < paraSize; ++p) { + H5::DataSet vdsDataSetPara(fd->createDataSet( + parameterNames[p].c_str(), parameterDataTypes[p], + vdsDataSpacePara, plistPara[p])); + } + //} fd->close(); } catch (const H5::Exception &error) {