mirror of
https://github.com/slsdetectorgroup/slsDetectorPackage.git
synced 2025-06-20 00:37:12 +02:00
Rx roi (#428)
* roi structure expanded to have ymin and ymax * compile with 'detector roi' * wip * wip, rx_roi, rx_clearroi * wip rxroi * rxroi wip * wip rxroi * merge fix * wip * rx_roi works, impl wip, test * tests in, impl left * wip, rxroi impl * wip, rxroi impl * wip * setrx_Roi works, getrx_roi, wip * rx_roi impl done * wip, rxroi * wip, getrx_roi rxr ports * fix ports * wip * wip * fix positions on server side * wip * numports wip * wip * jungfrau top inner interface row increment * x, y detpos, wip * removed eiger row indices flipping in gui (bottom flipping maintained) * wip * wip, jungfrau numinterfaces2 * jungfrau virtual works * eiger, jungfrau, g2 virtual server works * eiger positions fix, wip * binaries in * minor printout * binaries in * merge fix * merge fix * removing getposition * setrxroi wip * set upto port * get messed, wip * roi multi to module works, wip * wip * roi dont return -1 * added rxroi metadata in master file * added rxroifromshm, not yet in detector * rx roi in gui with box, also for gap pixels (gappixels for jungfrau mess) * fix for segfault in gui with detaching roi box in gui * wip * m3 gui: slave timing modes should be discarded when squashing * fixed m3 virtual data, and fixed counters in gui asthetics * m3 roi works * wip, g2 * wip * handling g225um boards, and showing roi for gainplot as well * udpate python functions * fix for 1d and a2d roi written * fixed actual roi written to file * no virtual hdf5 when handling rx roi * test * minor * binarie in
This commit is contained in:
@ -70,7 +70,7 @@ void DetectorImpl::freeSharedMemory(int detectorIndex, int detPos) {
|
||||
|
||||
if (detectorShm.exists()) {
|
||||
detectorShm.openSharedMemory(false);
|
||||
numModules = detectorShm()->numberOfModules;
|
||||
numModules = detectorShm()->totalNumberOfModules;
|
||||
detectorShm.removeSharedMemory();
|
||||
}
|
||||
|
||||
@ -161,10 +161,10 @@ void DetectorImpl::initSharedMemory(bool verify) {
|
||||
|
||||
void DetectorImpl::initializeDetectorStructure() {
|
||||
shm()->shmversion = DETECTOR_SHMVERSION;
|
||||
shm()->numberOfModules = 0;
|
||||
shm()->totalNumberOfModules = 0;
|
||||
shm()->detType = GENERIC;
|
||||
shm()->numberOfModule.x = 0;
|
||||
shm()->numberOfModule.y = 0;
|
||||
shm()->numberOfModules.x = 0;
|
||||
shm()->numberOfModules.y = 0;
|
||||
shm()->numberOfChannels.x = 0;
|
||||
shm()->numberOfChannels.y = 0;
|
||||
shm()->acquiringFlag = false;
|
||||
@ -172,6 +172,10 @@ void DetectorImpl::initializeDetectorStructure() {
|
||||
shm()->gapPixels = false;
|
||||
// zmqlib default
|
||||
shm()->zmqHwm = -1;
|
||||
shm()->rx_roi.xmin = -1;
|
||||
shm()->rx_roi.xmax = -1;
|
||||
shm()->rx_roi.ymin = -1;
|
||||
shm()->rx_roi.ymax = -1;
|
||||
}
|
||||
|
||||
void DetectorImpl::initializeMembers(bool verify) {
|
||||
@ -179,7 +183,7 @@ void DetectorImpl::initializeMembers(bool verify) {
|
||||
zmqSocket.clear();
|
||||
|
||||
// get objects from single det shared memory (open)
|
||||
for (int i = 0; i < shm()->numberOfModules; i++) {
|
||||
for (int i = 0; i < shm()->totalNumberOfModules; i++) {
|
||||
try {
|
||||
modules.push_back(
|
||||
sls::make_unique<Module>(detectorIndex, i, verify));
|
||||
@ -246,7 +250,7 @@ void DetectorImpl::setVirtualDetectorServers(const int numdet, const int port) {
|
||||
|
||||
void DetectorImpl::setHostname(const std::vector<std::string> &name) {
|
||||
// this check is there only to allow the previous detsizechan command
|
||||
if (shm()->numberOfModules != 0) {
|
||||
if (shm()->totalNumberOfModules != 0) {
|
||||
LOG(logWARNING) << "There are already module(s) in shared memory."
|
||||
"Freeing Shared memory now.";
|
||||
bool initialChecks = shm()->initialChecks;
|
||||
@ -305,7 +309,7 @@ void DetectorImpl::addModule(const std::string &hostname) {
|
||||
auto pos = modules.size();
|
||||
modules.emplace_back(
|
||||
sls::make_unique<Module>(type, detectorIndex, pos, false));
|
||||
shm()->numberOfModules = modules.size();
|
||||
shm()->totalNumberOfModules = modules.size();
|
||||
modules[pos]->setControlPort(port);
|
||||
modules[pos]->setStopPort(port + 1);
|
||||
modules[pos]->setHostname(host, shm()->initialChecks);
|
||||
@ -328,9 +332,8 @@ void DetectorImpl::addModule(const std::string &hostname) {
|
||||
void DetectorImpl::updateDetectorSize() {
|
||||
LOG(logDEBUG) << "Updating Detector Size: " << size();
|
||||
|
||||
const slsDetectorDefs::xy det_size = modules[0]->getNumberOfChannels();
|
||||
|
||||
if (det_size.x == 0 || det_size.y == 0) {
|
||||
const slsDetectorDefs::xy modSize = modules[0]->getNumberOfChannels();
|
||||
if (modSize.x == 0 || modSize.y == 0) {
|
||||
throw sls::RuntimeError(
|
||||
"Module size for x or y dimensions is 0. Unable to proceed in "
|
||||
"updating detector size. ");
|
||||
@ -338,39 +341,39 @@ void DetectorImpl::updateDetectorSize() {
|
||||
|
||||
int maxx = shm()->numberOfChannels.x;
|
||||
int maxy = shm()->numberOfChannels.y;
|
||||
int ndetx = 0, ndety = 0;
|
||||
int nModx = 0, nMody = 0;
|
||||
// 1d, add modules along x axis
|
||||
if (det_size.y == 1) {
|
||||
if (modSize.y == 1) {
|
||||
if (maxx == 0) {
|
||||
maxx = det_size.x * size();
|
||||
maxx = modSize.x * size();
|
||||
}
|
||||
ndetx = maxx / det_size.x;
|
||||
ndety = size() / ndetx;
|
||||
if ((maxx % det_size.x) > 0) {
|
||||
++ndety;
|
||||
nModx = maxx / modSize.x;
|
||||
nMody = size() / nModx;
|
||||
if ((maxx % modSize.x) > 0) {
|
||||
++nMody;
|
||||
}
|
||||
}
|
||||
// 2d, add modules along y axis (due to eiger top/bottom)
|
||||
else {
|
||||
if (maxy == 0) {
|
||||
maxy = det_size.y * size();
|
||||
maxy = modSize.y * size();
|
||||
}
|
||||
ndety = maxy / det_size.y;
|
||||
ndetx = size() / ndety;
|
||||
if ((maxy % det_size.y) > 0) {
|
||||
++ndetx;
|
||||
nMody = maxy / modSize.y;
|
||||
nModx = size() / nMody;
|
||||
if ((maxy % modSize.y) > 0) {
|
||||
++nModx;
|
||||
}
|
||||
}
|
||||
|
||||
shm()->numberOfModule.x = ndetx;
|
||||
shm()->numberOfModule.y = ndety;
|
||||
shm()->numberOfChannels.x = det_size.x * ndetx;
|
||||
shm()->numberOfChannels.y = det_size.y * ndety;
|
||||
shm()->numberOfModules.x = nModx;
|
||||
shm()->numberOfModules.y = nMody;
|
||||
shm()->numberOfChannels.x = modSize.x * nModx;
|
||||
shm()->numberOfChannels.y = modSize.y * nMody;
|
||||
|
||||
LOG(logDEBUG) << "\n\tNumber of Modules in X direction:"
|
||||
<< shm()->numberOfModule.x
|
||||
<< shm()->numberOfModules.x
|
||||
<< "\n\tNumber of Modules in Y direction:"
|
||||
<< shm()->numberOfModule.y
|
||||
<< shm()->numberOfModules.y
|
||||
<< "\n\tNumber of Channels in X direction:"
|
||||
<< shm()->numberOfChannels.x
|
||||
<< "\n\tNumber of Channels in Y direction:"
|
||||
@ -378,7 +381,7 @@ void DetectorImpl::updateDetectorSize() {
|
||||
|
||||
for (auto &module : modules) {
|
||||
if (module->getUpdateMode() == 0) {
|
||||
module->updateNumberOfModule(shm()->numberOfModule);
|
||||
module->updateNumberOfModule(shm()->numberOfModules);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -386,7 +389,7 @@ void DetectorImpl::updateDetectorSize() {
|
||||
int DetectorImpl::size() const { return modules.size(); }
|
||||
|
||||
slsDetectorDefs::xy DetectorImpl::getNumberOfModules() const {
|
||||
return shm()->numberOfModule;
|
||||
return shm()->numberOfModules;
|
||||
}
|
||||
|
||||
slsDetectorDefs::xy DetectorImpl::getNumberOfChannels() const {
|
||||
@ -412,7 +415,7 @@ void DetectorImpl::setGapPixelsinCallback(const bool enable) {
|
||||
if (size() && modules[0]->getQuad()) {
|
||||
break;
|
||||
}
|
||||
if (shm()->numberOfModule.y % 2 != 0) {
|
||||
if (shm()->numberOfModules.y % 2 != 0) {
|
||||
throw RuntimeError("Gap pixels can only be used "
|
||||
"for full modules.");
|
||||
}
|
||||
@ -495,6 +498,7 @@ void DetectorImpl::readFrameFromReceiver() {
|
||||
bool quadEnable = false;
|
||||
// to flip image
|
||||
bool eiger = false;
|
||||
std::array<int, 4> rxRoi = shm()->rx_roi.getIntArray();
|
||||
|
||||
std::vector<bool> runningList(zmqSocket.size());
|
||||
std::vector<bool> connectList(zmqSocket.size());
|
||||
@ -571,7 +575,7 @@ void DetectorImpl::readFrameFromReceiver() {
|
||||
// shape
|
||||
nPixelsX = zHeader.npixelsx;
|
||||
nPixelsY = zHeader.npixelsy;
|
||||
// module shape (port)
|
||||
// port geometry
|
||||
nX = zHeader.ndetx;
|
||||
nY = zHeader.ndety;
|
||||
nDetPixelsX = nX * nPixelsX;
|
||||
@ -668,6 +672,7 @@ void DetectorImpl::readFrameFromReceiver() {
|
||||
<< "\n\t databytes: " << multisize
|
||||
<< "\n\t dynamicRange: " << dynamicRange;
|
||||
|
||||
|
||||
// send data to callback
|
||||
if (data) {
|
||||
char *callbackImage = multiframe.get();
|
||||
@ -691,7 +696,7 @@ void DetectorImpl::readFrameFromReceiver() {
|
||||
thisData = new detectorData(currentProgress, currentFileName,
|
||||
nDetActualPixelsX, nDetActualPixelsY,
|
||||
callbackImage, imagesize, dynamicRange,
|
||||
currentFileIndex, completeImage);
|
||||
currentFileIndex, completeImage, rxRoi);
|
||||
try {
|
||||
dataReady(
|
||||
thisData, currentFrameIndex,
|
||||
@ -1094,9 +1099,6 @@ int DetectorImpl::acquire() {
|
||||
return FAIL;
|
||||
}
|
||||
|
||||
// We need this to handle Mythen3 synchronization
|
||||
auto detector_type = Parallel(&Module::getDetectorType, {}).squash();
|
||||
|
||||
try {
|
||||
struct timespec begin, end;
|
||||
clock_gettime(CLOCK_REALTIME, &begin);
|
||||
@ -1174,6 +1176,7 @@ int DetectorImpl::acquire() {
|
||||
}
|
||||
|
||||
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;
|
||||
@ -1425,6 +1428,218 @@ void DetectorImpl::setDefaultDac(defs::dacIndex index, int defaultValue,
|
||||
Parallel(&Module::setDefaultDac, pos, index, defaultValue, sett);
|
||||
}
|
||||
|
||||
defs::xy DetectorImpl::getPortGeometry() const {
|
||||
defs::xy portGeometry(1, 1);
|
||||
switch (shm()->detType) {
|
||||
case EIGER:
|
||||
portGeometry.x = modules[0]->getNumberofUDPInterfacesFromShm();
|
||||
break;
|
||||
case JUNGFRAU:
|
||||
portGeometry.y = modules[0]->getNumberofUDPInterfacesFromShm();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return portGeometry;
|
||||
}
|
||||
|
||||
defs::xy DetectorImpl::calculatePosition(int moduleIndex,
|
||||
defs::xy geometry) const {
|
||||
defs::xy pos{};
|
||||
int maxYMods = shm()->numberOfModules.y;
|
||||
pos.y = (moduleIndex % maxYMods) * geometry.y;
|
||||
pos.x = (moduleIndex / maxYMods) * geometry.x;
|
||||
return pos;
|
||||
}
|
||||
|
||||
defs::ROI DetectorImpl::getRxROI() const {
|
||||
if (shm()->detType == CHIPTESTBOARD || shm()->detType == MOENCH) {
|
||||
throw RuntimeError("RxRoi not implemented for this Detector");
|
||||
}
|
||||
if (modules.size() == 0) {
|
||||
throw RuntimeError("No Modules added");
|
||||
}
|
||||
// complete detector in roi
|
||||
auto t = Parallel(&Module::getRxROI, {});
|
||||
if (t.equal() && t.front().completeRoi()) {
|
||||
LOG(logDEBUG) << "no roi";
|
||||
return defs::ROI (0, shm()->numberOfChannels.x - 1, 0, shm()->numberOfChannels.y - 1);
|
||||
}
|
||||
|
||||
defs::xy numChansPerMod = modules[0]->getNumberOfChannels();
|
||||
bool is2D = (numChansPerMod.y > 1 ? true : false);
|
||||
defs::xy geometry = getPortGeometry();
|
||||
|
||||
defs::ROI retval{};
|
||||
for (size_t iModule = 0; iModule != modules.size(); ++iModule) {
|
||||
|
||||
defs::ROI moduleRoi = modules[iModule]->getRxROI();
|
||||
if (moduleRoi.noRoi()) {
|
||||
LOG(logDEBUG) << iModule << ": no roi";
|
||||
} else {
|
||||
// expand complete roi
|
||||
if (moduleRoi.completeRoi()) {
|
||||
moduleRoi.xmin = 0;
|
||||
moduleRoi.xmax = numChansPerMod.x;
|
||||
if (is2D) {
|
||||
moduleRoi.ymin = 0;
|
||||
moduleRoi.ymax = numChansPerMod.y;
|
||||
}
|
||||
}
|
||||
LOG(logDEBUG) << iModule << ": " << moduleRoi;
|
||||
|
||||
// get roi at detector level
|
||||
defs::xy pos = calculatePosition(iModule, geometry);
|
||||
defs::ROI moduleFullRoi{};
|
||||
moduleFullRoi.xmin = numChansPerMod.x * pos.x + moduleRoi.xmin;
|
||||
moduleFullRoi.xmax = numChansPerMod.x * pos.x + moduleRoi.xmax;
|
||||
if (is2D) {
|
||||
moduleFullRoi.ymin = numChansPerMod.y * pos.y + moduleRoi.ymin;
|
||||
moduleFullRoi.ymax = numChansPerMod.y * pos.y + moduleRoi.ymax;
|
||||
}
|
||||
LOG(logDEBUG) << iModule << ": (full roi)" << moduleFullRoi;
|
||||
|
||||
// get min and max
|
||||
if (retval.xmin == -1 || moduleFullRoi.xmin < retval.xmin) {
|
||||
LOG(logDEBUG) << iModule << ": xmin updated";
|
||||
retval.xmin = moduleFullRoi.xmin;
|
||||
}
|
||||
if (retval.xmax == -1 || moduleFullRoi.xmax > retval.xmax) {
|
||||
LOG(logDEBUG) << iModule << ": xmax updated";
|
||||
retval.xmax = moduleFullRoi.xmax;
|
||||
}
|
||||
if (retval.ymin == -1 || moduleFullRoi.ymin < retval.ymin) {
|
||||
LOG(logDEBUG) << iModule << ": ymin updated";
|
||||
retval.ymin = moduleFullRoi.ymin;
|
||||
}
|
||||
if (retval.ymax == -1 || moduleFullRoi.ymax > retval.ymax) {
|
||||
LOG(logDEBUG) << iModule << ": ymax updated";
|
||||
retval.ymax = moduleFullRoi.ymax;
|
||||
}
|
||||
}
|
||||
LOG(logDEBUG) << iModule << ": (retval): " << retval;
|
||||
}
|
||||
if (retval.ymin == -1) {
|
||||
retval.ymin = 0;
|
||||
retval.ymax = 0;
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
void DetectorImpl::setRxROI(const defs::ROI arg) {
|
||||
if (shm()->detType == CHIPTESTBOARD || shm()->detType == MOENCH) {
|
||||
throw RuntimeError("RxRoi not implemented for this Detector");
|
||||
}
|
||||
if (modules.size() == 0) {
|
||||
throw RuntimeError("No Modules added");
|
||||
}
|
||||
if (arg.noRoi()) {
|
||||
throw RuntimeError("Invalid Roi of size 0.");
|
||||
}
|
||||
if (arg.completeRoi()) {
|
||||
throw RuntimeError("Did you mean the clear roi command (API: clearRxROI, cmd: rx_clearroi)?");
|
||||
}
|
||||
if (arg.xmin > arg.xmax || arg.ymin > arg.ymax) {
|
||||
throw RuntimeError("Invalid Receiver Roi. xmin/ymin exceeds xmax/ymax.");
|
||||
}
|
||||
|
||||
defs::xy numChansPerMod = modules[0]->getNumberOfChannels();
|
||||
bool is2D = (numChansPerMod.y > 1 ? true : false);
|
||||
defs::xy geometry = getPortGeometry();
|
||||
|
||||
if (!is2D && ((arg.ymin != -1 && arg.ymin != 0) || (arg.ymax != -1 && arg.ymax != 0))) {
|
||||
throw RuntimeError("Invalid Receiver roi. Cannot set 2d roi for a 1d detector.");
|
||||
}
|
||||
|
||||
if (arg.xmin < 0 || arg.xmax >= shm()->numberOfChannels.x || (is2D && (arg.ymin < 0 || arg.ymax >= shm()->numberOfChannels.y))) {
|
||||
throw RuntimeError("Invalid Receiver Roi. Outside detector range.");
|
||||
}
|
||||
|
||||
for (size_t iModule = 0; iModule != modules.size(); ++iModule) {
|
||||
// default init = complete roi
|
||||
defs::ROI moduleRoi{};
|
||||
|
||||
// incomplete roi
|
||||
if (!arg.completeRoi()) {
|
||||
// multi module Gotthard2
|
||||
if (shm()->detType == GOTTHARD2 && size() > 1) {
|
||||
moduleRoi.xmin = arg.xmin / 2;
|
||||
moduleRoi.xmax = arg.xmax / 2;
|
||||
if (iModule == 0) {
|
||||
// all should be even
|
||||
if (arg.xmin % 2 != 0) {
|
||||
++moduleRoi.xmin;
|
||||
}
|
||||
} else if (iModule == 1) {
|
||||
// all should be odd
|
||||
if (arg.xmax % 2 == 0) {
|
||||
--moduleRoi.xmax;
|
||||
}
|
||||
} else {
|
||||
throw RuntimeError("Cannot have more than 2 modules for a Gotthard2 detector");
|
||||
}
|
||||
} else {
|
||||
// get module limits
|
||||
defs::xy pos = calculatePosition(iModule, geometry);
|
||||
defs::ROI moduleFullRoi{};
|
||||
moduleFullRoi.xmin = numChansPerMod.x * pos.x;
|
||||
moduleFullRoi.xmax = numChansPerMod.x * (pos.x + 1) - 1;
|
||||
if (is2D) {
|
||||
moduleFullRoi.ymin = numChansPerMod.y * pos.y;
|
||||
moduleFullRoi.ymax = numChansPerMod.y * (pos.y + 1) - 1;
|
||||
}
|
||||
|
||||
// no roi
|
||||
if (arg.xmin > moduleFullRoi.xmax ||
|
||||
arg.xmax < moduleFullRoi.xmin ||
|
||||
(is2D && (arg.ymin > moduleFullRoi.ymax ||
|
||||
arg.ymax < moduleFullRoi.ymin))) {
|
||||
moduleRoi.setNoRoi();
|
||||
}
|
||||
// incomplete module roi
|
||||
else if (arg.xmin > moduleFullRoi.xmin ||
|
||||
arg.xmax < moduleFullRoi.xmax ||
|
||||
(is2D && (arg.ymin > moduleFullRoi.ymin ||
|
||||
arg.ymax < moduleFullRoi.ymax))) {
|
||||
moduleRoi.xmin = (arg.xmin <= moduleFullRoi.xmin)
|
||||
? 0
|
||||
: (arg.xmin % numChansPerMod.x);
|
||||
moduleRoi.xmax = (arg.xmax >= moduleFullRoi.xmax)
|
||||
? numChansPerMod.x - 1
|
||||
: (arg.xmax % numChansPerMod.x);
|
||||
if (is2D) {
|
||||
moduleRoi.ymin = (arg.ymin <= moduleFullRoi.ymin)
|
||||
? 0
|
||||
: (arg.ymin % numChansPerMod.y);
|
||||
moduleRoi.ymax = (arg.ymax >= moduleFullRoi.ymax)
|
||||
? numChansPerMod.y - 1
|
||||
: (arg.ymax % numChansPerMod.y);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
modules[iModule]->setRxROI(moduleRoi);
|
||||
}
|
||||
// updating shm rx_roi for gui purposes
|
||||
shm()->rx_roi = arg;
|
||||
|
||||
// metadata
|
||||
if (arg.completeRoi()) {
|
||||
modules[0]->setRxROIMetadata(defs::ROI (0, shm()->numberOfChannels.x - 1, 0, shm()->numberOfChannels.y - 1));
|
||||
} else {
|
||||
modules[0]->setRxROIMetadata(arg);
|
||||
}
|
||||
}
|
||||
|
||||
void DetectorImpl::clearRxROI() {
|
||||
Parallel(&Module::setRxROI, {}, defs::ROI{});
|
||||
shm()->rx_roi.xmin = -1;
|
||||
shm()->rx_roi.ymin = -1;
|
||||
shm()->rx_roi.xmax = -1;
|
||||
shm()->rx_roi.ymax = -1;
|
||||
}
|
||||
|
||||
|
||||
std::vector<std::string> DetectorImpl::getCtbDacNames() const {
|
||||
return ctb_shm()->getDacNames();
|
||||
}
|
||||
|
Reference in New Issue
Block a user