mirror of
https://github.com/slsdetectorgroup/slsDetectorPackage.git
synced 2025-06-17 15:27:13 +02:00
Gappixels (#89)
* WIP * WIP virtual delays, imagetest for saturation * WIP, vertical and horizontal * WIP * gap pixels work, fixed 32 bit data out (10gbe=0) for virtual servers * quad works (also in virtual), handling gappixels and quad * jungfrau gapppixels work * jungfrau: done * complete image or missing packets given in json header and gui * eiger virtual 4 bit mode bug fix * working version of zmq add json header, except printout * printout bug * fix for json para * to map WIP * map done * map print , mapwith result left * json result works, testing added * updated server binaries * compiling on rhels7, variable size char array iniitalization * zmqsocket parsing didnt need Document * const to map, json para is strings not map * json add header: mapping cleaner without insert make_pair
This commit is contained in:
@ -1001,24 +1001,27 @@ std::string CmdProxy::GapPixels(int action) {
|
||||
std::ostringstream os;
|
||||
os << cmd << ' ';
|
||||
if (action == defs::HELP_ACTION) {
|
||||
os << "[0, 1]\n\t[Eiger] Include Gap pixels in data file or data call "
|
||||
"back. 4 bit mode gap pixels only ind ata call back."
|
||||
os << "[0, 1]\n\t[Eiger][Jungfrau] Include Gap pixels only in data call back."
|
||||
<< '\n';
|
||||
} else if (action == defs::GET_ACTION) {
|
||||
if (det_id != -1) {
|
||||
throw sls::RuntimeError(
|
||||
"Cannot get gap pixels at module level");
|
||||
}
|
||||
if (!args.empty()) {
|
||||
WrongNumberOfParameters(0);
|
||||
}
|
||||
auto t = det->getRxAddGapPixels({det_id});
|
||||
os << OutString(t) << '\n';
|
||||
auto t = det->getGapPixelsinCallback();
|
||||
os << t << '\n';
|
||||
} else if (action == defs::PUT_ACTION) {
|
||||
if (det_id != -1) {
|
||||
throw sls::RuntimeError(
|
||||
"Cannot execute dynamic range at module level");
|
||||
"Cannot add gap pixels at module level");
|
||||
}
|
||||
if (args.size() != 1) {
|
||||
WrongNumberOfParameters(1);
|
||||
}
|
||||
det->setRxAddGapPixels(StringTo<int>(args[0]));
|
||||
det->setGapPixelsinCallback(StringTo<int>(args[0]));
|
||||
os << args.front() << '\n';
|
||||
} else {
|
||||
throw sls::RuntimeError("Unknown action");
|
||||
@ -1224,7 +1227,7 @@ std::string CmdProxy::Quad(int action) {
|
||||
} else if (action == defs::PUT_ACTION) {
|
||||
if (det_id != -1) {
|
||||
throw sls::RuntimeError(
|
||||
"Cannot execute dynamic range at module level");
|
||||
"Cannot execute quad at module level");
|
||||
}
|
||||
if (args.size() != 1) {
|
||||
WrongNumberOfParameters(1);
|
||||
@ -1879,13 +1882,47 @@ std::string CmdProxy::PatternWaitTime(int action) {
|
||||
|
||||
/* Moench */
|
||||
|
||||
std::string CmdProxy::AdditionalJsonHeader(int action) {
|
||||
std::ostringstream os;
|
||||
os << cmd << ' ';
|
||||
if (action == defs::HELP_ACTION) {
|
||||
os << "[key1] [value1] [key2] [value2]...[keyn] [valuen]"
|
||||
"\n\tAdditional json header to be streamed out from receiver via zmq. "
|
||||
"Default is empty. Use only if to be processed by an intermediate user process "
|
||||
"listening to receiver zmq packets. Empty value deletes header. "
|
||||
<< '\n';
|
||||
} else if (action == defs::GET_ACTION) {
|
||||
if (args.size() != 0) {
|
||||
WrongNumberOfParameters(0);
|
||||
}
|
||||
auto t = det->getAdditionalJsonHeader({det_id});
|
||||
os << OutString(t) << '\n';
|
||||
} else if (action == defs::PUT_ACTION) {
|
||||
// arguments can be empty
|
||||
std::map<std::string, std::string> json;
|
||||
for (size_t i = 0; i < args.size(); i = i + 2) {
|
||||
// last value is empty
|
||||
if (i + 1 >= args.size()) {
|
||||
json[args[i]] = "";
|
||||
} else {
|
||||
json[args[i]] = args[i + 1];
|
||||
}
|
||||
}
|
||||
det->setAdditionalJsonHeader(json, {det_id});
|
||||
os << sls::ToString(json) << '\n';
|
||||
} else {
|
||||
throw sls::RuntimeError("Unknown action");
|
||||
}
|
||||
return os.str();
|
||||
}
|
||||
|
||||
std::string CmdProxy::JsonParameter(int action) {
|
||||
std::ostringstream os;
|
||||
os << cmd << ' ';
|
||||
if (action == defs::HELP_ACTION) {
|
||||
os << "[key1] [value1]\n\tAdditional json header parameter streamed "
|
||||
"out from receiver. If empty in a get, then no parameter found. "
|
||||
"This is same as calling rx_jsonaddheader \"key\":\"value1\"."
|
||||
"out from receiver. If not found in header, the pair is appended. "
|
||||
"An empty values deletes parameter."
|
||||
<< '\n';
|
||||
} else if (action == defs::GET_ACTION) {
|
||||
if (args.size() != 1) {
|
||||
@ -1894,11 +1931,21 @@ std::string CmdProxy::JsonParameter(int action) {
|
||||
auto t = det->getAdditionalJsonParameter(args[0], {det_id});
|
||||
os << OutString(t) << '\n';
|
||||
} else if (action == defs::PUT_ACTION) {
|
||||
if (args.size() != 2) {
|
||||
WrongNumberOfParameters(2);
|
||||
switch (args.size()) {
|
||||
case 1:
|
||||
det->setAdditionalJsonParameter(args[0], "", {det_id});
|
||||
break;
|
||||
case 2:
|
||||
det->setAdditionalJsonParameter(args[0], args[1], {det_id});
|
||||
break;
|
||||
default:
|
||||
WrongNumberOfParameters(1);
|
||||
}
|
||||
if (args.size() == 1) {
|
||||
os << args[0] << " deleted" << '\n';
|
||||
} else {
|
||||
os << "{" << args[0] << ": " << args[1] << "}" << '\n';
|
||||
}
|
||||
det->setAdditionalJsonParameter(args[0], args[1], {det_id});
|
||||
os << sls::ToString(args) << '\n';
|
||||
} else {
|
||||
throw sls::RuntimeError("Unknown action");
|
||||
}
|
||||
|
@ -477,6 +477,7 @@ class CmdProxy {
|
||||
{"cycles", "triggers"},
|
||||
{"cyclesl", "triggersl"},
|
||||
{"clkdivider", "speed"},
|
||||
{"digitest", "imagetest"},
|
||||
|
||||
/** temperature */
|
||||
/** dacs */
|
||||
@ -527,8 +528,6 @@ class CmdProxy {
|
||||
|
||||
/* Jungfrau Specific */
|
||||
/* Gotthard Specific */
|
||||
{"digitest", "imagetest"},
|
||||
|
||||
/* Gotthard2 Specific */
|
||||
/* Mythen3 Specific */
|
||||
/* CTB Specific */
|
||||
@ -591,6 +590,7 @@ class CmdProxy {
|
||||
{"clkdiv", &CmdProxy::ClockDivider},
|
||||
{"vhighvoltage", &CmdProxy::vhighvoltage},
|
||||
{"powerchip", &CmdProxy::powerchip},
|
||||
{"imagetest", &CmdProxy::imagetest},
|
||||
|
||||
/** temperature */
|
||||
{"temp_adc", &CmdProxy::temp_adc},
|
||||
@ -789,7 +789,6 @@ class CmdProxy {
|
||||
{"clearroi", &CmdProxy::ClearROI},
|
||||
{"exptimel", &CmdProxy::exptimel},
|
||||
{"extsig", &CmdProxy::extsig},
|
||||
{"imagetest", &CmdProxy::imagetest},
|
||||
|
||||
/* Gotthard2 Specific */
|
||||
{"bursts", &CmdProxy::bursts},
|
||||
@ -867,7 +866,7 @@ class CmdProxy {
|
||||
{"patsetbit", &CmdProxy::patsetbit},
|
||||
|
||||
/* Moench */
|
||||
{"rx_jsonaddheader", &CmdProxy::rx_jsonaddheader},
|
||||
{"rx_jsonaddheader", &CmdProxy::AdditionalJsonHeader},
|
||||
{"rx_jsonpara", &CmdProxy::JsonParameter},
|
||||
{"emin", &CmdProxy::MinMaxEnergyThreshold},
|
||||
{"emax", &CmdProxy::MinMaxEnergyThreshold},
|
||||
@ -980,6 +979,7 @@ class CmdProxy {
|
||||
std::string PatternWaitAddress(int action);
|
||||
std::string PatternWaitTime(int action);
|
||||
/* Moench */
|
||||
std::string AdditionalJsonHeader(int action);
|
||||
std::string JsonParameter(int action);
|
||||
std::string MinMaxEnergyThreshold(int action);
|
||||
/* Advanced */
|
||||
@ -1088,6 +1088,10 @@ class CmdProxy {
|
||||
"\n\t[Mythen3] If module not connected or wrong module, 1 will fail. By default, not powered on"
|
||||
"\n\t[Gotthard2] If module not connected or wrong module, 1 will fail. By default, powered on at server start up.");
|
||||
|
||||
INTEGER_COMMAND(imagetest, getImageTestMode, setImageTestMode, StringTo<int>,
|
||||
"[0, 1]\n\t[Gotthard] 1 adds channel intensity with precalculated values when taking an acquisition. Default is 0."
|
||||
"\n\t[Eiger][Jungfrau] Only for Virtual servers. If 0, each pixel intensity incremented by 1. If 1, all pixels almost saturated.");
|
||||
|
||||
/** temperature */
|
||||
|
||||
GET_IND_COMMAND(temp_adc, getTemperature, slsDetectorDefs::TEMPERATURE_ADC, " °C",
|
||||
@ -1582,9 +1586,6 @@ class CmdProxy {
|
||||
INTEGER_COMMAND(extsig, getExternalSignalFlags, setExternalSignalFlags, sls::StringTo<slsDetectorDefs::externalSignalFlag>,
|
||||
"[trigger_in_rising_edge|trigger_in_falling_edge]\n\t[Gotthard] External signal mode for trigger timing mode.");
|
||||
|
||||
INTEGER_COMMAND(imagetest, getImageTestMode, setImageTestMode, StringTo<int>,
|
||||
"[0, 1]\n\t[Gotthard] 1 adds channel intensity with precalculated values when taking an acquisition. Default is 0.");
|
||||
|
||||
/* Gotthard2 Specific */
|
||||
INTEGER_COMMAND_NOID(bursts, getNumberOfBursts, setNumberOfBursts,
|
||||
StringTo<int64_t>,
|
||||
@ -1719,9 +1720,6 @@ class CmdProxy {
|
||||
|
||||
/* Moench */
|
||||
|
||||
STRING_COMMAND(rx_jsonaddheader, getAdditionalJsonHeader, setAdditionalJsonHeader,
|
||||
"[\\\"label1\\\":\\\"value1\\\"], [\\\"label2\\\":\\\"value2\\\"]\n\tAdditional json header to be streamd out from receiver via zmq. Default is empty. Use only if to be processed by an intermediate user process listening to receiver zmq packets.");
|
||||
|
||||
INTEGER_COMMAND(framemode, getFrameMode, setFrameMode, sls::StringTo<slsDetectorDefs::frameModeType>,
|
||||
"[pedestal|newpedestal|flatfield|newflatfield]\n\t[Moench] Frame mode (soft setting) in processor.");
|
||||
|
||||
|
@ -167,6 +167,14 @@ void Detector::registerDataCallback(void (*func)(detectorData *, uint64_t,
|
||||
pimpl->registerDataCallback(func, pArg);
|
||||
}
|
||||
|
||||
bool Detector::getGapPixelsinCallback() const {
|
||||
return pimpl->getGapPixelsinCallback();
|
||||
}
|
||||
|
||||
void Detector::setGapPixelsinCallback(bool enable) {
|
||||
pimpl->setGapPixelsinCallback(enable);
|
||||
}
|
||||
|
||||
// Acquisition Parameters
|
||||
|
||||
Result<int64_t> Detector::getNumberOfFrames(Positions pos) const {
|
||||
@ -359,6 +367,14 @@ void Detector::setPowerChip(bool on, Positions pos) {
|
||||
}
|
||||
}
|
||||
|
||||
Result<int> Detector::getImageTestMode(Positions pos) {
|
||||
return pimpl->Parallel(&Module::getImageTestMode, pos);
|
||||
}
|
||||
|
||||
void Detector::setImageTestMode(int value, Positions pos) {
|
||||
pimpl->Parallel(&Module::setImageTestMode, pos, value);
|
||||
}
|
||||
|
||||
Result<int> Detector::getTemperature(defs::dacIndex index,
|
||||
Positions pos) const {
|
||||
switch (index) {
|
||||
@ -953,14 +969,6 @@ void Detector::loadTrimbits(const std::string &fname, Positions pos) {
|
||||
pimpl->Parallel(&Module::loadSettingsFile, pos, fname);
|
||||
}
|
||||
|
||||
Result<bool> Detector::getRxAddGapPixels(Positions pos) const {
|
||||
return pimpl->Parallel(&Module::enableGapPixels, pos, -1);
|
||||
}
|
||||
|
||||
void Detector::setRxAddGapPixels(bool enable) {
|
||||
pimpl->setGapPixelsinReceiver(enable);
|
||||
}
|
||||
|
||||
Result<bool> Detector::getParallelMode(Positions pos) const {
|
||||
return pimpl->Parallel(&Module::getParallelMode, pos);
|
||||
}
|
||||
@ -1195,14 +1203,6 @@ void Detector::setExternalSignalFlags(defs::externalSignalFlag value,
|
||||
pimpl->Parallel(&Module::setExternalSignalFlags, pos, value);
|
||||
}
|
||||
|
||||
Result<int> Detector::getImageTestMode(Positions pos) {
|
||||
return pimpl->Parallel(&Module::getImageTestMode, pos);
|
||||
}
|
||||
|
||||
void Detector::setImageTestMode(int value, Positions pos) {
|
||||
pimpl->Parallel(&Module::setImageTestMode, pos, value);
|
||||
}
|
||||
|
||||
// Gotthard2 Specific
|
||||
|
||||
Result<int64_t> Detector::getNumberOfBursts(Positions pos) const {
|
||||
@ -1612,13 +1612,13 @@ void Detector::setPatternBitMask(uint64_t mask, Positions pos) {
|
||||
|
||||
// Moench
|
||||
|
||||
Result<std::string> Detector::getAdditionalJsonHeader(Positions pos) const {
|
||||
Result<std::map<std::string, std::string>> Detector::getAdditionalJsonHeader(Positions pos) const {
|
||||
return pimpl->Parallel(&Module::getAdditionalJsonHeader, pos);
|
||||
}
|
||||
|
||||
void Detector::setAdditionalJsonHeader(const std::string &jsonheader,
|
||||
void Detector::setAdditionalJsonHeader(const std::map<std::string, std::string> &jsonHeader,
|
||||
Positions pos) {
|
||||
pimpl->Parallel(&Module::setAdditionalJsonHeader, pos, jsonheader);
|
||||
pimpl->Parallel(&Module::setAdditionalJsonHeader, pos, jsonHeader);
|
||||
}
|
||||
|
||||
Result<std::string> Detector::getAdditionalJsonParameter(const std::string &key,
|
||||
@ -1626,8 +1626,7 @@ Result<std::string> Detector::getAdditionalJsonParameter(const std::string &key,
|
||||
return pimpl->Parallel(&Module::getAdditionalJsonParameter, pos, key);
|
||||
}
|
||||
|
||||
void Detector::setAdditionalJsonParameter(const std::string &key,
|
||||
const std::string &value,
|
||||
void Detector::setAdditionalJsonParameter(const std::string &key, const std::string &value,
|
||||
Positions pos) {
|
||||
pimpl->Parallel(&Module::setAdditionalJsonParameter, pos, key, value);
|
||||
}
|
||||
|
@ -157,6 +157,7 @@ void DetectorImpl::initializeDetectorStructure() {
|
||||
multi_shm()->numberOfChannels.y = 0;
|
||||
multi_shm()->acquiringFlag = false;
|
||||
multi_shm()->initialChecks = true;
|
||||
multi_shm()->gapPixels = false;
|
||||
}
|
||||
|
||||
void DetectorImpl::initializeMembers(bool verify) {
|
||||
@ -339,17 +340,30 @@ void DetectorImpl::setNumberOfChannels(const slsDetectorDefs::xy c) {
|
||||
multi_shm()->numberOfChannels = c;
|
||||
}
|
||||
|
||||
void DetectorImpl::setGapPixelsinReceiver(bool enable) {
|
||||
Parallel(&Module::enableGapPixels, {}, static_cast<int>(enable));
|
||||
// update number of channels
|
||||
Result<slsDetectorDefs::xy> res =
|
||||
Parallel(&Module::getNumberOfChannels, {});
|
||||
multi_shm()->numberOfChannels.x = 0;
|
||||
multi_shm()->numberOfChannels.y = 0;
|
||||
for (auto &it : res) {
|
||||
multi_shm()->numberOfChannels.x += it.x;
|
||||
multi_shm()->numberOfChannels.y += it.y;
|
||||
bool DetectorImpl::getGapPixelsinCallback() const {
|
||||
return multi_shm()->gapPixels;
|
||||
}
|
||||
|
||||
void DetectorImpl::setGapPixelsinCallback(const bool enable) {
|
||||
if (enable) {
|
||||
switch (multi_shm()->multiDetectorType) {
|
||||
case JUNGFRAU:
|
||||
break;
|
||||
case EIGER:
|
||||
if (size() && detectors[0]->getQuad()) {
|
||||
break;
|
||||
}
|
||||
if (multi_shm()->numberOfDetector.y % 2 != 0) {
|
||||
throw RuntimeError("Gap pixels can only be used "
|
||||
"for full modules.");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw RuntimeError("Gap Pixels is not implemented for "
|
||||
+ multi_shm()->multiDetectorType);
|
||||
}
|
||||
}
|
||||
multi_shm()->gapPixels = enable;
|
||||
}
|
||||
|
||||
int DetectorImpl::createReceivingDataSockets(const bool destroy) {
|
||||
@ -406,11 +420,13 @@ int DetectorImpl::createReceivingDataSockets(const bool destroy) {
|
||||
|
||||
void DetectorImpl::readFrameFromReceiver() {
|
||||
|
||||
bool gapPixels = multi_shm()->gapPixels;
|
||||
LOG(logDEBUG) << "Gap pixels: " << gapPixels;
|
||||
|
||||
int nX = 0;
|
||||
int nY = 0;
|
||||
int nDetPixelsX = 0;
|
||||
int nDetPixelsY = 0;
|
||||
bool gappixelsenable = false;
|
||||
bool quadEnable = false;
|
||||
bool eiger = false;
|
||||
bool numInterfaces =
|
||||
@ -434,6 +450,7 @@ void DetectorImpl::readFrameFromReceiver() {
|
||||
}
|
||||
int numConnected = numRunning;
|
||||
bool data = false;
|
||||
bool completeImage = false;
|
||||
char *image = nullptr;
|
||||
char *multiframe = nullptr;
|
||||
char *multigappixels = nullptr;
|
||||
@ -461,6 +478,7 @@ void DetectorImpl::readFrameFromReceiver() {
|
||||
if (multiframe != nullptr) {
|
||||
memset(multiframe, 0xFF, multisize);
|
||||
}
|
||||
completeImage = true;
|
||||
|
||||
// get each frame
|
||||
for (unsigned int isocket = 0; isocket < zmqSocket.size(); ++isocket) {
|
||||
@ -470,9 +488,9 @@ void DetectorImpl::readFrameFromReceiver() {
|
||||
|
||||
// HEADER
|
||||
{
|
||||
rapidjson::Document doc;
|
||||
zmqHeader zHeader;
|
||||
if (zmqSocket[isocket]->ReceiveHeader(
|
||||
isocket, doc, SLS_DETECTOR_JSON_HEADER_VERSION) ==
|
||||
isocket, zHeader, SLS_DETECTOR_JSON_HEADER_VERSION) ==
|
||||
0) {
|
||||
// parse error, version error or end of acquisition for
|
||||
// socket
|
||||
@ -484,33 +502,29 @@ void DetectorImpl::readFrameFromReceiver() {
|
||||
// if first message, allocate (all one time stuff)
|
||||
if (image == nullptr) {
|
||||
// allocate
|
||||
size = doc["size"].GetUint();
|
||||
size = zHeader.imageSize;
|
||||
multisize = size * zmqSocket.size();
|
||||
image = new char[size];
|
||||
multiframe = new char[multisize];
|
||||
memset(multiframe, 0xFF, multisize);
|
||||
// dynamic range
|
||||
dynamicRange = doc["bitmode"].GetUint();
|
||||
dynamicRange = zHeader.dynamicRange;
|
||||
bytesPerPixel = (float)dynamicRange / 8;
|
||||
// shape
|
||||
nPixelsX = doc["shape"][0].GetUint();
|
||||
nPixelsY = doc["shape"][1].GetUint();
|
||||
nPixelsX = zHeader.npixelsx;
|
||||
nPixelsY = zHeader.npixelsy;
|
||||
// detector shape
|
||||
nX = doc["detshape"][0].GetUint();
|
||||
nY = doc["detshape"][1].GetUint();
|
||||
nX = zHeader.ndetx;
|
||||
nY = zHeader.ndety;
|
||||
nY *= numInterfaces;
|
||||
nDetPixelsX = nX * nPixelsX;
|
||||
nDetPixelsY = nY * nPixelsY;
|
||||
// det type
|
||||
eiger =
|
||||
(doc["detType"].GetUint() == static_cast<int>(3))
|
||||
eiger = (zHeader.detType == static_cast<int>(3))
|
||||
? true
|
||||
: false; // to be changed to EIGER when firmware
|
||||
// updates its header data
|
||||
gappixelsenable =
|
||||
(doc["gappixels"].GetUint() == 0) ? false : true;
|
||||
quadEnable =
|
||||
(doc["quad"].GetUint() == 0) ? false : true;
|
||||
quadEnable = (zHeader.quad == 0) ? false : true;
|
||||
LOG(logDEBUG1)
|
||||
<< "One Time Header Info:"
|
||||
"\n\tsize: "
|
||||
@ -520,21 +534,23 @@ void DetectorImpl::readFrameFromReceiver() {
|
||||
<< "\n\tnPixelsX: " << nPixelsX
|
||||
<< "\n\tnPixelsY: " << nPixelsY << "\n\tnX: " << nX
|
||||
<< "\n\tnY: " << nY << "\n\teiger: " << eiger
|
||||
<< "\n\tgappixelsenable: " << gappixelsenable
|
||||
<< "\n\tquadEnable: " << quadEnable;
|
||||
}
|
||||
// each time, parse rest of header
|
||||
currentFileName = doc["fname"].GetString();
|
||||
currentAcquisitionIndex = doc["acqIndex"].GetUint64();
|
||||
currentFrameIndex = doc["fIndex"].GetUint64();
|
||||
currentFileIndex = doc["fileIndex"].GetUint64();
|
||||
currentSubFrameIndex = doc["expLength"].GetUint();
|
||||
coordY = doc["row"].GetUint();
|
||||
coordX = doc["column"].GetUint();
|
||||
currentFileName = zHeader.fname;
|
||||
currentAcquisitionIndex = zHeader.acqIndex;
|
||||
currentFrameIndex = zHeader.frameIndex;
|
||||
currentFileIndex = zHeader.fileIndex;
|
||||
currentSubFrameIndex = zHeader.expLength;
|
||||
coordY = zHeader.row;
|
||||
coordX = zHeader.column;
|
||||
if (eiger) {
|
||||
coordY = (nY - 1) - coordY;
|
||||
}
|
||||
flippedDataX = doc["flippedDataX"].GetUint();
|
||||
flippedDataX = zHeader.flippedDataX;
|
||||
if (zHeader.completeImage == 0) {
|
||||
completeImage = false;
|
||||
}
|
||||
LOG(logDEBUG1)
|
||||
<< "Header Info:"
|
||||
"\n\tcurrentFileName: "
|
||||
@ -544,12 +560,14 @@ void DetectorImpl::readFrameFromReceiver() {
|
||||
<< "\n\tcurrentFileIndex: " << currentFileIndex
|
||||
<< "\n\tcurrentSubFrameIndex: " << currentSubFrameIndex
|
||||
<< "\n\tcoordX: " << coordX << "\n\tcoordY: " << coordY
|
||||
<< "\n\tflippedDataX: " << flippedDataX;
|
||||
<< "\n\tflippedDataX: " << flippedDataX
|
||||
<< "\n\tcompleteImage: " << completeImage;
|
||||
}
|
||||
|
||||
// DATA
|
||||
data = true;
|
||||
zmqSocket[isocket]->ReceiveData(isocket, image, size);
|
||||
|
||||
// creating multi image
|
||||
{
|
||||
uint32_t xoffset = coordX * nPixelsX * bytesPerPixel;
|
||||
@ -586,43 +604,36 @@ void DetectorImpl::readFrameFromReceiver() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LOG(logDEBUG)<< "Call Back Info:"
|
||||
<< "\n\t nDetPixelsX: " << nDetPixelsX
|
||||
<< "\n\t nDetPixelsY: " << nDetPixelsY
|
||||
<< "\n\t databytes: " << multisize
|
||||
<< "\n\t dynamicRange: " << dynamicRange ;
|
||||
<< "\n\t dynamicRange: " << dynamicRange;
|
||||
|
||||
// send data to callback
|
||||
if (data) {
|
||||
setCurrentProgress(currentFrameIndex + 1);
|
||||
// 4bit gap pixels
|
||||
if (dynamicRange == 4 && gappixelsenable) {
|
||||
if (quadEnable) {
|
||||
nDetPixelsX += 2;
|
||||
nDetPixelsY += 2;
|
||||
} else {
|
||||
nDetPixelsX = nX * (nPixelsX + 3);
|
||||
nDetPixelsY = nY * (nPixelsY + 1);
|
||||
}
|
||||
int n = processImageWithGapPixels(multiframe, multigappixels,
|
||||
quadEnable);
|
||||
LOG(logDEBUG)
|
||||
<< "Call Back Info Recalculated:"
|
||||
<< "\n\t nDetPixelsX: " << nDetPixelsX
|
||||
<< "\n\t nDetPixelsY: " << nDetPixelsY
|
||||
<< "\n\t databytes: " << n;
|
||||
thisData =
|
||||
new detectorData(getCurrentProgress(), currentFileName,
|
||||
nDetPixelsX, nDetPixelsY, multigappixels,
|
||||
n, dynamicRange, currentFileIndex);
|
||||
}
|
||||
// normal pixels
|
||||
else {
|
||||
thisData =
|
||||
new detectorData(getCurrentProgress(), currentFileName,
|
||||
nDetPixelsX, nDetPixelsY, multiframe,
|
||||
multisize, dynamicRange, currentFileIndex);
|
||||
char* image = multiframe;
|
||||
int imagesize = multisize;
|
||||
|
||||
if (gapPixels) {
|
||||
int n = InsertGapPixels(multiframe, multigappixels,
|
||||
quadEnable, dynamicRange, nDetPixelsX, nDetPixelsY);
|
||||
image = multigappixels;
|
||||
imagesize = n;
|
||||
}
|
||||
LOG(logDEBUG)
|
||||
<< "Image Info:"
|
||||
<< "\n\tnDetPixelsX: " << nDetPixelsX
|
||||
<< "\n\tnDetPixelsY: " << nDetPixelsY
|
||||
<< "\n\timagesize: " << imagesize
|
||||
<< "\n\tdynamicRange: " << dynamicRange;
|
||||
|
||||
thisData = new detectorData(getCurrentProgress(),
|
||||
currentFileName, nDetPixelsX, nDetPixelsY, image,
|
||||
imagesize, dynamicRange, currentFileIndex, completeImage);
|
||||
|
||||
dataReady(
|
||||
thisData, currentFrameIndex,
|
||||
((dynamicRange == 32 && eiger) ? currentSubFrameIndex : -1),
|
||||
@ -667,141 +678,301 @@ void DetectorImpl::readFrameFromReceiver() {
|
||||
delete[] multigappixels;
|
||||
}
|
||||
|
||||
int DetectorImpl::processImageWithGapPixels(char *image, char *&gpImage,
|
||||
bool quadEnable) {
|
||||
// eiger 4 bit mode
|
||||
int nxb =
|
||||
multi_shm()->numberOfDetector.x * (512 + 3); //(divided by 2 already)
|
||||
int nyb = multi_shm()->numberOfDetector.y * (256 + 1);
|
||||
int nchipInRow = 4;
|
||||
int nxchip = multi_shm()->numberOfDetector.x * 4;
|
||||
int nychip = multi_shm()->numberOfDetector.y * 1;
|
||||
int DetectorImpl::InsertGapPixels(char *image, char *&gpImage,
|
||||
bool quadEnable, int dr, int &nPixelsx, int &nPixelsy) {
|
||||
|
||||
LOG(logDEBUG)<< "Insert Gap pixels:"
|
||||
<< "\n\t nPixelsx: " << nPixelsx
|
||||
<< "\n\t nPixelsy: " << nPixelsy
|
||||
<< "\n\t quadEnable: " << quadEnable
|
||||
<< "\n\t dr: " << dr;
|
||||
|
||||
// inter module gap pixels
|
||||
int modGapPixelsx = 8;
|
||||
int modGapPixelsy = 36;
|
||||
// inter chip gap pixels
|
||||
int chipGapPixelsx = 2;
|
||||
int chipGapPixelsy = 2;
|
||||
// number of pixels in a chip
|
||||
int nChipPixelsx = 256;
|
||||
int nChipPixelsy = 256;
|
||||
// 1 module
|
||||
// number of chips in a module
|
||||
int nMod1Chipx = 4;
|
||||
int nMod1Chipy = 2;
|
||||
if (quadEnable) {
|
||||
nxb = multi_shm()->numberOfDetector.x *
|
||||
(256 + 1); //(divided by 2 already)
|
||||
nyb = multi_shm()->numberOfDetector.y * (512 + 2);
|
||||
nxchip /= 2;
|
||||
nychip *= 2;
|
||||
nchipInRow /= 2;
|
||||
nMod1Chipx = 2;
|
||||
}
|
||||
int gapdatabytes = nxb * nyb;
|
||||
// number of pixels in a module
|
||||
int nMod1Pixelsx = nChipPixelsx * nMod1Chipx;
|
||||
int nMod1Pixelsy = nChipPixelsy * nMod1Chipy;
|
||||
// number of gap pixels in a module
|
||||
int nMod1GapPixelsx = (nMod1Chipx - 1) * chipGapPixelsx;
|
||||
int nMod1GapPixelsy = (nMod1Chipy - 1) * chipGapPixelsy;
|
||||
// total number of modules
|
||||
int nModx = nPixelsx / nMod1Pixelsx;
|
||||
int nMody = nPixelsy / nMod1Pixelsy;
|
||||
|
||||
// allocate
|
||||
if (gpImage == nullptr) {
|
||||
gpImage = new char[gapdatabytes];
|
||||
// check if not full modules
|
||||
// (setting gap pixels and then adding half module or disabling quad)
|
||||
if (nPixelsy / nMod1Pixelsy == 0) {
|
||||
LOG(logERROR) << "Gap pixels can only be enabled with full modules. "
|
||||
"Sending dummy data without gap pixels.\n";
|
||||
double bytesPerPixel = (double)dr / 8.00;
|
||||
int imagesize = nPixelsy * nPixelsx * bytesPerPixel;
|
||||
if (gpImage == NULL) {
|
||||
gpImage = new char[imagesize];
|
||||
}
|
||||
memset(gpImage, 0xFF, imagesize);
|
||||
return imagesize;
|
||||
}
|
||||
// fill value
|
||||
memset(gpImage, 0xFF, gapdatabytes);
|
||||
|
||||
const int b1chipx = 128;
|
||||
const int b1chipy = 256;
|
||||
// total number of pixels
|
||||
int nTotx = nPixelsx + (nMod1GapPixelsx * nModx) + (modGapPixelsx * (nModx - 1));
|
||||
int nToty = nPixelsy + (nMod1GapPixelsy * nMody) + (modGapPixelsy * (nMody - 1));
|
||||
// total number of chips
|
||||
int nChipx = nPixelsx / nChipPixelsx;
|
||||
int nChipy = nPixelsy / nChipPixelsy;
|
||||
|
||||
double bytesPerPixel = (double)dr / 8.00;
|
||||
int imagesize = nTotx * nToty * bytesPerPixel;
|
||||
|
||||
int nChipBytesx = nChipPixelsx * bytesPerPixel; // 1 chip bytes in x
|
||||
int nChipGapBytesx = chipGapPixelsx * bytesPerPixel; // 2 pixel bytes
|
||||
int nModGapBytesx = modGapPixelsx * bytesPerPixel; // 8 pixel bytes
|
||||
int nChipBytesy = nChipPixelsy * nTotx * bytesPerPixel; // 1 chip bytes in y
|
||||
int nChipGapBytesy = chipGapPixelsy * nTotx * bytesPerPixel; // 2 lines
|
||||
int nModGapBytesy = modGapPixelsy * nTotx * 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 row1Bytes = nTotx * bytesPerPixel;
|
||||
int nMod1TotPixelsx = nMod1Pixelsx + nMod1GapPixelsx;
|
||||
if (dr == 4) {
|
||||
nMod1TotPixelsx /= 2;
|
||||
}
|
||||
// eiger requires inter chip gap pixels are halved
|
||||
// jungfrau prefers same inter chip gap pixels as the boundary pixels
|
||||
int divisionValue = 2;
|
||||
slsDetectorDefs::detectorType detType = multi_shm()->multiDetectorType;
|
||||
if (detType == JUNGFRAU) {
|
||||
divisionValue = 1;
|
||||
}
|
||||
LOG(logDEBUG)
|
||||
<< "Insert Gap pixels Calculations:\n\t"
|
||||
<< "nPixelsx: " << nPixelsx << "\n\t"
|
||||
<< "nPixelsy: " << nPixelsy << "\n\t"
|
||||
<< "nMod1Pixelsx: " << nMod1Pixelsx << "\n\t"
|
||||
<< "nMod1Pixelsy: " << nMod1Pixelsy << "\n\t"
|
||||
<< "nMod1GapPixelsx: " << nMod1GapPixelsx << "\n\t"
|
||||
<< "nMod1GapPixelsy: " << nMod1GapPixelsy << "\n\t"
|
||||
<< "nChipy: " << nChipy << "\n\t"
|
||||
<< "nChipx: " << nChipx << "\n\t"
|
||||
<< "nModx: " << nModx << "\n\t"
|
||||
<< "nMody: " << nMody << "\n\t"
|
||||
<< "nTotx: " << nTotx << "\n\t"
|
||||
<< "nToty: " << nToty << "\n\t"
|
||||
<< "bytesPerPixel: " << bytesPerPixel << "\n\t"
|
||||
<< "imagesize: " << imagesize << "\n\t"
|
||||
<< "nChipBytesx: " << nChipBytesx << "\n\t"
|
||||
<< "nChipGapBytesx: " << nChipGapBytesx << "\n\t"
|
||||
<< "nModGapBytesx: " << nModGapBytesx << "\n\t"
|
||||
<< "nChipBytesy: " << nChipBytesy << "\n\t"
|
||||
<< "nChipGapBytesy: " << nChipGapBytesy << "\n\t"
|
||||
<< "nModGapBytesy: " << nModGapBytesy << "\n\t"
|
||||
<< "pixel1: " << pixel1 << "\n\t"
|
||||
<< "row1Bytes: " << row1Bytes << "\n\t"
|
||||
<< "nMod1TotPixelsx: " << nMod1TotPixelsx << "\n\t"
|
||||
<< "divisionValue: " << divisionValue << "\n\n";
|
||||
|
||||
if (gpImage == NULL) {
|
||||
gpImage = new char[imagesize];
|
||||
}
|
||||
memset(gpImage, 0xFF, imagesize);
|
||||
//memcpy(gpImage, image, imagesize);
|
||||
char *src = nullptr;
|
||||
char *dst = nullptr;
|
||||
|
||||
// copying line by line
|
||||
src = image;
|
||||
dst = gpImage;
|
||||
for (int row = 0; row < nychip; ++row) { // for each chip row
|
||||
for (int ichipy = 0; ichipy < b1chipy;
|
||||
++ichipy) { // for each row in a chip
|
||||
for (int col = 0; col < nxchip; ++col) { // for each chip in a row
|
||||
memcpy(dst, src, b1chipx);
|
||||
src += b1chipx;
|
||||
dst += b1chipx;
|
||||
if (((col + 1) % nchipInRow) != 0) { // skip gap pixels
|
||||
++dst;
|
||||
// for each chip row in y
|
||||
for (int iChipy = 0; iChipy < nChipy; ++iChipy) {
|
||||
// for each row
|
||||
for (int iy = 0; iy < nChipPixelsy; ++iy) {
|
||||
// in each row, for every chip
|
||||
for (int iChipx = 0; iChipx < nChipx; ++iChipx) {
|
||||
// copy 1 chip line
|
||||
memcpy(dst, src, nChipBytesx);
|
||||
src += nChipBytesx;
|
||||
dst += nChipBytesx;
|
||||
// skip inter chip gap pixels in x
|
||||
if (((iChipx + 1) % nMod1Chipx) != 0) {
|
||||
dst += nChipGapBytesx;
|
||||
}
|
||||
// skip inter module gap pixels in x
|
||||
else if (iChipx + 1 != nChipx) {
|
||||
dst += nModGapBytesx;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dst += (2 * nxb);
|
||||
// skip inter chip gap pixels in y
|
||||
if (((iChipy + 1) % nMod1Chipy) != 0) {
|
||||
dst += nChipGapBytesy;
|
||||
}
|
||||
// skip inter module gap pixels in y
|
||||
else if (iChipy + 1 != nChipy) {
|
||||
dst += nModGapBytesy;
|
||||
}
|
||||
}
|
||||
|
||||
// vertical filling of values
|
||||
{
|
||||
uint8_t temp, g1, g2;
|
||||
int mod;
|
||||
dst = gpImage;
|
||||
for (int row = 0; row < nychip; ++row) { // for each chip row
|
||||
for (int ichipy = 0; ichipy < b1chipy;
|
||||
++ichipy) { // for each row in a chip
|
||||
for (int col = 0; col < nxchip;
|
||||
++col) { // for each chip in a row
|
||||
dst += b1chipx;
|
||||
mod = (col + 1) % nchipInRow; // get gap pixels
|
||||
// copy gap pixel(chip 0, 1, 2)
|
||||
if (mod != 0) {
|
||||
// iner chip gap pixel values is half of neighboring one
|
||||
// (corners becomes divide by 4 automatically after horizontal filling)
|
||||
|
||||
// vertical filling of inter chip gap pixels
|
||||
dst = gpImage;
|
||||
// for each chip row in y
|
||||
for (int iChipy = 0; iChipy < nChipy; ++iChipy) {
|
||||
// for each row
|
||||
for (int iy = 0; iy < nChipPixelsy; ++iy) {
|
||||
// in each row, for every chip
|
||||
for (int iChipx = 0; iChipx < nChipx; ++iChipx) {
|
||||
// go to gap pixels
|
||||
dst += nChipBytesx;
|
||||
// fix inter chip gap pixels in x
|
||||
if (((iChipx + 1) % nMod1Chipx) != 0) {
|
||||
uint8_t temp8 = 0;
|
||||
uint16_t temp16 = 0;
|
||||
uint32_t temp32 = 0;
|
||||
uint8_t g1 = 0;
|
||||
uint8_t g2 = 0;
|
||||
switch (dr) {
|
||||
case 4:
|
||||
// neighbouring gap pixels to left
|
||||
temp = (*((uint8_t *)(dst - 1)));
|
||||
g1 = ((temp & 0xF) / 2);
|
||||
(*((uint8_t *)(dst - 1))) = (temp & 0xF0) + g1;
|
||||
|
||||
temp8 = (*((uint8_t *)(dst - 1)));
|
||||
g1 = ((temp8 & 0xF) / 2);
|
||||
(*((uint8_t *)(dst - 1))) = (temp8 & 0xF0) + g1;
|
||||
// neighbouring gap pixels to right
|
||||
temp = (*((uint8_t *)(dst + 1)));
|
||||
g2 = ((temp >> 4) / 2);
|
||||
(*((uint8_t *)(dst + 1))) = (g2 << 4) + (temp & 0x0F);
|
||||
|
||||
temp8 = (*((uint8_t *)(dst + 1)));
|
||||
g2 = ((temp8 >> 4) / 2);
|
||||
(*((uint8_t *)(dst + 1))) = (g2 << 4) + (temp8 & 0x0F);
|
||||
// gap pixels
|
||||
(*((uint8_t *)dst)) = (g1 << 4) + g2;
|
||||
|
||||
// increment to point to proper chip destination
|
||||
++dst;
|
||||
}
|
||||
(*((uint8_t *)dst)) = (g1 << 4) + g2;
|
||||
break;
|
||||
case 8:
|
||||
// neighbouring gap pixels to left
|
||||
temp8 = (*((uint8_t *)(dst - pixel1))) / 2;
|
||||
(*((uint8_t *)dst)) = temp8;
|
||||
(*((uint8_t *)(dst - pixel1))) = temp8;
|
||||
// neighbouring gap pixels to right
|
||||
temp8 = (*((uint8_t *)(dst + 2 * pixel1))) / 2;
|
||||
(*((uint8_t *)(dst + pixel1))) = temp8;
|
||||
(*((uint8_t *)(dst + 2 * pixel1))) = temp8;
|
||||
break;
|
||||
case 16:
|
||||
// neighbouring gap pixels to left
|
||||
temp16 = (*((uint16_t *)(dst - pixel1))) / divisionValue;
|
||||
(*((uint16_t *)dst)) = temp16;
|
||||
(*((uint16_t *)(dst - pixel1))) = temp16;
|
||||
// neighbouring gap pixels to right
|
||||
temp16 = (*((uint16_t *)(dst + 2 * pixel1))) / divisionValue;
|
||||
(*((uint16_t *)(dst + pixel1))) = temp16;
|
||||
(*((uint16_t *)(dst + 2 * pixel1))) = temp16;
|
||||
break;
|
||||
default:
|
||||
// neighbouring gap pixels to left
|
||||
temp32 = (*((uint32_t *)(dst - pixel1))) / 2;
|
||||
(*((uint32_t *)dst)) = temp32;
|
||||
(*((uint32_t *)(dst - pixel1))) = temp32;
|
||||
// neighbouring gap pixels to right
|
||||
temp32 = (*((uint32_t *)(dst + 2 * pixel1))) / 2;
|
||||
(*((uint32_t *)(dst + pixel1))) = temp32;
|
||||
(*((uint32_t *)(dst + 2 * pixel1))) = temp32;
|
||||
break;
|
||||
}
|
||||
dst += nChipGapBytesx;
|
||||
}
|
||||
// skip inter module gap pixels in x
|
||||
else if (iChipx + 1 != nChipx) {
|
||||
dst += nModGapBytesx;
|
||||
}
|
||||
}
|
||||
}
|
||||
// skip inter chip gap pixels in y
|
||||
if (((iChipy + 1) % nMod1Chipy) != 0) {
|
||||
dst += nChipGapBytesy;
|
||||
}
|
||||
// skip inter module gap pixels in y
|
||||
else if (iChipy + 1 != nChipy) {
|
||||
dst += nModGapBytesy;
|
||||
}
|
||||
}
|
||||
|
||||
dst += (2 * nxb);
|
||||
// horizontal filling of inter chip gap pixels
|
||||
// starting at bottom part (1 line below to copy from)
|
||||
src = gpImage + (nChipBytesy - row1Bytes);
|
||||
dst = gpImage + nChipBytesy;
|
||||
// for each chip row in y
|
||||
for (int iChipy = 0; iChipy < nChipy; ++iChipy) {
|
||||
// for each module in x
|
||||
for (int iModx = 0; iModx < nModx; ++iModx) {
|
||||
// in each module, for every pixel in x
|
||||
for (int iPixel = 0; iPixel < nMod1TotPixelsx; ++iPixel) {
|
||||
uint8_t temp8 = 0, g1 = 0, g2 = 0;
|
||||
uint16_t temp16 = 0;
|
||||
uint32_t temp32 = 0;
|
||||
switch (dr) {
|
||||
case 4:
|
||||
temp8 = (*((uint8_t *)src));
|
||||
g1 = ((temp8 >> 4) / 2);
|
||||
g2 = ((temp8 & 0xF) / 2);
|
||||
temp8 = (g1 << 4) + g2;
|
||||
(*((uint8_t *)dst)) = temp8;
|
||||
(*((uint8_t *)src)) = temp8;
|
||||
break;
|
||||
case 8:
|
||||
temp8 = (*((uint8_t *)src)) / divisionValue;
|
||||
(*((uint8_t *)dst)) = temp8;
|
||||
(*((uint8_t *)src)) = temp8;
|
||||
break;
|
||||
case 16:
|
||||
temp16 = (*((uint16_t *)src)) / divisionValue;
|
||||
(*((uint16_t *)dst)) = temp16;
|
||||
(*((uint16_t *)src)) = temp16;
|
||||
break;
|
||||
default:
|
||||
temp32 = (*((uint32_t *)src)) / 2;
|
||||
(*((uint32_t *)dst)) = temp32;
|
||||
(*((uint32_t *)src)) = temp32;
|
||||
break;
|
||||
}
|
||||
// every pixel (but 4 bit mode, every byte)
|
||||
src += pixel1;
|
||||
dst += pixel1;
|
||||
}
|
||||
// skip inter module gap pixels in x
|
||||
if (iModx + 1 < nModx) {
|
||||
src += nModGapBytesx;
|
||||
dst += nModGapBytesx;
|
||||
}
|
||||
}
|
||||
// bottom parts, skip inter chip gap pixels
|
||||
if ((iChipy % nMod1Chipy) == 0) {
|
||||
src += nChipGapBytesy;
|
||||
}
|
||||
// top parts, skip inter module gap pixels and two chips
|
||||
else {
|
||||
src += (nModGapBytesy + 2 * nChipBytesy - 2 * row1Bytes);
|
||||
dst += (nModGapBytesy + 2 * nChipBytesy);
|
||||
}
|
||||
}
|
||||
|
||||
// return gapdatabytes;
|
||||
// horizontal filling
|
||||
{
|
||||
uint8_t temp, g1, g2;
|
||||
char *dst_prevline = nullptr;
|
||||
dst = gpImage;
|
||||
for (int row = 0; row < nychip; ++row) { // for each chip row
|
||||
dst += (b1chipy * nxb);
|
||||
// horizontal copying of gap pixels from neighboring past line
|
||||
// (bottom parts)
|
||||
if (row < nychip - 1) {
|
||||
dst_prevline = dst - nxb;
|
||||
for (int gapline = 0; gapline < nxb; ++gapline) {
|
||||
temp = (*((uint8_t *)dst_prevline));
|
||||
g1 = ((temp >> 4) / 2);
|
||||
g2 = ((temp & 0xF) / 2);
|
||||
(*((uint8_t *)dst_prevline)) = (g1 << 4) + g2;
|
||||
(*((uint8_t *)dst)) = (*((uint8_t *)dst_prevline));
|
||||
++dst;
|
||||
++dst_prevline;
|
||||
}
|
||||
}
|
||||
|
||||
// horizontal copying of gap pixels from neihboring future line (top
|
||||
// part)
|
||||
if (row > 0) {
|
||||
dst -= ((b1chipy + 1) * nxb);
|
||||
dst_prevline = dst + nxb;
|
||||
for (int gapline = 0; gapline < nxb; ++gapline) {
|
||||
temp = (*((uint8_t *)dst_prevline));
|
||||
g1 = ((temp >> 4) / 2);
|
||||
g2 = ((temp & 0xF) / 2);
|
||||
temp = (g1 << 4) + g2;
|
||||
(*((uint8_t *)dst_prevline)) = temp;
|
||||
(*((uint8_t *)dst)) = temp;
|
||||
++dst;
|
||||
++dst_prevline;
|
||||
}
|
||||
dst += ((b1chipy + 1) * nxb);
|
||||
}
|
||||
|
||||
dst += nxb;
|
||||
}
|
||||
}
|
||||
|
||||
return gapdatabytes;
|
||||
nPixelsx = nTotx;
|
||||
nPixelsy = nToty;
|
||||
return imagesize;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool DetectorImpl::enableDataStreamingToClient(int enable) {
|
||||
if (enable >= 0) {
|
||||
// destroy data threads
|
||||
|
@ -16,7 +16,7 @@ class detectorData;
|
||||
#include <vector>
|
||||
|
||||
#define MULTI_SHMAPIVERSION 0x190809
|
||||
#define MULTI_SHMVERSION 0x200131
|
||||
#define MULTI_SHMVERSION 0x200319
|
||||
#define SHORT_STRING_LENGTH 50
|
||||
|
||||
#include <future>
|
||||
@ -47,10 +47,7 @@ struct sharedMultiSlsDetector {
|
||||
/** last time stamp when accessing the shared memory */
|
||||
char lastDate[SHORT_STRING_LENGTH];
|
||||
|
||||
/** number of sls detectors in shared memory */
|
||||
int numberOfDetectors;
|
||||
|
||||
/** multi detector type */
|
||||
slsDetectorDefs::detectorType multiDetectorType;
|
||||
|
||||
/** END OF FIXED PATTERN
|
||||
@ -62,11 +59,9 @@ struct sharedMultiSlsDetector {
|
||||
/** max number of channels for complete detector*/
|
||||
slsDetectorDefs::xy numberOfChannels;
|
||||
|
||||
/** flag for acquiring */
|
||||
bool acquiringFlag;
|
||||
|
||||
/** initial checks */
|
||||
bool initialChecks;
|
||||
bool gapPixels;
|
||||
};
|
||||
|
||||
class DetectorImpl : public virtual slsDetectorDefs {
|
||||
@ -236,11 +231,10 @@ class DetectorImpl : public virtual slsDetectorDefs {
|
||||
* Sets maximum number of channels of all sls detectors */
|
||||
void setNumberOfChannels(const slsDetectorDefs::xy c);
|
||||
|
||||
/**
|
||||
* Enable gap pixels, only for Eiger and for 8,16 and 32 bit mode. (Eiger)
|
||||
* 4 bit mode gap pixels only in gui call back
|
||||
*/
|
||||
void setGapPixelsinReceiver(bool enable);
|
||||
/** [Eiger][Jungfrau] */
|
||||
bool getGapPixelsinCallback() const;
|
||||
/** [Eiger][Jungfrau] */
|
||||
void setGapPixelsinCallback(const bool enable);
|
||||
|
||||
/**
|
||||
* Enable data streaming to client
|
||||
@ -347,15 +341,18 @@ class DetectorImpl : public virtual slsDetectorDefs {
|
||||
*/
|
||||
void readFrameFromReceiver();
|
||||
|
||||
/**
|
||||
* add gap pixels to the image (only for Eiger in 4 bit mode)
|
||||
/** [Eiger][Jungfrau]
|
||||
* add gap pixels to the imag
|
||||
* @param image pointer to image without gap pixels
|
||||
* @param gpImage poiner to image with gap pixels, if NULL, allocated
|
||||
* inside function
|
||||
* quadEnable quad enabled
|
||||
* @returns number of data bytes of image with gap pixels
|
||||
* @param quadEnable quad enabled
|
||||
* @param dr dynamic range
|
||||
* @param nPixelsx number of pixels in X axis (updated)
|
||||
* @param nPixelsy number of pixels in Y axis (updated)
|
||||
* @returns total data bytes for updated image
|
||||
*/
|
||||
int processImageWithGapPixels(char *image, char *&gpImage, bool quadEnable);
|
||||
int InsertGapPixels(char *image, char *&gpImage, bool quadEnable, int dr,
|
||||
int &nPixelsx, int &nPixelsy);
|
||||
|
||||
double setTotalProgress();
|
||||
|
||||
|
@ -410,7 +410,6 @@ void Module::initializeDetectorStructure(detectorType type) {
|
||||
shm()->zmqport = DEFAULT_ZMQ_CL_PORTNO +
|
||||
(detId * ((shm()->myDetectorType == EIGER) ? 2 : 1));
|
||||
shm()->zmqip = IpAddr{};
|
||||
shm()->gappixels = 0U;
|
||||
shm()->numUDPInterfaces = 1;
|
||||
shm()->stoppedFlag = false;
|
||||
|
||||
@ -422,8 +421,6 @@ void Module::initializeDetectorStructure(detectorType type) {
|
||||
shm()->nChip.y = parameters.nChipY;
|
||||
shm()->nDacs = parameters.nDacs;
|
||||
shm()->dynamicRange = parameters.dynamicRange;
|
||||
shm()->nGappixels.x = parameters.nGappixelsX;
|
||||
shm()->nGappixels.y = parameters.nGappixelsY;
|
||||
}
|
||||
|
||||
int Module::sendModule(sls_detector_module *myMod,
|
||||
@ -582,10 +579,8 @@ void Module::updateNumberOfChannels() {
|
||||
|
||||
slsDetectorDefs::xy Module::getNumberOfChannels() const {
|
||||
slsDetectorDefs::xy coord{};
|
||||
coord.x = (shm()->nChan.x * shm()->nChip.x +
|
||||
shm()->gappixels * shm()->nGappixels.x);
|
||||
coord.y = (shm()->nChan.y * shm()->nChip.y +
|
||||
shm()->gappixels * shm()->nGappixels.y);
|
||||
coord.x = (shm()->nChan.x * shm()->nChip.x);
|
||||
coord.y = (shm()->nChan.y * shm()->nChip.y);
|
||||
return coord;
|
||||
}
|
||||
|
||||
@ -937,23 +932,17 @@ int Module::getThresholdEnergy() {
|
||||
return retval;
|
||||
}
|
||||
|
||||
int Module::setThresholdEnergy(int e_eV, detectorSettings isettings,
|
||||
void Module::setThresholdEnergy(int e_eV, detectorSettings isettings,
|
||||
int tb) {
|
||||
|
||||
// check as there is client processing
|
||||
if (shm()->myDetectorType == EIGER) {
|
||||
setThresholdEnergyAndSettings(e_eV, isettings, tb);
|
||||
return e_eV;
|
||||
}
|
||||
|
||||
// moench - send threshold energy to processor
|
||||
else if (shm()->myDetectorType == MOENCH) {
|
||||
std::string result =
|
||||
setAdditionalJsonParameter("threshold", std::to_string(e_eV));
|
||||
if (result == std::to_string(e_eV)) {
|
||||
return e_eV;
|
||||
}
|
||||
return -1;
|
||||
setAdditionalJsonParameter("threshold", std::to_string(e_eV));
|
||||
}
|
||||
throw RuntimeError(
|
||||
"Set threshold energy not implemented for this detector");
|
||||
@ -1719,7 +1708,6 @@ std::string Module::setReceiverHostname(const std::string &receiverIP) {
|
||||
setSubDeadTime(getSubDeadTime());
|
||||
setDynamicRange(shm()->dynamicRange);
|
||||
activate(-1);
|
||||
enableGapPixels(shm()->gappixels);
|
||||
enableTenGigabitEthernet(-1);
|
||||
setQuad(getQuad());
|
||||
break;
|
||||
@ -2105,106 +2093,99 @@ void Module::setTransmissionDelayRight(int value) {
|
||||
}
|
||||
|
||||
|
||||
void Module::setAdditionalJsonHeader(const std::string &jsonheader) {
|
||||
void Module::setAdditionalJsonHeader(const std::map<std::string, std::string> &jsonHeader) {
|
||||
if (!shm()->useReceiverFlag) {
|
||||
throw RuntimeError("Set rx_hostname first to use receiver parameters (zmq json header)");
|
||||
}
|
||||
char args[MAX_STR_LENGTH]{};
|
||||
sls::strcpy_safe(args, jsonheader.c_str());
|
||||
sendToReceiver(F_SET_ADDITIONAL_JSON_HEADER, args, nullptr);
|
||||
}
|
||||
|
||||
std::string Module::getAdditionalJsonHeader() {
|
||||
if (!shm()->useReceiverFlag) {
|
||||
throw RuntimeError("Set rx_hostname first to use receiver parameters (zmq json header)");
|
||||
}
|
||||
char retvals[MAX_STR_LENGTH]{};
|
||||
sendToReceiver(F_GET_ADDITIONAL_JSON_HEADER, nullptr, retvals);
|
||||
return std::string(retvals);
|
||||
}
|
||||
|
||||
std::string Module::setAdditionalJsonParameter(const std::string &key,
|
||||
const std::string &value) {
|
||||
if (key.empty() || value.empty()) {
|
||||
throw RuntimeError(
|
||||
"Could not set additional json header parameter as the key or "
|
||||
"value is empty");
|
||||
}
|
||||
|
||||
// validation (ignore if key or value has , : ")
|
||||
if (key.find_first_of(",\":") != std::string::npos ||
|
||||
value.find_first_of(",\":") != std::string::npos) {
|
||||
throw RuntimeError("Could not set additional json header parameter as "
|
||||
"the key or value has "
|
||||
"illegal characters (,\":)");
|
||||
}
|
||||
|
||||
// create actual key to search for and actual value to put, (key has
|
||||
// additional ':' as value could exist the same way)
|
||||
std::string keyLiteral(std::string("\"") + key + std::string("\":"));
|
||||
std::string valueLiteral(value);
|
||||
// add quotations to value only if it is a string
|
||||
try {
|
||||
std::stoi(valueLiteral);
|
||||
} catch (...) {
|
||||
// add quotations if it failed to convert to integer, otherwise nothing
|
||||
valueLiteral.insert(0, "\"");
|
||||
valueLiteral.append("\"");
|
||||
}
|
||||
|
||||
std::string header = getAdditionalJsonHeader();
|
||||
size_t keyPos = header.find(keyLiteral);
|
||||
|
||||
// if key found, replace value
|
||||
if (keyPos != std::string::npos) {
|
||||
size_t valueStartPos = header.find(std::string(":"), keyPos) + 1;
|
||||
size_t valueEndPos = header.find(std::string(","), valueStartPos) - 1;
|
||||
// if valueEndPos doesnt find comma (end of string), it goes anyway to
|
||||
// end of line
|
||||
header.replace(valueStartPos, valueEndPos - valueStartPos + 1,
|
||||
valueLiteral);
|
||||
}
|
||||
|
||||
// key not found, append key value pair
|
||||
else {
|
||||
if (header.length() != 0U) {
|
||||
header.append(",");
|
||||
for (auto &it : jsonHeader) {
|
||||
if (it.first.empty() || it.first.length() > SHORT_STR_LENGTH ||
|
||||
it.second.length() > SHORT_STR_LENGTH ) {
|
||||
throw RuntimeError(it.first + " or " + it.second + " pair has invalid size. "
|
||||
"Key cannot be empty. Both can have max 20 characters");
|
||||
}
|
||||
header.append(keyLiteral + valueLiteral);
|
||||
}
|
||||
const int size = jsonHeader.size();
|
||||
int fnum = F_SET_ADDITIONAL_JSON_HEADER;
|
||||
int ret = FAIL;
|
||||
LOG(logDEBUG) << "Sending to receiver additional json header " << ToString(jsonHeader);
|
||||
auto client = ReceiverSocket(shm()->rxHostname, shm()->rxTCPPort);
|
||||
client.Send(&fnum, sizeof(fnum));
|
||||
client.Send(&size, sizeof(size));
|
||||
if (size > 0) {
|
||||
char args[size * 2][SHORT_STR_LENGTH];
|
||||
memset(args, 0, sizeof(args));
|
||||
int iarg = 0;
|
||||
for (auto &it : jsonHeader) {
|
||||
sls::strcpy_safe(args[iarg], it.first.c_str());
|
||||
sls::strcpy_safe(args[iarg + 1], it.second.c_str());
|
||||
iarg += 2;
|
||||
}
|
||||
client.Send(args, sizeof(args));
|
||||
}
|
||||
client.Receive(&ret, sizeof(ret));
|
||||
if (ret == FAIL) {
|
||||
char mess[MAX_STR_LENGTH]{};
|
||||
client.Receive(mess, MAX_STR_LENGTH);
|
||||
throw RuntimeError("Receiver " + std::to_string(detId) +
|
||||
" returned error: " + std::string(mess));
|
||||
}
|
||||
}
|
||||
|
||||
// update additional json header
|
||||
setAdditionalJsonHeader(header);
|
||||
return getAdditionalJsonParameter(key);
|
||||
std::map<std::string, std::string> Module::getAdditionalJsonHeader() {
|
||||
if (!shm()->useReceiverFlag) {
|
||||
throw RuntimeError("Set rx_hostname first to use receiver parameters (zmq json header)");
|
||||
}
|
||||
int fnum = F_GET_ADDITIONAL_JSON_HEADER;
|
||||
int ret = FAIL;
|
||||
int size = 0;
|
||||
auto client = ReceiverSocket(shm()->rxHostname, shm()->rxTCPPort);
|
||||
client.Send(&fnum, sizeof(fnum));
|
||||
client.Receive(&ret, sizeof(ret));
|
||||
if (ret == FAIL) {
|
||||
char mess[MAX_STR_LENGTH]{};
|
||||
client.Receive(mess, MAX_STR_LENGTH);
|
||||
throw RuntimeError("Receiver " + std::to_string(detId) +
|
||||
" returned error: " + std::string(mess));
|
||||
} else {
|
||||
client.Receive(&size, sizeof(size));
|
||||
std::map<std::string, std::string> retval;
|
||||
if (size > 0) {
|
||||
char retvals[size * 2][SHORT_STR_LENGTH];
|
||||
memset(retvals, 0, sizeof(retvals));
|
||||
client.Receive(retvals, sizeof(retvals));
|
||||
for (int i = 0; i < size; ++i) {
|
||||
retval[retvals[2 * i]] = retvals[2 * i + 1];
|
||||
}
|
||||
}
|
||||
LOG(logDEBUG) << "Getting additional json header " << ToString(retval);
|
||||
return retval;
|
||||
}
|
||||
}
|
||||
|
||||
void Module::setAdditionalJsonParameter(const std::string &key, const std::string &value) {
|
||||
if (!shm()->useReceiverFlag) {
|
||||
throw RuntimeError("Set rx_hostname first to use receiver parameters (zmq json parameter)");
|
||||
}
|
||||
if (key.empty() || key.length() > SHORT_STR_LENGTH ||
|
||||
value.length() > SHORT_STR_LENGTH ) {
|
||||
throw RuntimeError(key + " or " + value + " pair has invalid size. "
|
||||
"Key cannot be empty. Both can have max 2 characters");
|
||||
}
|
||||
char args[2][SHORT_STR_LENGTH]{};
|
||||
sls::strcpy_safe(args[0], key.c_str());
|
||||
sls::strcpy_safe(args[1], value.c_str());
|
||||
sendToReceiver(F_SET_ADDITIONAL_JSON_PARAMETER, args, nullptr);
|
||||
}
|
||||
|
||||
std::string Module::getAdditionalJsonParameter(const std::string &key) {
|
||||
// additional json header is empty
|
||||
std::string jsonheader = getAdditionalJsonHeader();
|
||||
if (jsonheader.empty())
|
||||
return jsonheader;
|
||||
|
||||
// add quotations before and after the key value
|
||||
std::string keyLiteral = key;
|
||||
keyLiteral.insert(0, "\"");
|
||||
keyLiteral.append("\"");
|
||||
|
||||
// loop through the parameters
|
||||
for (const auto ¶meter :
|
||||
sls::split(jsonheader, ',')) {
|
||||
// get a vector of key value pair for each parameter
|
||||
const auto &pairs = sls::split(parameter, ':');
|
||||
// match for key
|
||||
if (pairs[0] == keyLiteral) {
|
||||
// return value without quotations (if it has any)
|
||||
if (pairs[1][0] == '\"')
|
||||
return pairs[1].substr(1, pairs[1].length() - 2);
|
||||
else
|
||||
return pairs[1];
|
||||
}
|
||||
if (!shm()->useReceiverFlag) {
|
||||
throw RuntimeError("Set rx_hostname first to use receiver parameters (zmq json parameter)");
|
||||
}
|
||||
// return empty string as no match found with key
|
||||
return std::string();
|
||||
char arg[SHORT_STR_LENGTH]{};
|
||||
sls::strcpy_safe(arg, key.c_str());
|
||||
char retval[SHORT_STR_LENGTH]{};
|
||||
sendToReceiver(F_GET_ADDITIONAL_JSON_PARAMETER, arg, retval);
|
||||
return retval;
|
||||
}
|
||||
|
||||
int64_t Module::setReceiverUDPSocketBufferSize(int64_t udpsockbufsize) {
|
||||
@ -2672,24 +2653,6 @@ int Module::setAllTrimbits(int val) {
|
||||
return retval;
|
||||
}
|
||||
|
||||
int Module::enableGapPixels(int val) {
|
||||
if (val >= 0) {
|
||||
if (shm()->myDetectorType != EIGER) {
|
||||
throw NotImplementedError(
|
||||
"Function (enableGapPixels) not implemented for this detector");
|
||||
}
|
||||
int fnum = F_ENABLE_GAPPIXELS_IN_RECEIVER;
|
||||
int retval = -1;
|
||||
LOG(logDEBUG1) << "Sending gap pixels enable to receiver: " << val;
|
||||
if (shm()->useReceiverFlag) {
|
||||
sendToReceiver(fnum, val, retval);
|
||||
LOG(logDEBUG1) << "Gap pixels enable to receiver:" << retval;
|
||||
shm()->gappixels = retval;
|
||||
}
|
||||
}
|
||||
return shm()->gappixels;
|
||||
}
|
||||
|
||||
int Module::setTrimEn(const std::vector<int>& energies) {
|
||||
if (shm()->myDetectorType != EIGER) {
|
||||
throw RuntimeError("setTrimEn not implemented for this detector.");
|
||||
@ -3084,33 +3047,6 @@ void Module::execReceiverCommand(const std::string &cmd) {
|
||||
}
|
||||
}
|
||||
|
||||
void Module::updateCachedReceiverVariables() const {
|
||||
int fnum = F_UPDATE_RECEIVER_CLIENT;
|
||||
LOG(logDEBUG1) << "Sending update client to receiver server";
|
||||
|
||||
if (shm()->useReceiverFlag) {
|
||||
auto receiver =
|
||||
sls::ClientSocket("Receiver", shm()->rxHostname, shm()->rxTCPPort);
|
||||
receiver.sendCommandThenRead(fnum, nullptr, 0, nullptr, 0);
|
||||
int n = 0, i32 = 0;
|
||||
IpAddr ip;
|
||||
|
||||
n += receiver.Receive(&ip, sizeof(ip));
|
||||
LOG(logDEBUG1)
|
||||
<< "Updating receiver last modified by " << ip;
|
||||
|
||||
// gap pixels
|
||||
n += receiver.Receive(&i32, sizeof(i32));
|
||||
shm()->gappixels = i32;
|
||||
|
||||
if (n == 0) {
|
||||
throw RuntimeError(
|
||||
"Could not update receiver: " + std::string(shm()->rxHostname) +
|
||||
", received 0 bytes\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Module::sendMultiDetectorSize() {
|
||||
int args[]{shm()->multiSize.x, shm()->multiSize.y};
|
||||
int retval = -1;
|
||||
@ -3317,9 +3253,6 @@ std::vector<uint64_t> Module::getNumMissingPackets() const {
|
||||
throw RuntimeError("Receiver " + std::to_string(detId) +
|
||||
" returned error: " + std::string(mess));
|
||||
} else {
|
||||
if (ret == FORCE_UPDATE) {
|
||||
updateCachedReceiverVariables();
|
||||
}
|
||||
int nports = -1;
|
||||
client.Receive(&nports, sizeof(nports));
|
||||
uint64_t mp[nports];
|
||||
|
@ -9,11 +9,12 @@
|
||||
#include <array>
|
||||
#include <cmath>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
|
||||
class ServerInterface;
|
||||
|
||||
#define SLS_SHMAPIVERSION 0x190726
|
||||
#define SLS_SHMVERSION 0x200318
|
||||
#define SLS_SHMVERSION 0x200324
|
||||
|
||||
namespace sls{
|
||||
|
||||
@ -104,12 +105,6 @@ struct sharedSlsDetector {
|
||||
/** zmq tcp src ip address in client (only data) **/
|
||||
sls::IpAddr zmqip;
|
||||
|
||||
/** gap pixels enable */
|
||||
int gappixels;
|
||||
|
||||
/** gap pixels in each direction */
|
||||
slsDetectorDefs::xy nGappixels;
|
||||
|
||||
/** num udp interfaces */
|
||||
int numUDPInterfaces;
|
||||
|
||||
@ -221,10 +216,7 @@ class Module : public virtual slsDetectorDefs {
|
||||
*/
|
||||
void updateNumberOfChannels();
|
||||
|
||||
/**
|
||||
* Returns the total number of channels including gap pixels
|
||||
* @returns the total number of channels including gap pixels
|
||||
*/
|
||||
|
||||
slsDetectorDefs::xy getNumberOfChannels() const;
|
||||
|
||||
/**
|
||||
@ -353,9 +345,8 @@ class Module : public virtual slsDetectorDefs {
|
||||
* @param e_eV threshold in eV
|
||||
* @param isettings ev. change settings
|
||||
* @param tb 1 to include trimbits, 0 to exclude
|
||||
* @returns current threshold value in ev (-1 failed)
|
||||
*/
|
||||
int setThresholdEnergy(int e_eV, detectorSettings isettings = GET_SETTINGS,
|
||||
void setThresholdEnergy(int e_eV, detectorSettings isettings = GET_SETTINGS,
|
||||
int tb = 1);
|
||||
|
||||
/**
|
||||
@ -988,36 +979,14 @@ class Module : public virtual slsDetectorDefs {
|
||||
*/
|
||||
void setTransmissionDelayRight(int value);
|
||||
|
||||
/**
|
||||
* Sets the additional json header\sa sharedSlsDetector
|
||||
* @param jsonheader additional json header
|
||||
*/
|
||||
void setAdditionalJsonHeader(const std::string &jsonheader);
|
||||
/** empty vector deletes entire additional json header */
|
||||
void setAdditionalJsonHeader(const std::map<std::string, std::string> &jsonHeader);
|
||||
std::map<std::string, std::string> getAdditionalJsonHeader();
|
||||
|
||||
/**
|
||||
* Returns the additional json header \sa sharedSlsDetector
|
||||
* @returns the additional json header, returns "none" if default setting
|
||||
* and no custom ip set
|
||||
*/
|
||||
std::string getAdditionalJsonHeader();
|
||||
|
||||
/**
|
||||
* Sets the value for the additional json header parameter if found, else
|
||||
* append it
|
||||
* @param key additional json header parameter
|
||||
* @param value additional json header parameter value (cannot be empty)
|
||||
* @returns the additional json header parameter value,
|
||||
* empty if no parameter found in additional json header
|
||||
*/
|
||||
std::string setAdditionalJsonParameter(const std::string &key,
|
||||
const std::string &value);
|
||||
|
||||
/**
|
||||
* Returns the additional json header parameter value
|
||||
* @param key additional json header parameter
|
||||
* @returns the additional json header parameter value,
|
||||
* empty if no parameter found in additional json header
|
||||
*/
|
||||
* Sets the value for the additional json header parameter key if found, else
|
||||
* append it. If value empty, then deletes parameter */
|
||||
void setAdditionalJsonParameter(const std::string &key, const std::string &value);
|
||||
std::string getAdditionalJsonParameter(const std::string &key);
|
||||
|
||||
/**
|
||||
@ -1045,11 +1014,13 @@ class Module : public virtual slsDetectorDefs {
|
||||
/** [Gotthard][Jungfrau][CTB][Moench] */
|
||||
void executeBusTest();
|
||||
|
||||
/** [Gotthard] */
|
||||
/** [Gotthard][Eiger virtual] */
|
||||
int getImageTestMode();
|
||||
|
||||
/** [Gotthard] If 1, adds channel intensity with precalculated values.
|
||||
* Default is 0 */
|
||||
* Default is 0
|
||||
* [Eiger virtual] If 1, pixels are saturated. If 0, increasing intensity
|
||||
* Only for virtual servers */
|
||||
void setImageTestMode(const int value);
|
||||
|
||||
|
||||
@ -1232,14 +1203,6 @@ class Module : public virtual slsDetectorDefs {
|
||||
*/
|
||||
int setAllTrimbits(int val);
|
||||
|
||||
/**
|
||||
* Enable gap pixels, only for Eiger and for 8,16 and 32 bit mode. (Eiger)
|
||||
* 4 bit mode gap pixels only in gui call back
|
||||
* @param val 1 sets, 0 unsets, -1 gets
|
||||
* @returns gap pixel enable or -1 for error
|
||||
*/
|
||||
int enableGapPixels(int val = -1);
|
||||
|
||||
/**
|
||||
* Sets the number of trim energies and their value (Eiger)
|
||||
* \sa sharedSlsDetector
|
||||
@ -1436,11 +1399,6 @@ class Module : public virtual slsDetectorDefs {
|
||||
*/
|
||||
void execReceiverCommand(const std::string &cmd);
|
||||
|
||||
/**
|
||||
* Updates the shared memory receiving the data from the detector
|
||||
*/
|
||||
void updateCachedReceiverVariables() const;
|
||||
|
||||
/**
|
||||
* Send the multi detector size to the detector
|
||||
* @param detx number of detectors in x dir
|
||||
|
Reference in New Issue
Block a user