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:
Dhanya Thattil
2020-03-30 14:54:35 +02:00
committed by GitHub
parent 6a6af528ef
commit d58eb1dc6e
52 changed files with 1879 additions and 1398 deletions

View File

@ -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");
}

View File

@ -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.");

View File

@ -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);
}

View File

@ -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

View File

@ -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();

View File

@ -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 &parameter :
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];

View File

@ -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