Compare commits

...

47 Commits
7.0.0 ... 7.0.3

Author SHA1 Message Date
cfbe3c86cc 7.0.3.rc2 (#866) (#867)
*7.0.3.rc2
* moench: handling bug in post processing from receiver when partial_frames policy and empty frame happens, only json header without data is sent
2023-11-14 11:32:33 +01:00
4b414bfddb release notes 2023-11-12 15:39:58 +01:00
5ab64efe3e added python 3.12 to the conda build variants 2023-11-10 14:18:38 +01:00
bfe53c6693 udpated release notes 2023-11-09 15:10:17 +01:00
c64e87a2b6 7.0.3.rc: fix server logic in checking detector idle (#859)
* fix buggy logic in checking detector idle and an argument check
2023-11-09 14:21:11 +01:00
14e11e8b5b formatting and versioning 2023-11-08 11:43:09 +01:00
af3dc1e7f4 7.0.3.rc: execute command inside server fixed (from fix simulator tests and exec command PR) (#855)
* execute command inside server fixed (from fix simulator tests and exec command PR)
2023-11-08 09:25:52 +01:00
8174fc9691 Update RELEASE.txt 2023-11-07 12:34:10 +01:00
d6eac6da71 updated release notes 2023-11-07 11:22:09 +01:00
9b9b09ceaf 703rc/tests/fix execute command (#842)
* fix execute command
* fix for tests for ctb
2023-11-07 09:29:48 +01:00
4613c54f57 handling inconsistent fnums to be -1 in gui, so when one sets 0 (change of value) will also give an exception (#852) 2023-11-06 16:11:25 +01:00
58ac7ac280 7.0.3.rc: gui acq finished callback for different status (#847)
* fix acquisition finished status to have different status for different modules, but does not have to be error. for eg. jf sync fw (2.4.1 gives idle for master and stopped for slaves when stopping acquiistion)
2023-11-06 16:07:38 +01:00
82edfa75d3 7.0.3.rc: process the raw data files as a list (#848)
* Added file list option for moenchRawDataProcess
2023-11-03 12:10:20 +01:00
b6ef3bc39e updated release notest 2023-10-25 09:15:10 +02:00
2035666792 versioning and binaries updated 2023-10-25 08:43:23 +02:00
1ff4d806e7 minor 2023-10-25 08:25:02 +02:00
3861379653 updated release notes 2023-10-24 17:39:47 +02:00
91140bbb71 formatting 2023-10-24 11:17:18 +02:00
d44329117d fix warning for prev_val (variable size array) in tests (#836) 2023-10-23 15:52:59 +02:00
6c67025ea8 7.0.3.rc eiger: fw version to 32 (quad blocking trigger) (#832)
* eiger required fw version to 32: fix for blocking trigger in quad
2023-10-18 16:51:17 +02:00
37ce3d6f59 7.0.3.rc: jf sync: stopping master gives idle (#822)
* jf sync mode master could return idle when stopped and so not all modules return the same value and must check for 'stopped or idle', Also must throw if any of the module gives an error ( not jungfrau, but eiger could)

* added contains_only to sls::Result (#827)

* added variadic template for checking if a result contains only specified values

* fix for gcc4.8

* renamed to Result::contains_only

* stop on only the positions

---------

Co-authored-by: Erik Fröjdh <erik.frojdh@gmail.com>
2023-10-13 12:27:43 +02:00
1484d038de 7.03.rc: update 2d gain plot color map (if no x and ymin/max changes or window resizing): setFixedWidth was updating for window resize, updated virtual servers for g2 and jungfrau to keep changing gain and data for every frame. the data value (#818) 2023-10-03 17:22:03 +02:00
fb0090c79e removing the misleading word 'Simulating' when programmig fpga (#814) 2023-09-28 16:20:59 +02:00
adc68cd519 formatting 2023-09-28 15:51:40 +02:00
1566eef247 703rc/fix numeric limits (#812)
* fixed compilation for fedora for numeric_limits

* formatting
2023-09-28 10:49:02 +02:00
e7cd90db78 fixed crashing of moench03RawDataProcess when nframes>0 (#810) 2023-09-27 09:22:40 +02:00
45414149fe binaries in for the previous PR 2023-09-22 15:59:35 +02:00
48759f440e 703rc/fix port size (#802)
* validate port numbers in client

* validate port numbers created at virtual servers and receiver process as tcp ports
2023-09-18 08:59:53 +02:00
b367b7e431 fixed some interpolation issues (#796) 2023-08-28 13:38:19 +02:00
f0b2a6f6f9 update release notes 2023-08-25 14:02:50 +02:00
f761046bfc updated docs and versions 2023-07-12 16:50:13 +02:00
1a859b83db formatting 2023-07-12 16:06:31 +02:00
70bfc875a6 updating release notes 2023-07-11 17:02:27 +02:00
c0755308a4 updating release notes 2023-07-11 17:01:14 +02:00
ab5509e10c updating release notes 2023-07-11 17:00:42 +02:00
004cb26646 updated firmware versions for 7.0.2 2023-07-10 12:21:19 +02:00
a4f47a5945 synced master status running when setting to slave (#747)
* jf: unsync before setting master/slave and then sync (if it was set) to overcome master going into running state when making it a slave and synced

* add tests for this condition

* updated release notes, updated min fw version requirement for v1.0 boards
2023-05-25 11:04:05 +02:00
312f3f473d fix that only master starts second and not all (for start acq), typo with pos and masters list (#743) 2023-05-11 10:20:17 +02:00
5871086cd6 formatting 2023-05-08 17:04:04 +02:00
6a0fe823b3 enable fix g0 when in expert mode (when gain mode enabled and not just visible) (#736) 2023-05-08 14:20:21 +02:00
5912aae53e Rx roi zmq (#726)
adding rx_roi also in the zmq header for external guis to put the "yellow box".. sending full roi instead of -1, and sending for each zmq port. "(multiple yellow boxes)".
2023-05-08 12:23:05 +02:00
8833ccf5cc 7.0.2.rc (#721)
* row and column for jungfrau mixed up

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

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

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

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

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

* adding missing cstdint for gcc 13

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

---------

Co-authored-by: Erik Frojdh <erik.frojdh@gmail.com>
2023-05-08 12:11:19 +02:00
77c558a7be formatting 2023-03-24 12:54:55 +01:00
378fc301b8 updating client version, release version and project_version in CMakeLists.txt 2023-03-23 15:43:17 +01:00
87d6e16090 7.0.1 fix det server version (#702)
* check server version before initial checks, catch old server version exception, get old server version as 64 bit and print it along with exception
2023-03-23 15:37:01 +01:00
2ef021041c rx_arping sigchld (#701)
* rx_arping pclose gave -1 due to sigchld being ignored, fixed with sig handler doing a wait
2023-03-23 13:58:40 +01:00
574127b5ac fix hdf5 compilation using det spec fields in header (#700)
* fix hdf5 compilation using det spec fields in header
2023-03-23 12:30:38 +01:00
78 changed files with 889 additions and 1150 deletions

View File

@ -2,7 +2,7 @@
# Copyright (C) 2021 Contributors to the SLS Detector Package
cmake_minimum_required(VERSION 3.12)
project(slsDetectorPackage)
set(PROJECT_VERSION 7.0.0)
set(PROJECT_VERSION 7.0.3)
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG")

File diff suppressed because it is too large Load Diff

View File

@ -3,6 +3,5 @@ python:
- 3.9
- 3.10
- 3.11
- 3.12
numpy:
- 1.17

View File

@ -140,14 +140,21 @@ ZMQ: Json Header Format
"quad": unsigned int,
"addJsonHeader": {
string : string
}
},
"rx_roi": [
unsigned int,
unsigned int,
unsigned int,
unsigned int
]
}
+--------------+----------------------------------------------+
| Field | Description |
+--------------+----------------------------------------------+
| jsonversion | Version of the json header. |
| | Value at 4 for v6.x.x and v7.x.x |
| | Value at 4 for v6.x.x - v7.0.1 |
| | Value at 5 for v7.0.2 |
+--------------+----------------------------------------------+
| bitmode | Bits per pixel [4|8|16|32] |
+--------------+----------------------------------------------+
@ -222,7 +229,10 @@ ZMQ: Json Header Format
| addJsonHeader| Optional custom parameters that is required |
| | for processing code. |
+--------------+----------------------------------------------+
| rx_roi | ROI in the receiver per port (xmin, xmax, |
| | ymin, ymax). For external guis to know |
| | what is saved |
+--------------+----------------------------------------------+
SLS Receiver Header Format
--------------------------

View File

@ -3,33 +3,34 @@
### edit with hostname or IP address of your detector
############################################
#hostname bchip181+
hostname bchip135
hostname bchip076
#############################################
### edit with hostname or 1Gbs IP address of your server
############################################
rx_hostname mpc2011
rx_hostname mpc2011:7777
#############################################
### edit with 10 Gbs IP of your server
############################################
udp_dstip 10.1.1.102
udp_dstip 10.1.2.102
#############################################
### edit with any number in the subnet of your server (first 3 numbers as above)
############################################
udp_srcip 10.1.1.19
udp_dstport 32411
udp_srcip 10.1.2.19
udp_dstport 32777
#############################################
### edit with 10 Gbs IP of your server
############################################
rx_zmqip 10.1.1.102
rx_zmqport 50003
rx_zmqip 10.1.2.102
rx_zmqport 9003
#############################################
### edit with 1 Gbs IP of PC where you will run the GUI
############################################
zmqip 129.129.202.57
zmqport 50001
zmqport 9005
@ -38,7 +39,7 @@ rx_zmqstream 1
frames 100000
frames 1
period 0.0006
exptime 0.00035
@ -49,7 +50,7 @@ fpath /mnt/moench_data/scratch1/
fwrite 0
rx_jsonpara frameMode frame
rx_jsonpara frameMode newPedestal
rx_jsonpara detectorMode counting
rx_discardpolicy discardpartial

View File

@ -1 +0,0 @@
../slsDetectorServers/ctbDetectorServer/bin/ctbDetectorServerv7.0.0

View File

@ -0,0 +1 @@
../slsDetectorServers/ctbDetectorServer/bin/ctbDetectorServerv7.0.3

View File

@ -1 +0,0 @@
../slsDetectorServers/eigerDetectorServer/bin/eigerDetectorServerv7.0.0

View File

@ -0,0 +1 @@
../slsDetectorServers/eigerDetectorServer/bin/eigerDetectorServerv7.0.3

View File

@ -1 +0,0 @@
../slsDetectorServers/gotthard2DetectorServer/bin/gotthard2DetectorServerv7.0.0

View File

@ -0,0 +1 @@
../slsDetectorServers/gotthard2DetectorServer/bin/gotthard2DetectorServerv7.0.3

View File

@ -1 +0,0 @@
../slsDetectorServers/gotthardDetectorServer/bin/gotthardDetectorServerv7.0.0

View File

@ -0,0 +1 @@
../slsDetectorServers/gotthardDetectorServer/bin/gotthardDetectorServerv7.0.3

View File

@ -1 +0,0 @@
../slsDetectorServers/jungfrauDetectorServer/bin/jungfrauDetectorServerv7.0.0

View File

@ -0,0 +1 @@
../slsDetectorServers/jungfrauDetectorServer/bin/jungfrauDetectorServerv7.0.3

View File

@ -1 +0,0 @@
../slsDetectorServers/moenchDetectorServer/bin/moenchDetectorServerv7.0.0

View File

@ -0,0 +1 @@
../slsDetectorServers/moenchDetectorServer/bin/moenchDetectorServerv7.0.3

View File

@ -1 +0,0 @@
../slsDetectorServers/mythen3DetectorServer/bin/mythen3DetectorServerv7.0.0

View File

@ -0,0 +1 @@
../slsDetectorServers/mythen3DetectorServer/bin/mythen3DetectorServerv7.0.3

View File

@ -42,7 +42,7 @@ class moench03T1ReceiverDataNew : public slsDetectorData<uint16_t> {
int sc_width;
int sc_height;
const int nSamples;
int headerSize;
double ghost[200][25];
// Single point of definition if we need to customize
@ -62,7 +62,7 @@ class moench03T1ReceiverDataNew : public slsDetectorData<uint16_t> {
moench03T1ReceiverDataNew(int ns = 5000)
: slsDetectorData<uint16_t>(400, 400, ns * 2 * 32 + sizeof(header)),
nSamples(ns) {
headerSize=112;
int nadc = 32;
int sc_width = 25;
int sc_height = 200;
@ -250,13 +250,22 @@ class moench03T1ReceiverDataNew : public slsDetectorData<uint16_t> {
virtual char *readNextFrame(std::ifstream &filebin, int &ff, int &np,
char *data) {
np = 0;
if (filebin.is_open()) {
if (filebin.read(data, dataSize)) {
ff = getFrameNumber(data);
np = getPacketNumber(data);
return data;
}
}
if (filebin.is_open()) {
if (filebin.read(data, headerSize)) {
ff = getFrameNumber(data);
np = getPacketNumber(data);
if (np>0)
filebin.read(data+headerSize, dataSize-headerSize);
return data;
}
/* if (filebin.read(data, dataSize)) { */
/* ff = getFrameNumber(data); */
/* np = getPacketNumber(data); */
/* return data; */
/* } */
}
return nullptr;
}

View File

@ -13,22 +13,7 @@ class etaInterpolationGlobal : public etaInterpolationBase {
virtual void prepareInterpolation(int &ok) {
ok = 1;
#ifdef MYROOT1
if (hhx)
delete hhx;
if (hhy)
delete hhy;
hhx = new TH2D("hhx", "hhx", heta->GetNbinsX(),
heta->GetXaxis()->GetXmin(), heta->GetXaxis()->GetXmax(),
heta->GetNbinsY(), heta->GetYaxis()->GetXmin(),
heta->GetYaxis()->GetXmax());
hhy = new TH2D("hhy", "hhy", heta->GetNbinsX(),
heta->GetXaxis()->GetXmin(), heta->GetXaxis()->GetXmax(),
heta->GetNbinsY(), heta->GetYaxis()->GetXmin(),
heta->GetYaxis()->GetXmax());
#endif
///*Eta Distribution Rebinning*///
double bsize = 1. / nSubPixels; // precision

View File

@ -357,6 +357,16 @@ class slsInterpolation {
}
}
/* cout << "(((" << totquad << "\t" << corner << endl; */
/* for (int iy=0; iy<3; iy++) { */
/* for (int ix=0; ix<3; ix++) */
/* cout << cl[ix+iy*3] <<"\t"; */
/* cout << endl; */
/* } */
/* cout << ")))" << endl; */
return corner;
}
@ -370,6 +380,10 @@ class slsInterpolation {
etax = r / totquad;
etay = t / totquad;
}
/* cout << "************" << endl; */
/* cout << sDum[0][0]<< "\t"<<sDum[0][1] << endl << sDum[1][0]<< "\t"<<sDum[1][1] << endl; */
/* cout << "***************" <<endl; */
/* cout << etax << " " << etay << endl; */
return 0;
}

View File

@ -33,7 +33,7 @@ int main(int argc, char *argv[]) {
#ifndef FF
if (argc < 9) {
cout << "Wrong usage! Should be: " << argv[0]
<< " infile etafile outfile runmin runmax ns cmin cmax" << endl;
<< " infile etafile outfile runmin runmax ns [cmin cmax xmin xmax ymin ymax]" << endl;
return 1;
}
#endif
@ -41,7 +41,7 @@ int main(int argc, char *argv[]) {
#ifdef FF
if (argc < 7) {
cout << "Wrong usage! Should be: " << argv[0]
<< " infile etafile runmin runmax cmin cmax" << endl;
<< " infile etafile runmin runmax [cmin cmax xmin xmax ymin ymax]" << endl;
return 1;
}
#endif
@ -65,13 +65,30 @@ int main(int argc, char *argv[]) {
nsubpix = atoi(argv[iarg++]);
cout << "Subpix: " << nsubpix << endl;
#endif
float cmin = atof(argv[iarg++]);
float cmax = atof(argv[iarg++]);
float cmin = 0;
float cmax=1000000;
if (argc>iarg)
cmin=atof(argv[iarg++]);
if (argc>iarg)
cmax= atof(argv[iarg++]);
cout << "Energy min: " << cmin << endl;
cout << "Energy max: " << cmax << endl;
int xmin=0, xmax=NC, ymin=0, ymax=NR;
if (argc>iarg)
xmin=atof(argv[iarg++]);
if (argc>iarg)
xmax= atof(argv[iarg++]);
if (argc>iarg)
ymin=atof(argv[iarg++]);
if (argc>iarg)
ymax= atof(argv[iarg++]);
// int etabins=500;
int etabins = 1000; // nsubpix*2*100;
double etamin = -1, etamax = 2;
double etamin = -0.25, etamax = 1.25;
// double etamin=-0.1, etamax=1.1;
// double eta3min = -2, eta3max = 2;
double sum, totquad;
@ -80,7 +97,7 @@ int main(int argc, char *argv[]) {
// double eta3x, eta3y, int3_x, int3_y, noint_x, noint_y;
int ix, iy, isx, isy;
int nframes = 0, lastframe = -1;
int nframes = 0, lastframe = -1, iframe, nphFrame;
//double d_x, d_y, res = 5, xx, yy;
int nph = 0, totph = 0;
//badph = 0,
@ -98,7 +115,7 @@ int main(int argc, char *argv[]) {
// int nSubPixels = nsubpix;
#ifndef NOINTERPOLATION
eta2InterpolationPosXY *interp =
new eta2InterpolationPosXY(NC, NR, nsubpix, etabins, etamin, etamax);
new eta2InterpolationPosXY(NC, NR, nsubpix, nsubpix, etabins, etabins, etamin, etamax);
// eta2InterpolationCleverAdaptiveBins *interp=new
// eta2InterpolationCleverAdaptiveBins(NC, NR, nsubpix, etabins, etamin,
// etamax);
@ -107,8 +124,8 @@ int main(int argc, char *argv[]) {
noInterpolation *interp = new noInterpolation(NC, NR, nsubpix);
#endif
#ifndef FF
int quad;
#ifndef FF
#ifndef NOINTERPOLATION
char fname[10000];
int ok;
@ -142,19 +159,26 @@ int main(int argc, char *argv[]) {
#endif
int irun;
for (irun = runmin; irun < runmax; irun++) {
for (irun = runmin; irun <= runmax; irun++) {
sprintf(infname, argv[1], irun);
#ifndef FF
sprintf(outfname, argv[3], irun);
#endif
f = fopen(infname, "r");
if (f) {
cout << infname << endl;
nframes = 0;
//f0 = -1;
while (cl.read(f)) {
//iff=0;
while (fread((void*)&iframe, 1, sizeof(int), f)) {
//n=0;
if (fread((void*)&nphFrame, 1, sizeof(int), f)) {
for (int iph=0; iph<nphFrame; iph++) {
//while (cl.read(f)) {
if (cl.read(f)) {
totph++;
if (lastframe != cl.iframe) {
lastframe = cl.iframe;
@ -165,18 +189,28 @@ int main(int argc, char *argv[]) {
nframes++;
}
// quad=interp->calcQuad(cl.get_cluster(), sum, totquad, sDum);
#ifndef FF
// #ifndef FF
// quad = interp->calcEta(cl.get_cluster(), etax, etay, sum,
// totquad, sDum);
// #endif
// #ifdef FF
quad = interp->calcEta(cl.get_cluster(), etax, etay, sum,
totquad, sDum);
#endif
#ifdef FF
interp->calcEta(cl.get_cluster(), etax, etay, sum,
totquad, sDum);
#endif
/* cl.print();
cout << "(" << etax <<","<< etay <<")"<< quad<< endl;
*/
//#endif
if (sum > cmin && totquad / sum > 0.8 && totquad / sum < 1.2 &&
sum < cmax) {
nph++;
if (totquad > cmin && cl.x >= xmin && cl.x <= xmax &&
cl.y >= ymin && cl.y <= ymax &&
totquad < cmax) {
// if (sum > cmin && totquad / sum > 0.8 && totquad / sum < 1.2 &&
// sum < cmax) {
nph++;
// if (sum>200 && sum<580) {
// interp->getInterpolatedPosition(cl.x,cl.y,
// totquad,quad,cl.get_cluster(),int_x, int_y);
@ -227,9 +261,12 @@ int main(int argc, char *argv[]) {
#ifdef FF
interp->writeFlatField(outfname);
#endif
}
}
}
}
}
}
}
fclose(f);
#ifdef FF

View File

@ -304,18 +304,38 @@ int main(int argc, char *argv[]) {
int ifile = 0;
mt->setFrameMode(eFrame);
int filelist=0;
ifstream flist;
flist.open (fformat, std::ifstream::in);
if (flist.is_open()) {
runmin=0;
runmax=0;
while (flist.getline(ffname,10000)){
cout << ffname << endl;
runmax++;
}
runmax--;
flist.close();
cout << "Found " << runmax << " files " << endl;
flist.open (fformat, std::ifstream::in);
}
for (int irun = runmin; irun <= runmax; irun++) {
cout << "DATA ";
// sprintf(fn,fformat,irun);
sprintf(ffname, "%s/%s.raw", indir, fformat);
sprintf(fname, (const char*)ffname, irun);
sprintf(ffname, "%s/%s.tiff", outdir, fformat);
sprintf(imgfname, (const char*)ffname, irun);
sprintf(ffname, "%s/%s.clust", outdir, fformat);
sprintf(cfname, (const char*)ffname, irun);
if (flist.is_open()) {
flist.getline(ffname,10000);
cout << "file list " << ffname << endl;
} else {
sprintf(ffname,(const char*)fformat,irun);
cout << "loop " << ffname << endl;
}
cout << "ffname "<<ffname << endl;
sprintf(fname, "%s/%s.raw",indir,ffname);
sprintf(imgfname, "%s/%s.tiff",outdir,ffname);
sprintf(cfname, "%s/%s.clust",outdir,ffname);
cout << fname << " ";
cout << imgfname << endl;
cout << imgfname << " " << cfname << endl;
std::time(&end_time);
cout << std::ctime(&end_time) << endl;
// cout << fname << " " << outfname << " " << imgfname << endl;
@ -349,13 +369,15 @@ int main(int argc, char *argv[]) {
mt->popFree(buff);
ifr++;
if (ifr % 100 == 0)
if (ifr % 10000 == 0)
cout << ifr << " " << ff << endl;
if (nframes > 0) {
if (ifr % nframes == 0) {
sprintf(ffname, "%s/%s_f%05d.tiff", outdir, fformat,
ifile);
sprintf(imgfname, (const char*)ffname, irun);
sprintf(imgfname, "%s/%s_f%05d.tiff",outdir,ffname,ifile);
while (mt->isBusy())
;
mt->writeImage(imgfname, thr1);
mt->clearImage();
ifile++;
@ -374,13 +396,13 @@ int main(int argc, char *argv[]) {
}
if (nframes >= 0) {
if (nframes > 0) {
sprintf(ffname, "%s/%s_f%05d.tiff", outdir, fformat, ifile);
sprintf(imgfname, (const char*)ffname, irun);
sprintf(imgfname, "%s/%s_f%05d.tiff",outdir,ffname,ifile);
} else {
sprintf(ffname, "%s/%s.tiff", outdir, fformat);
sprintf(imgfname, (const char*)ffname, irun);
sprintf(imgfname, "%s/%s_f%05d.tiff",outdir,ffname,ifile);
}
cout << "Writing tiff to " << imgfname << " " << thr1 << endl;
while (mt->isBusy())
;
mt->writeImage(imgfname, thr1);
mt->clearImage();
if (of) {
@ -395,11 +417,12 @@ int main(int argc, char *argv[]) {
cout << "Could not open " << fname << " for reading " << endl;
}
if (nframes < 0) {
sprintf(ffname, "%s/%s.tiff", outdir, fformat);
strcpy(imgfname, ffname);
cout << "Writing tiff to " << imgfname << " " << thr1 << endl;
mt->writeImage(imgfname, thr1);
sprintf(imgfname, "%s/%s_tot.tiff",outdir,ffname);
cout << "Writing tiff to " << imgfname << " " << thr1 << endl;
mt->writeImage(imgfname, thr1);
}
if (flist.is_open()) {
flist.close();
}
return 0;
}

View File

@ -720,6 +720,22 @@ int main(int argc, char *argv[]) {
ymin >> ymax;
}
if (addJsonHeader.find("xMin") != addJsonHeader.end()) {
istringstream(addJsonHeader.at("xMin")) >> xmin;
}
if (addJsonHeader.find("yMin") != addJsonHeader.end()) {
istringstream(addJsonHeader.at("yMin")) >> ymin;
}
if (addJsonHeader.find("xMax") != addJsonHeader.end()) {
istringstream(addJsonHeader.at("xMax")) >> xmax;
}
if (addJsonHeader.find("yMax") != addJsonHeader.end()) {
istringstream(addJsonHeader.at("yMax")) >> ymax;
}
cprintf(MAGENTA, "%d %d %d %d\n", xmin, xmax, ymin, ymax);
mt->setROI(xmin, xmax, ymin, ymax);
if (addJsonHeader.find("dynamicRange") != addJsonHeader.end()) {

View File

@ -533,7 +533,7 @@ class singlePhotonDetector : public analogDetector<uint16_t> {
(clusters + nph)->print();
cout << max << " " << val[iy * nx + ix] << endl;
}
good = 1;
//good = 1;
if (eMin > 0 && tot < eMin)
good = 0;
if (eMax > 0 && tot > eMax)
@ -542,7 +542,7 @@ class singlePhotonDetector : public analogDetector<uint16_t> {
nph++;
image[iy * nx + ix]++;
}
good=1;
} else if (ee == PEDESTAL) {
addToPedestal(data, ix, iy, cm);
} /*else {

View File

@ -193,6 +193,7 @@ void qDrawPlot::SetupPlots() {
gainplot2d = new SlsQt2DPlot(boxPlot, true);
gainplot2d->SetData(nPixelsX, -0.5, nPixelsX - 0.5, nPixelsY, -0.5,
nPixelsY - 0.5, gainData);
gainplot2d->Update();
gainplot2d->hide();
connect(plot2d, SIGNAL(PlotZoomedSignal(const QRectF &)), this,
SLOT(Zoom2DGainPlot(const QRectF &)));
@ -1009,6 +1010,7 @@ void qDrawPlot::Update2dPlot() {
if (isGainDataExtracted) {
gainplot2d->SetData(nPixelsX, -0.5, nPixelsX - 0.5, nPixelsY, -0.5,
nPixelsY - 0.5, gainData);
gainplot2d->Update();
if (!gainplot2d->isVisible()) {
gainplot2d->setFixedWidth(plot2d->width() /
qDefs::DATA_GAIN_PLOT_RATIO);

View File

@ -849,8 +849,9 @@ void qTabMeasurement::GetNextFrameNumber() {
"Inconsistent starting frame number for all detectors.");
spinNextFrameNumber->setValue(retval);
}
CATCH_DISPLAY("Could not get starting frame number.",
"qTabMeasurement::GetNextFrameNumber")
CATCH_HANDLE("Could not get starting frame number.",
"qTabMeasurement::GetNextFrameNumber", spinNextFrameNumber,
&QSpinBox::setValue, -1)
connect(spinNextFrameNumber, SIGNAL(valueChanged(int)), this,
SLOT(SetNextFrameNumber(int)));
}

View File

@ -132,7 +132,7 @@ void qTabSettings::SetupWidgetWindow() {
}
void qTabSettings::SetExportMode(bool exportMode) {
if (comboGainMode->isVisible()) {
if (comboGainMode->isEnabled()) {
ShowFixG0(exportMode);
}
}

View File

@ -5,7 +5,7 @@
#define LINKED_SERVER_NAME "eigerDetectorServer"
#define REQUIRED_FIRMWARE_VERSION (31)
#define REQUIRED_FIRMWARE_VERSION (32)
// virtual ones renamed for consistency
// real ones keep previous name for compatibility (already in production)
#ifdef VIRTUAL

View File

@ -3323,6 +3323,27 @@ void *start_timer(void *arg) {
break;
}
// change gain and data for every frame
{
const int nchannels = NCHIP * NCHAN;
int gainVal = 0;
for (int i = 0; i < nchannels; ++i) {
if ((i % nchannels) < 400) {
gainVal = 1 + frameNr;
} else if ((i % nchannels) < 800) {
gainVal = 2 + frameNr;
} else {
gainVal = 3 + frameNr;
}
int dataVal =
*((uint16_t *)(imageData + i * sizeof(uint16_t)));
dataVal += frameNr;
int channelVal =
(dataVal & ~GAIN_VAL_MSK) | (gainVal << GAIN_VAL_OFST);
*((uint16_t *)(imageData + i * sizeof(uint16_t))) =
(uint16_t)channelVal;
}
}
// sleep for exposure time
struct timespec begin, end;
clock_gettime(CLOCK_REALTIME, &begin);

View File

@ -1388,14 +1388,18 @@ int setMaster(enum MASTERINDEX m) {
char *master_names[] = {MASTER_NAMES};
LOG(logINFOBLUE, ("Setting up as %s in (%s server)\n", master_names[m],
(isControlServer ? "control" : "stop")));
int prevSync = getSynchronization();
setSynchronization(0);
int retval = -1;
int retMaster = OK;
switch (m) {
case OW_MASTER:
bus_w(CONTROL_REG, bus_r(CONTROL_REG) | CONTROL_MASTER_MSK);
isMaster(&retval);
if (retval != 1) {
LOG(logERROR, ("Could not set master\n"));
return FAIL;
retMaster = FAIL;
}
break;
case OW_SLAVE:
@ -1403,15 +1407,16 @@ int setMaster(enum MASTERINDEX m) {
isMaster(&retval);
if (retval != 0) {
LOG(logERROR, ("Could not set slave\n"));
return FAIL;
retMaster = FAIL;
}
break;
default:
LOG(logERROR, ("Cannot reset to hardware settings from client. Restart "
"detector server.\n"));
return FAIL;
retMaster = FAIL;
}
return OK;
setSynchronization(prevSync);
return retMaster;
}
int isMaster(int *retval) {
@ -1449,7 +1454,7 @@ void setTiming(enum timingMode arg) {
}
enum timingMode getTiming() {
if (bus_r(EXT_SIGNAL_REG) == EXT_SIGNAL_MSK)
if ((bus_r(EXT_SIGNAL_REG) & EXT_SIGNAL_MSK) >> EXT_SIGNAL_OFST)
return TRIGGER_EXPOSURE;
return AUTO_TIMING;
}
@ -1736,40 +1741,40 @@ int setDetectorPosition(int pos[]) {
detPos[2] = outerPos[X];
detPos[3] = outerPos[Y];
// row
// row [Y]
// outer
uint32_t addr = COORD_ROW_REG;
bus_w(addr,
(bus_r(addr) & ~COORD_ROW_OUTER_MSK) |
((outerPos[X] << COORD_ROW_OUTER_OFST) & COORD_ROW_OUTER_MSK));
((outerPos[Y] << COORD_ROW_OUTER_OFST) & COORD_ROW_OUTER_MSK));
if (((bus_r(addr) & COORD_ROW_OUTER_MSK) >> COORD_ROW_OUTER_OFST) !=
outerPos[X])
ret = FAIL;
// inner
bus_w(addr,
(bus_r(addr) & ~COORD_ROW_INNER_MSK) |
((innerPos[X] << COORD_ROW_INNER_OFST) & COORD_ROW_INNER_MSK));
if (((bus_r(addr) & COORD_ROW_INNER_MSK) >> COORD_ROW_INNER_OFST) !=
innerPos[X])
ret = FAIL;
// col
// outer
addr = COORD_COL_REG;
bus_w(addr,
(bus_r(addr) & ~COORD_COL_OUTER_MSK) |
((outerPos[Y] << COORD_COL_OUTER_OFST) & COORD_COL_OUTER_MSK));
if (((bus_r(addr) & COORD_COL_OUTER_MSK) >> COORD_COL_OUTER_OFST) !=
outerPos[Y])
ret = FAIL;
// inner
bus_w(addr,
(bus_r(addr) & ~COORD_COL_INNER_MSK) |
((innerPos[Y] << COORD_COL_INNER_OFST) & COORD_COL_INNER_MSK));
if (((bus_r(addr) & COORD_COL_INNER_MSK) >> COORD_COL_INNER_OFST) !=
(bus_r(addr) & ~COORD_ROW_INNER_MSK) |
((innerPos[Y] << COORD_ROW_INNER_OFST) & COORD_ROW_INNER_MSK));
if (((bus_r(addr) & COORD_ROW_INNER_MSK) >> COORD_ROW_INNER_OFST) !=
innerPos[Y])
ret = FAIL;
// col [X]
// outer
addr = COORD_COL_REG;
bus_w(addr,
(bus_r(addr) & ~COORD_COL_OUTER_MSK) |
((outerPos[X] << COORD_COL_OUTER_OFST) & COORD_COL_OUTER_MSK));
if (((bus_r(addr) & COORD_COL_OUTER_MSK) >> COORD_COL_OUTER_OFST) !=
outerPos[X])
ret = FAIL;
// inner
bus_w(addr,
(bus_r(addr) & ~COORD_COL_INNER_MSK) |
((innerPos[X] << COORD_COL_INNER_OFST) & COORD_COL_INNER_MSK));
if (((bus_r(addr) & COORD_COL_INNER_MSK) >> COORD_COL_INNER_OFST) !=
innerPos[X])
ret = FAIL;
if (ret == OK) {
if (getNumberofUDPInterfaces() == 1) {
LOG(logINFOBLUE, ("Position set to [%d, %d] #(col, row)\n",
@ -2627,6 +2632,7 @@ void *start_timer(void *arg) {
if (i % pixelsPerPacket == 0) {
++dataVal;
}
if ((i % 1024) < 300) {
gainVal = 1;
} else if ((i % 1024) < 600) {
@ -2667,6 +2673,28 @@ void *start_timer(void *arg) {
clock_gettime(CLOCK_REALTIME, &begin);
usleep(expUs);
// change gain and data for every frame
{
const int npixels = (NCHAN * NCHIP);
for (int i = 0; i < npixels; ++i) {
int gainVal = 0;
if ((i % 1024) < 300) {
gainVal = 1 + iframes;
} else if ((i % 1024) < 600) {
gainVal = 2 + iframes;
} else {
gainVal = 3 + iframes;
}
int dataVal =
*((uint16_t *)(imageData + i * sizeof(uint16_t)));
dataVal += iframes;
int pixelVal =
(dataVal & ~GAIN_VAL_MSK) | (gainVal << GAIN_VAL_OFST);
*((uint16_t *)(imageData + i * sizeof(uint16_t))) =
(uint16_t)pixelVal;
}
}
int srcOffset = 0;
int srcOffset2 = DATA_BYTES / 2;
int row0 = (numInterfaces == 1 ? detPos[1] : detPos[3]);

View File

@ -5,8 +5,8 @@
#include "sls/sls_detector_defs.h"
#define MIN_REQRD_VRSN_T_RD_API 0x171220
#define REQRD_FRMWRE_VRSN_BOARD2 0x221104 // 1.0 pcb (version = 010)
#define REQRD_FRMWRE_VRSN 0x221103 // 2.0 pcb (version = 011)
#define REQRD_FRMWRE_VRSN_BOARD2 0x230516 // 1.0 pcb (version = 010)
#define REQRD_FRMWRE_VRSN 0x230515 // 2.0 pcb (version = 011)
#define NUM_HARDWARE_VERSIONS (2)
#define HARDWARE_VERSION_NUMBERS \

View File

@ -13,6 +13,7 @@
#include "slsDetectorServer_funcs.h"
#include <getopt.h>
#include <limits.h>
#include <signal.h>
#include <string.h>
#include <unistd.h>
@ -276,6 +277,14 @@ int main(int argc, char *argv[]) {
LOG(logERROR, ("Could not set handler function for SIGINT"));
}
// validate control and stop port number
if (0 >= portno || portno > USHRT_MAX || 0 >= (portno + 1) ||
(portno + 1) > USHRT_MAX) {
LOG(logERROR, ("Invalid control server or stop server port "
"numbers (%d, %d). It must be in range 1 - %d",
portno, portno + 1, USHRT_MAX));
return -1;
}
if (sharedMemory_create(portno) == FAIL) {
return -1;
}

View File

@ -515,6 +515,11 @@ int executeCommand(char *command, char *result, enum TLogLevel level) {
fflush(stdout);
FILE *sysFile = popen(cmd, "r");
if (sysFile == NULL) {
ret = FAIL;
sprintf(mess, "Executing cmd[%s] failed\n", cmd);
return ret;
}
while (fgets(temp, tempsize, sysFile) != NULL) {
// size left excludes terminating character
size_t sizeleft = MAX_STR_LENGTH - strlen(result) - 1;
@ -530,17 +535,15 @@ int executeCommand(char *command, char *result, enum TLogLevel level) {
if (strlen(result) == 0) {
strcpy(result, "No result");
}
int retval = OK;
int success = pclose(sysFile);
if (success) {
retval = FAIL;
LOG(logERROR, ("Executing cmd[%s]:%s\n", cmd, result));
if (success == -1) {
ret = FAIL;
strcpy(mess, result);
LOG(logERROR, ("Executing cmd[%s] failed:%s\n", cmd, mess));
} else {
LOG(level, ("Result:\n[%s]\n", result));
}
return retval;
return ret;
}
int M_nofunc(int file_des) {
@ -568,7 +571,7 @@ int exec_command(int file_des) {
// set
if (Server_VerifyLock() == OK) {
ret = executeCommand(cmd, retval, logINFO);
executeCommand(cmd, retval, logINFO);
}
return Server_SendResult(file_des, OTHER, retval, sizeof(retval));
}
@ -4664,7 +4667,8 @@ int set_read_n_rows(int file_des) {
functionNotImplemented();
#else
// only set
if (Server_VerifyLock() == OK) {
if ((Server_VerifyLock() == OK) &&
(check_detector_idle("set number of rows") == OK)) {
if (arg <= 0 || arg > MAX_ROWS_PER_READOUT) {
ret = FAIL;
sprintf(mess,
@ -4696,8 +4700,7 @@ int set_read_n_rows(int file_des) {
LOG(logERROR, (mess));
} else
#elif JUNGFRAUD
if ((check_detector_idle("set number of rows") == OK) &&
(arg % READ_N_ROWS_MULTIPLE != 0)) {
if (arg % READ_N_ROWS_MULTIPLE != 0) {
ret = FAIL;
sprintf(mess,
"Could not set number of rows. %d must be a multiple "
@ -8280,9 +8283,9 @@ int set_master(int file_des) {
functionNotImplemented();
#else
// only set
if (Server_VerifyLock() == OK) {
if ((check_detector_idle("set master") == OK) &&
(arg != 0 && arg != 1)) {
if ((Server_VerifyLock() == OK) &&
(check_detector_idle("set master") == OK)) {
if (arg != 0 && arg != 1) {
ret = FAIL;
sprintf(mess, "Could not set master. Invalid argument %d.\n", arg);
LOG(logERROR, (mess));
@ -8836,9 +8839,9 @@ int set_flip_rows(int file_des) {
functionNotImplemented();
#else
// only set
if (Server_VerifyLock() == OK) {
if ((check_detector_idle("set flip rows") == OK) &&
(arg != 0 && arg != 1)) {
if ((Server_VerifyLock() == OK) &&
(check_detector_idle("set flip rows") == OK)) {
if (arg != 0 && arg != 1) {
ret = FAIL;
sprintf(mess, "Could not set flip rows. Invalid argument %d.\n",
arg);
@ -10160,9 +10163,9 @@ int set_synchronization(int file_des) {
functionNotImplemented();
#else
// only set
if (Server_VerifyLock() == OK) {
if ((check_detector_idle("set synchronization") == OK) &&
(arg != 0 && arg != 1)) {
if ((Server_VerifyLock() == OK) &&
(check_detector_idle("set synchronization") == OK)) {
if (arg != 0 && arg != 1) {
ret = FAIL;
sprintf(mess,
"Could not set synchronization. Invalid argument %d.\n",

View File

@ -2008,7 +2008,7 @@ class Detector {
///@}
private:
std::vector<int> getPortNumbers(int start_port);
std::vector<int> getValidPortNumbers(int start_port);
void updateRxRateCorrections();
void setNumberofUDPInterfaces_(int n, Positions pos);
};

View File

@ -16,6 +16,7 @@
#include <vector>
#include "sls/ToString.h"
#include "sls/TypeTraits.h"
#include "sls/container_utils.h"
namespace sls {
@ -128,6 +129,25 @@ template <class T, class Allocator = std::allocator<T>> class Result {
/** Test whether all elements of the result are equal */
bool equal() const noexcept { return allEqual(vec); }
/** Test whether any element of the result are equal to a value */
bool any(const T &value) const noexcept { return anyEqualTo(vec, value); }
template <typename V, typename... Args, typename = AllSame<V, Args...>>
typename std::enable_if<std::is_same<V, T>::value, bool>::type
contains_only(const V &a, const Args &...args) const noexcept {
auto values = {a, args...};
for (const auto &element : vec) {
int found = 0;
for (const auto &value : values) {
if (value == element)
found++;
}
if (!found)
return false;
}
return true;
}
/** Convert Result<T> to std::vector<T> */
operator std::vector<T>() { return vec; }
};

View File

@ -18,6 +18,7 @@
#include <chrono>
#include <fstream>
#include <set>
#include <thread>
namespace sls {
@ -108,6 +109,9 @@ void Detector::setHostname(const std::vector<std::string> &hostname) {
}
void Detector::setVirtualDetectorServers(int numServers, int startingPort) {
for (int i = 0; i != numServers; ++i) {
validatePortNumber(startingPort + i * 2);
}
pimpl->setVirtualDetectorServers(numServers, startingPort);
}
@ -845,18 +849,26 @@ void Detector::startDetectorReadout() {
void Detector::stopDetector(Positions pos) {
// stop and check status X times
int retries{0};
// avoid default construction of runStatus::IDLE on squash
auto status = getDetectorStatus().squash(defs::runStatus::RUNNING);
while (status != defs::runStatus::IDLE &&
status != defs::runStatus::STOPPED) {
if (status == defs::runStatus::ERROR) {
throw RuntimeError(
"Could not stop detector. Returned error status.");
auto status = getDetectorStatus(pos);
// jf sync fix: status [stopped or idle] = [stopped]
// sync issue: (master idle sometimes, slaves stopped)
// eiger fix: stop multiple times from multi client till all modules stopped
// issue: asynchronous start and stop scripts with a module being started
// (stop before) and waiting for the other to be done. So a module that was
// idle before stopping will return running (after async start script) when
// getting status after, which will then be stopped again.
while (!status.contains_only(defs::runStatus::IDLE,
defs::runStatus::STOPPED)) {
if (status.any(defs::runStatus::ERROR)) {
throw RuntimeError("Could not stop detector. At least one module "
"returned error status.");
}
pimpl->Parallel(&Module::stopAcquisition, pos);
status = getDetectorStatus().squash(defs::runStatus::RUNNING);
pimpl->stopDetector(pos);
status = getDetectorStatus(pos);
++retries;
if (retries == 10)
@ -875,7 +887,7 @@ void Detector::stopDetector(Positions pos) {
for (auto it : res) {
maxVal = std::max(maxVal, it);
}
setNextFrameNumber(maxVal + 1);
setNextFrameNumber(maxVal + 1, pos);
}
} break;
default:
@ -914,7 +926,7 @@ void Detector::setNextFrameNumber(uint64_t value, Positions pos) {
}
void Detector::sendSoftwareTrigger(const bool block, Positions pos) {
pimpl->Parallel(&Module::sendSoftwareTrigger, pos, block);
pimpl->sendSoftwareTrigger(block, pos);
}
Result<defs::scanParameters> Detector::getScan(Positions pos) const {
@ -951,18 +963,23 @@ void Detector::setNumberofUDPInterfaces(int n, Positions pos) {
}
void Detector::setNumberofUDPInterfaces_(int n, Positions pos) {
if (!size()) {
throw RuntimeError("No modules added.");
}
bool previouslyClientStreaming = pimpl->getDataStreamingToClient();
int clientStartingPort = getClientZmqPort({0}).squash(0);
bool useReceiver = getUseReceiverFlag().squash(false);
bool previouslyReceiverStreaming = false;
int startingPort = 0;
int rxStartingPort = 0;
if (useReceiver) {
previouslyReceiverStreaming = getRxZmqDataStream(pos).squash(true);
startingPort = getRxZmqPort({0}).squash(0);
rxStartingPort = getRxZmqPort({0}).squash(0);
}
pimpl->Parallel(&Module::setNumberofUDPInterfaces, pos, n);
// ensure receiver zmq socket ports are multiplied by 2 (2 interfaces)
if (getUseReceiverFlag().squash(false) && size()) {
setRxZmqPort(startingPort, -1);
setClientZmqPort(clientStartingPort, -1);
if (getUseReceiverFlag().squash(false)) {
setRxZmqPort(rxStartingPort, -1);
}
// redo the zmq sockets if enabled
if (previouslyClientStreaming) {
@ -1082,12 +1099,13 @@ Result<int> Detector::getDestinationUDPPort(Positions pos) const {
void Detector::setDestinationUDPPort(int port, int module_id) {
if (module_id == -1) {
std::vector<int> port_list = getPortNumbers(port);
std::vector<int> port_list = getValidPortNumbers(port);
for (int idet = 0; idet < size(); ++idet) {
pimpl->Parallel(&Module::setDestinationUDPPort, {idet},
port_list[idet]);
}
} else {
validatePortNumber(port);
pimpl->Parallel(&Module::setDestinationUDPPort, {module_id}, port);
}
}
@ -1098,12 +1116,13 @@ Result<int> Detector::getDestinationUDPPort2(Positions pos) const {
void Detector::setDestinationUDPPort2(int port, int module_id) {
if (module_id == -1) {
std::vector<int> port_list = getPortNumbers(port);
std::vector<int> port_list = getValidPortNumbers(port);
for (int idet = 0; idet < size(); ++idet) {
pimpl->Parallel(&Module::setDestinationUDPPort2, {idet},
port_list[idet]);
}
} else {
validatePortNumber(port);
pimpl->Parallel(&Module::setDestinationUDPPort2, {module_id}, port);
}
}
@ -1215,9 +1234,11 @@ void Detector::setRxPort(int port, int module_id) {
it = port++;
}
for (int idet = 0; idet < size(); ++idet) {
validatePortNumber(port_list[idet]);
pimpl->Parallel(&Module::setReceiverPort, {idet}, port_list[idet]);
}
} else {
validatePortNumber(port);
pimpl->Parallel(&Module::setReceiverPort, {module_id}, port);
}
}
@ -1415,12 +1436,13 @@ void Detector::setRxZmqPort(int port, int module_id) {
bool previouslyReceiverStreaming =
getRxZmqDataStream(std::vector<int>{module_id}).squash(false);
if (module_id == -1) {
std::vector<int> port_list = getPortNumbers(port);
std::vector<int> port_list = getValidPortNumbers(port);
for (int idet = 0; idet < size(); ++idet) {
pimpl->Parallel(&Module::setReceiverStreamingPort, {idet},
port_list[idet]);
}
} else {
validatePortNumber(port);
pimpl->Parallel(&Module::setReceiverStreamingPort, {module_id}, port);
}
if (previouslyReceiverStreaming) {
@ -1449,12 +1471,13 @@ Result<int> Detector::getClientZmqPort(Positions pos) const {
void Detector::setClientZmqPort(int port, int module_id) {
bool previouslyClientStreaming = pimpl->getDataStreamingToClient();
if (module_id == -1) {
std::vector<int> port_list = getPortNumbers(port);
std::vector<int> port_list = getValidPortNumbers(port);
for (int idet = 0; idet < size(); ++idet) {
pimpl->Parallel(&Module::setClientStreamingPort, {idet},
port_list[idet]);
}
} else {
validatePortNumber(port);
pimpl->Parallel(&Module::setClientStreamingPort, {module_id}, port);
}
if (previouslyClientStreaming) {
@ -2458,6 +2481,7 @@ Result<int> Detector::getControlPort(Positions pos) const {
}
void Detector::setControlPort(int value, Positions pos) {
validatePortNumber(value);
pimpl->Parallel(&Module::setControlPort, pos, value);
}
@ -2466,6 +2490,7 @@ Result<int> Detector::getStopPort(Positions pos) const {
}
void Detector::setStopPort(int value, Positions pos) {
validatePortNumber(value);
pimpl->Parallel(&Module::setStopPort, pos, value);
}
@ -2500,13 +2525,17 @@ Result<ns> Detector::getMeasurementTime(Positions pos) const {
std::string Detector::getUserDetails() const { return pimpl->getUserDetails(); }
std::vector<int> Detector::getPortNumbers(int start_port) {
std::vector<int> Detector::getValidPortNumbers(int start_port) {
int num_sockets_per_detector = getNumberofUDPInterfaces({}).tsquash(
"Number of UDP Interfaces is not consistent among modules");
std::vector<int> res;
res.reserve(size());
for (int idet = 0; idet < size(); ++idet) {
res.push_back(start_port + (idet * num_sockets_per_detector));
int port = start_port + (idet * num_sockets_per_detector);
for (int i = 0; i != num_sockets_per_detector; ++i) {
validatePortNumber(port + i);
}
res.push_back(port);
}
return res;
}

View File

@ -288,6 +288,7 @@ void DetectorImpl::addModule(const std::string &hostname) {
if (res.size() > 1) {
host = res[0];
port = StringTo<int>(res[1]);
validatePortNumber(port);
}
if (host != "localhost") {
@ -769,7 +770,7 @@ void DetectorImpl::readFrameFromReceiver() {
int nDetActualPixelsY = nDetPixelsY;
if (gapPixels) {
int n = InsertGapPixels(multiframe.get(), multigappixels,
int n = insertGapPixels(multiframe.get(), multigappixels,
quadEnable, dynamicRange,
nDetActualPixelsX, nDetActualPixelsY);
callbackImage = multigappixels;
@ -808,7 +809,7 @@ void DetectorImpl::readFrameFromReceiver() {
delete[] multigappixels;
}
int DetectorImpl::InsertGapPixels(char *image, char *&gpImage, bool quadEnable,
int DetectorImpl::insertGapPixels(char *image, char *&gpImage, bool quadEnable,
int dr, int &nPixelsx, int &nPixelsy) {
LOG(logDEBUG) << "Insert Gap pixels:"
@ -1233,10 +1234,26 @@ int DetectorImpl::acquire() {
dataProcessingThread.join();
if (acquisition_finished != nullptr) {
int status = Parallel(&Module::getRunStatus, {}).squash(ERROR);
// status
runStatus status = IDLE;
auto statusList = Parallel(&Module::getRunStatus, {});
status = statusList.squash(ERROR);
// difference, but none error
if (status == ERROR && (!statusList.any(ERROR))) {
// handle jf sync issue (master idle, slaves stopped)
if (statusList.contains_only(IDLE, STOPPED)) {
status = STOPPED;
} else
status = statusList.squash(RUNNING);
}
// progress
auto a = Parallel(&Module::getReceiverProgress, {});
double progress = (*std::max_element(a.begin(), a.end()));
acquisition_finished(progress, status, acqFinished_p);
// callback
acquisition_finished(progress, static_cast<int>(status),
acqFinished_p);
}
clock_gettime(CLOCK_REALTIME, &end);
@ -1256,43 +1273,104 @@ int DetectorImpl::acquire() {
return OK;
}
void DetectorImpl::startAcquisition(bool blocking, std::vector<int> positions) {
// handle Mythen3 synchronization
if (shm()->detType == defs::MYTHEN3 && size() > 1) {
std::vector<int> master;
std::vector<int> slaves;
if (positions.empty() ||
(positions.size() == 1 && positions[0] == -1)) {
positions.resize(modules.size());
std::iota(begin(positions), end(positions), 0);
}
// could be all slaves in positions
slaves.reserve(positions.size());
auto is_master = Parallel(&Module::isMaster, positions);
for (size_t i : positions) {
if (is_master[i])
master.push_back(i);
else
slaves.push_back(i);
bool DetectorImpl::handleSynchronization(Positions pos) {
bool handleSync = false;
// multi module m3 or multi module sync enabled jungfrau
if (size() > 1) {
switch (shm()->detType) {
case defs::MYTHEN3:
case defs::GOTTHARD2:
case defs::GOTTHARD:
handleSync = true;
break;
case defs::JUNGFRAU:
if (Parallel(&Module::getSynchronizationFromStopServer, pos)
.tsquash("Inconsistent synchronization among modules")) {
handleSync = true;
}
break;
default:
break;
}
}
return handleSync;
}
void DetectorImpl::getMasterSlaveList(std::vector<int> positions,
std::vector<int> &masters,
std::vector<int> &slaves) {
// expand positions list
if (positions.empty() || (positions.size() == 1 && positions[0] == -1)) {
positions.resize(modules.size());
std::iota(begin(positions), end(positions), 0);
}
// could be all slaves in positions
slaves.reserve(positions.size());
auto is_master = Parallel(&Module::isMaster, positions);
for (size_t i : positions) {
if (is_master[i])
masters.push_back(i);
else
slaves.push_back(i);
}
}
void DetectorImpl::startAcquisition(const bool blocking, Positions pos) {
// slaves first
if (handleSynchronization(pos)) {
std::vector<int> masters;
std::vector<int> slaves;
getMasterSlaveList(pos, masters, slaves);
if (!slaves.empty()) {
Parallel(&Module::startAcquisition, slaves);
}
if (!master.empty()) {
if (blocking) {
Parallel(&Module::startAndReadAll, master);
} else {
Parallel(&Module::startAcquisition, master);
}
}
} else {
if (blocking) {
Parallel(&Module::startAndReadAll, positions);
} else {
Parallel(&Module::startAcquisition, positions);
if (!masters.empty()) {
Parallel((blocking ? &Module::startAndReadAll
: &Module::startAcquisition),
masters);
}
}
// all in parallel
else {
Parallel(
(blocking ? &Module::startAndReadAll : &Module::startAcquisition),
pos);
}
}
void DetectorImpl::sendSoftwareTrigger(const bool block, Positions pos) {
// slaves first
if (handleSynchronization(pos)) {
std::vector<int> masters;
std::vector<int> slaves;
getMasterSlaveList(pos, masters, slaves);
if (!slaves.empty())
Parallel(&Module::sendSoftwareTrigger, slaves, false);
if (!masters.empty())
Parallel(&Module::sendSoftwareTrigger, masters, block);
}
// all in parallel
else {
Parallel(&Module::sendSoftwareTrigger, pos, block);
}
}
void DetectorImpl::stopDetector(Positions pos) {
// masters first
if (handleSynchronization(pos)) {
std::vector<int> masters;
std::vector<int> slaves;
getMasterSlaveList(pos, masters, slaves);
if (!masters.empty())
Parallel(&Module::stopAcquisition, masters);
if (!slaves.empty())
Parallel(&Module::stopAcquisition, slaves);
}
// all in parallel
else {
Parallel(&Module::stopAcquisition, pos);
}
}
void DetectorImpl::printProgress(double progress) {
@ -1324,7 +1402,7 @@ void DetectorImpl::processData(bool receiver) {
if (fgetc(stdin) == 'q') {
LOG(logINFO)
<< "Caught the command to stop acquisition";
Parallel(&Module::stopAcquisition, {});
stopDetector({});
}
}
// get and print progress
@ -1397,7 +1475,8 @@ std::vector<char> DetectorImpl::readProgrammingFile(const std::string &fname) {
default:
throw RuntimeError(
"Unknown detector type. Did the 'hostname' command execute "
"successfully? Or use update mode in the detector server side.");
"successfully? Or use update mode in the detector server "
"side.");
}
LOG(logINFO) << "This can take awhile. Please be patient.";
@ -1425,10 +1504,9 @@ std::vector<char> DetectorImpl::readProgrammingFile(const std::string &fname) {
int dst = mkstemp(destfname); // create temporary file and open it in r/w
if (dst == -1) {
fclose(src);
throw RuntimeError(
std::string(
"Could not create destination file in /tmp for programming: ") +
destfname);
throw RuntimeError(std::string("Could not create destination file "
"in /tmp for programming: ") +
destfname);
}
// convert src to dst rawbin
@ -1480,8 +1558,8 @@ std::vector<char> DetectorImpl::readProgrammingFile(const std::string &fname) {
}
// validate pof: read less than footer offset
if (isPof && dstFilePos < pofFooterOfst) {
throw RuntimeError(
"Could not convert programming file. EOF before end of flash");
throw RuntimeError("Could not convert programming file. EOF "
"before end of flash");
}
}
if (fclose(src) != 0) {

View File

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

View File

@ -73,8 +73,8 @@ void Module::setHostname(const std::string &hostname,
auto client = DetectorSocket(shm()->hostname, shm()->controlPort);
client.close();
try {
initialDetectorServerChecks();
checkDetectorVersionCompatibility();
initialDetectorServerChecks();
LOG(logINFO) << "Module Version Compatibility - Success";
} catch (const RuntimeError &e) {
if (!initialChecks) {
@ -93,9 +93,28 @@ int64_t Module::getFirmwareVersion() const {
}
std::string Module::getControlServerLongVersion() const {
char retval[MAX_STR_LENGTH]{};
sendToDetector(F_GET_SERVER_VERSION, nullptr, retval);
return retval;
try {
char retval[MAX_STR_LENGTH]{};
sendToDetector(F_GET_SERVER_VERSION, nullptr, retval);
return retval;
}
// throw with old server version (sends 8 bytes)
catch (RuntimeError &e) {
std::string emsg = std::string(e.what());
if (emsg.find(F_GET_SERVER_VERSION) && emsg.find("8 bytes")) {
throwDeprecatedServerVersion();
}
throw;
}
}
void Module::throwDeprecatedServerVersion() const {
uint64_t res = sendToDetectorStop<int64_t>(F_GET_SERVER_VERSION);
std::cout << std::endl;
std::ostringstream os;
os << "Detector Server (Control) version (0x" << std::hex << res
<< ") is incompatible with this client. Please update detector server!";
throw RuntimeError(os.str());
}
std::string Module::getStopServerLongVersion() const {
@ -519,8 +538,15 @@ bool Module::getSynchronization() const {
return sendToDetector<int>(F_GET_SYNCHRONIZATION);
}
bool Module::getSynchronizationFromStopServer() const {
return sendToDetectorStop<int>(F_GET_SYNCHRONIZATION);
}
void Module::setSynchronization(const bool value) {
sendToDetector(F_SET_SYNCHRONIZATION, static_cast<int>(value), nullptr);
// to deal with virtual servers as well
// (get sync from stop server during blocking acquisition)
sendToDetectorStop(F_SET_SYNCHRONIZATION, static_cast<int>(value), nullptr);
}
std::vector<int> Module::getBadChannels() const {
@ -1324,7 +1350,9 @@ void Module::setReceiverHostname(const std::string &receiverIP,
auto res = split(host, ':');
if (res.size() > 1) {
host = res[0];
shm()->rxTCPPort = std::stoi(res[1]);
int port = StringTo<int>(res[1]);
validatePortNumber(port);
shm()->rxTCPPort = port;
}
strcpy_safe(shm()->rxHostname, host.c_str());
shm()->useReceiverFlag = true;
@ -3845,8 +3873,8 @@ void Module::sendProgram(bool blackfin, std::vector<char> buffer,
void Module::simulatingActivityinDetector(const std::string &functionType,
const int timeRequired) {
LOG(logINFO) << "(Simulating) " << functionType << " for module "
<< moduleIndex << " (" << shm()->hostname << ")";
LOG(logINFO) << functionType << " for module " << moduleIndex << " ("
<< shm()->hostname << ")";
printf("%d%%\r", 0);
std::cout << std::flush;
const int ERASE_TIME = timeRequired;

View File

@ -92,6 +92,7 @@ class Module : public virtual slsDetectorDefs {
int64_t getFirmwareVersion() const;
std::string getControlServerLongVersion() const;
std::string getStopServerLongVersion() const;
void throwDeprecatedServerVersion() const;
std::string getDetectorServerVersion() const;
std::string getHardwareVersion() const;
std::string getKernelVersion() const;
@ -128,6 +129,7 @@ class Module : public virtual slsDetectorDefs {
bool isMaster() const;
void setMaster(const bool master);
bool getSynchronization() const;
bool getSynchronizationFromStopServer() const;
void setSynchronization(const bool value);
std::vector<int> getBadChannels() const;
void setBadChannels(std::vector<int> list);

View File

@ -11,6 +11,31 @@ namespace sls {
using test::GET;
using test::PUT;
void test_valid_port(const std::string &command,
const std::vector<std::string> &arguments, int detector_id,
int action, int port_number) {
Detector det;
CmdProxy proxy(&det);
std::string string_port_number = std::to_string(port_number);
REQUIRE_THROWS_WITH(proxy.Call(command, arguments, detector_id, action),
"Invalid port number " + string_port_number +
". It must be in range 1 - 65535");
}
void test_valid_port(const std::string &command,
const std::vector<std::string> &arguments, int detector_id,
int action) {
std::vector<std::string> arg(arguments);
arg.push_back("0");
int test_values[2] = {77797, -1};
for (int i = 0; i != 2; ++i) {
int port_number = test_values[i];
arg[arg.size() - 1] = std::to_string(port_number);
test_valid_port(command, arg, detector_id, action, port_number);
}
}
void test_dac(defs::dacIndex index, const std::string &dacname, int dacvalue) {
Detector det;
CmdProxy proxy(&det);

View File

@ -5,6 +5,14 @@
namespace sls {
void test_valid_port(const std::string &command,
const std::vector<std::string> &arguments, int detector_id,
int action, int port_number);
void test_valid_port(const std::string &command,
const std::vector<std::string> &arguments, int detector_id,
int action);
void test_dac(slsDetectorDefs::dacIndex index, const std::string &dacname,
int dacvalue);
void test_onchip_dac(slsDetectorDefs::dacIndex index,

View File

@ -689,10 +689,11 @@ TEST_CASE("confadc", "[.cmd]") {
auto det_type = det.getDetectorType().squash();
if (det_type == defs::GOTTHARD2) {
int ndet = det.size();
int nchip = 10;
int nadc = 32;
int prev_val[ndet][nchip][nadc];
const int ndet = det.size();
const int nchip = 10;
const int nadc = 32;
std::vector<std::vector<std::vector<int>>> prev_val(
ndet, std::vector<std::vector<int>>(nchip, std::vector<int>(nadc)));
for (int i = 0; i != ndet; ++i) {
for (int j = 0; j != nchip; ++j) {
for (int k = 0; k != nadc; ++k) {

View File

@ -523,11 +523,61 @@ TEST_CASE("sync", "[.cmd]") {
proxy.Call("sync", {"1"}, -1, PUT, oss);
REQUIRE(oss.str() == "sync 1\n");
}
// setting to master or slave when synced
{
// get previous master
int prevMaster = 0;
auto previous = det.getMaster();
for (int i = 0; i != det.size(); ++i) {
if (previous[i] == 1) {
prevMaster = i;
break;
}
}
proxy.Call("master", {"1"}, 0, PUT);
proxy.Call("master", {"0"}, 0, PUT);
std::ostringstream oss;
proxy.Call("status", {}, -1, GET, oss);
REQUIRE(oss.str() != "status running\n");
// set all to slaves, and then master
for (int i = 0; i != det.size(); ++i) {
det.setMaster(0, {i});
}
det.setMaster(1, prevMaster);
}
{
std::ostringstream oss;
proxy.Call("sync", {}, -1, GET, oss);
REQUIRE(oss.str() == "sync 1\n");
}
// setting sync when running
{
auto prev_timing =
det.getTimingMode().tsquash("inconsistent timing mode in test");
auto prev_frames =
det.getNumberOfFrames().tsquash("inconsistent #frames in test");
auto prev_exptime =
det.getExptime().tsquash("inconsistent exptime in test");
auto prev_period =
det.getPeriod().tsquash("inconsistent period in test");
det.setTimingMode(defs::AUTO_TIMING);
det.setNumberOfFrames(10000);
det.setExptime(std::chrono::microseconds(200));
det.setPeriod(std::chrono::milliseconds(1000));
det.setSynchronization(1);
det.startDetector();
REQUIRE_THROWS(proxy.Call("sync", {"0"}, -1, PUT));
{
std::ostringstream oss;
proxy.Call("sync", {}, -1, GET, oss);
REQUIRE(oss.str() == "sync 1\n");
}
det.stopDetector();
det.setTimingMode(prev_timing);
det.setNumberOfFrames(prev_frames);
det.setExptime(prev_exptime);
det.setPeriod(prev_period);
}
det.setSynchronization(prev_val);
} else {
REQUIRE_THROWS(proxy.Call("sync", {}, -1, GET));

View File

@ -5,6 +5,7 @@
#include "sls/Detector.h"
#include "sls/Version.h"
#include "sls/sls_detector_defs.h"
#include "test-CmdProxy-global.h"
#include <sstream>
#include "sls/versionAPI.h"
@ -237,6 +238,22 @@ TEST_CASE("rx_tcpport", "[.cmd][.rx]") {
proxy.Call("rx_tcpport", {}, i, GET, oss);
REQUIRE(oss.str() == "rx_tcpport " + std::to_string(port + i) + '\n');
}
test_valid_port("rx_tcpport", {}, -1, PUT);
test_valid_port("rx_tcpport", {}, 0, PUT);
// should fail for the second module
if (det.size() > 1) {
test_valid_port("rx_tcpport", {"65535"}, -1, PUT, 65536);
auto rxHostname = det.getRxHostname().squash("none");
if (rxHostname != "none") {
std::ostringstream oss;
for (int i = 0; i != det.size(); ++i) {
oss << rxHostname << ":" << 65536 + i << "+";
}
test_valid_port("rx_hostname", {oss.str()}, -1, PUT, 65536);
}
}
for (int i = 0; i != det.size(); ++i) {
det.setRxPort(prev_val[i], i);
}
@ -828,6 +845,12 @@ TEST_CASE("rx_zmqport", "[.cmd][.rx]") {
std::to_string(port + i * socketsperdetector) +
'\n');
}
test_valid_port("rx_zmqport", {}, -1, PUT);
test_valid_port("rx_zmqport", {}, 0, PUT);
// should fail for the second module
if (det.size() > 1) {
test_valid_port("rx_zmqport", {"65535"}, -1, PUT, 65536);
}
for (int i = 0; i != det.size(); ++i) {
det.setRxZmqPort(prev_val_zmqport[i], i);
}

View File

@ -5,6 +5,7 @@
#include "sls/Detector.h"
#include "sls/file_utils.h"
#include "sls/sls_detector_defs.h"
#include "test-CmdProxy-global.h"
#include <chrono>
#include <sstream>
@ -76,7 +77,13 @@ TEST_CASE("hostname", "[.cmd]") {
REQUIRE_NOTHROW(proxy.Call("hostname", {}, -1, GET));
}
// virtual: not testing
TEST_CASE("virtual", "[.cmd]") {
Detector det;
CmdProxy proxy(&det);
REQUIRE_THROWS(proxy.Call("virtual", {}, -1, GET));
test_valid_port("virtual", {"1"}, -1, PUT);
test_valid_port("virtual", {"3", "65534"}, -1, PUT, 65536);
}
TEST_CASE("versions", "[.cmd]") {
Detector det;
@ -1221,10 +1228,10 @@ TEST_CASE("dbitphase", "[.cmd]") {
}
{
std::ostringstream oss1, oss2;
proxy.Call("dbitphase", {"20", "deg"}, -1, PUT, oss1);
REQUIRE(oss1.str() == "dbitphase 20 deg\n");
proxy.Call("dbitphase", {"23", "deg"}, -1, PUT, oss1);
REQUIRE(oss1.str() == "dbitphase 23 deg\n");
proxy.Call("dbitphase", {"deg"}, -1, GET, oss2);
REQUIRE(oss2.str() == "dbitphase 20 deg\n");
REQUIRE(oss2.str() == "dbitphase 23 deg\n");
}
for (int i = 0; i != det.size(); ++i) {
det.setDBITPhase(prev_val[i], {i});
@ -2618,6 +2625,13 @@ TEST_CASE("udp_dstport", "[.cmd]") {
proxy.Call("udp_dstport", {"50084"}, -1, PUT, oss);
REQUIRE(oss.str() == "udp_dstport 50084\n");
}
test_valid_port("udp_dstport", {}, -1, PUT);
test_valid_port("udp_dstport", {}, 0, PUT);
// should fail for the second module
if (det.size() > 1) {
test_valid_port("udp_dstport", {"65535"}, -1, PUT, 65536);
}
for (int i = 0; i != det.size(); ++i) {
det.setDestinationUDPPort(prev_val[i], {i});
}
@ -2702,8 +2716,18 @@ TEST_CASE("udp_dstport2", "[.cmd]") {
proxy.Call("udp_dstport2", {"50084"}, -1, PUT, oss);
REQUIRE(oss.str() == "udp_dstport2 50084\n");
}
test_valid_port("udp_dstport2", {}, -1, PUT);
test_valid_port("udp_dstport2", {}, 0, PUT);
// should fail for the second module
if (det.size() > 1) {
test_valid_port("udp_dstport2", {"65535"}, -1, PUT, 65536);
}
for (int i = 0; i != det.size(); ++i) {
det.setDestinationUDPPort2(prev_val[i], {i});
if (prev_val[i] != 0) {
det.setDestinationUDPPort2(prev_val[i], {i});
}
}
} else {
REQUIRE_THROWS(proxy.Call("udp_dstport2", {}, -1, GET));
@ -2922,6 +2946,13 @@ TEST_CASE("zmqport", "[.cmd]") {
std::to_string(port + i * socketsperdetector) +
'\n');
}
test_valid_port("zmqport", {}, -1, PUT);
test_valid_port("zmqport", {}, 0, PUT);
// should fail for the second module
if (det.size() > 1) {
test_valid_port("zmqport", {"65535"}, -1, PUT, 65536);
}
if (det_type == defs::JUNGFRAU) {
det.setNumberofUDPInterfaces(prev);
}
@ -3266,6 +3297,13 @@ TEST_CASE("port", "[.cmd]") {
proxy.Call("port", {}, 0, GET, oss);
REQUIRE(oss.str() == "port 1942\n");
}
test_valid_port("port", {}, -1, PUT);
test_valid_port("port", {}, 0, PUT);
// should fail for the second module
if (det.size() > 1) {
test_valid_port("port", {"65536"}, -1, PUT, 65536);
}
det.setControlPort(prev_val, {0});
}
@ -3283,6 +3321,12 @@ TEST_CASE("stopport", "[.cmd]") {
proxy.Call("stopport", {}, 0, GET, oss);
REQUIRE(oss.str() == "stopport 1942\n");
}
test_valid_port("stopport", {}, -1, PUT);
test_valid_port("stopport", {}, 0, PUT);
// should fail for the second module
if (det.size() > 1) {
test_valid_port("stopport", {"65536"}, -1, PUT, 65536);
}
det.setStopPort(prev_val, {0});
}
@ -3313,7 +3357,7 @@ TEST_CASE("lock", "[.cmd]") {
TEST_CASE("execcommand", "[.cmd]") {
Detector det;
CmdProxy proxy(&det);
REQUIRE_NOTHROW(proxy.Call("execcommand", {"ls"}, -1, PUT));
REQUIRE_NOTHROW(proxy.Call("execcommand", {"ls *.txt"}, -1, PUT));
}
TEST_CASE("framecounter", "[.cmd]") {

View File

@ -196,4 +196,24 @@ TEST_CASE("String conversions") {
"[{one: 1}, {one: 1, three: 3, two: 2}, {one: 1}]");
}
TEST_CASE("Any element is equal") {
Result<int> r{1, 2, 3, 4, 5};
REQUIRE(r.any(3));
REQUIRE_FALSE(r.any(9));
}
TEST_CASE("Result contains only the specified elements") {
Result<int> r{1, 1, 1};
REQUIRE(r.contains_only(1));
REQUIRE(r.contains_only(1, 1));
}
TEST_CASE("Only with multiple values") {
Result<int> r{1, 1, 2, 1, 2, 1, 1};
REQUIRE_FALSE(r.contains_only(1));
REQUIRE_FALSE(r.contains_only(2));
REQUIRE(r.contains_only(1, 2));
REQUIRE(r.contains_only(2, 1));
}
} // namespace sls

View File

@ -5,6 +5,7 @@
#include <chrono>
#include <signal.h>
#include <sys/wait.h>
#include <thread>
#include <unistd.h>
@ -16,6 +17,8 @@ namespace sls {
#define gettid() syscall(SYS_gettid)
#endif
void func(int signum) { wait(NULL); }
Arping::Arping() {}
Arping::~Arping() {
@ -44,10 +47,11 @@ pid_t Arping::GetProcessId() const { return childPid; }
bool Arping::IsRunning() const { return runningFlag; }
void Arping::StartProcess() {
TestCommands();
// to prevent zombies from child processes being killed
signal(SIGCHLD, SIG_IGN);
signal(SIGCHLD, func);
// test once to throw exception if arping failed
TestForErrors();
// Needs to be a fork and udp socket deleted after Listening threads
// done running to prevent udp socket cannot bind because of popen
@ -90,7 +94,7 @@ void Arping::ProcessExecution() {
}
}
void Arping::TestCommands() {
void Arping::TestForErrors() {
// atleast one interface must be set up
if (commands[0].empty()) {
throw RuntimeError(
@ -116,7 +120,8 @@ std::string Arping::ExecuteCommands() {
FILE *sysFile = popen(cmd.c_str(), "r");
if (sysFile == NULL) {
std::ostringstream os;
os << "Could not Arping [" << cmd << " ] : Popen fail";
os << "Could not Arping (" << cmd << " ) : Popen fail ("
<< strerror(errno) << ')';
return os.str();
}
@ -128,7 +133,7 @@ std::string Arping::ExecuteCommands() {
// check exit status of command
if (pclose(sysFile)) {
std::ostringstream os;
os << "Could not arping[" << cmd << "] : " << output;
os << "Could not arping (" << cmd << ") : " << strerror(errno);
return os.str();
} else {
LOG(logDEBUG) << output;

View File

@ -28,7 +28,7 @@ class Arping {
void StopProcess();
private:
void TestCommands();
void TestForErrors();
std::string ExecuteCommands();
void ProcessExecution();

View File

@ -45,6 +45,7 @@ ClientInterface::ClientInterface(int portNumber)
: detType(GOTTHARD),
portNumber(portNumber > 0 ? portNumber : DEFAULT_TCP_RX_PORTNO),
server(portNumber) {
validatePortNumber(portNumber);
functionTable();
parentThreadId = gettid();
tcpThread =

View File

@ -56,6 +56,8 @@ void DataStreamer::SetAdditionalJsonHeader(
isAdditionalJsonUpdated = true;
}
void DataStreamer::SetReceiverROI(ROI roi) { receiverRoi = roi; }
void DataStreamer::ResetParametersforNewAcquisition(const std::string &fname) {
StopRunning();
startedFlag = false;
@ -249,6 +251,7 @@ int DataStreamer::SendDataHeader(sls_detector_header header, uint32_t size,
isAdditionalJsonUpdated = false;
}
zHeader.addJsonHeader = localAdditionalJsonHeader;
zHeader.rx_roi = receiverRoi.getIntArray();
return zmqSocket->SendHeader(index, zHeader);
}

View File

@ -38,6 +38,7 @@ class DataStreamer : private virtual slsDetectorDefs, public ThreadObject {
void SetNumberofTotalFrames(uint64_t value);
void
SetAdditionalJsonHeader(const std::map<std::string, std::string> &json);
void SetReceiverROI(ROI roi);
void ResetParametersforNewAcquisition(const std::string &fname);
/**
@ -92,6 +93,7 @@ class DataStreamer : private virtual slsDetectorDefs, public ThreadObject {
uint64_t fileIndex{0};
bool flipRows{false};
std::map<std::string, std::string> additionalJsonHeader;
ROI receiverRoi{};
/** Used by streamer thread to update local copy (reduce number of locks
* during streaming) */

View File

@ -14,14 +14,14 @@ HDF5DataFile::HDF5DataFile(int index, std::mutex *hdf5Lib)
"frame number",
"exp length or sub exposure time",
"packets caught",
"bunch id",
"detector specific 1",
"timestamp",
"mod id",
"row",
"column",
"reserved",
"debug",
"round robin number",
"detector specific 2",
"detector specific 3",
"detector specific 4",
"detector type",
"detector header version",
"packets caught bit mask",
@ -317,7 +317,7 @@ void HDF5DataFile::WriteParameterDatasets(const uint64_t currentFrameNumber,
dataSetPara[2]->write(&header.packetNumber, parameterDataTypes[2],
memspace, *dataSpacePara);
i = 3;
dataSetPara[3]->write(&header.bunchId, parameterDataTypes[3], memspace,
dataSetPara[3]->write(&header.detSpec1, parameterDataTypes[3], memspace,
*dataSpacePara);
i = 4;
dataSetPara[4]->write(&header.timestamp, parameterDataTypes[4],
@ -332,13 +332,13 @@ void HDF5DataFile::WriteParameterDatasets(const uint64_t currentFrameNumber,
dataSetPara[7]->write(&header.column, parameterDataTypes[7], memspace,
*dataSpacePara);
i = 8;
dataSetPara[8]->write(&header.reserved, parameterDataTypes[8], memspace,
dataSetPara[8]->write(&header.detSpec2, parameterDataTypes[8], memspace,
*dataSpacePara);
i = 9;
dataSetPara[9]->write(&header.debug, parameterDataTypes[9], memspace,
dataSetPara[9]->write(&header.detSpec3, parameterDataTypes[9], memspace,
*dataSpacePara);
i = 10;
dataSetPara[10]->write(&header.roundRNumber, parameterDataTypes[10],
dataSetPara[10]->write(&header.detSpec4, parameterDataTypes[10],
memspace, *dataSpacePara);
i = 11;
dataSetPara[11]->write(&header.detType, parameterDataTypes[11],

View File

@ -216,6 +216,8 @@ void Implementation::SetupDataStreamer(int i) {
dataStreamer[i]->SetNumberofPorts(numPorts);
dataStreamer[i]->SetQuadEnable(quadEnable);
dataStreamer[i]->SetNumberofTotalFrames(numberOfTotalFrames);
dataStreamer[i]->SetReceiverROI(
portRois[i].completeRoi() ? GetMaxROIPerPort() : portRois[i]);
}
slsDetectorDefs::xy Implementation::getDetectorSize() const {
@ -231,6 +233,11 @@ const slsDetectorDefs::xy Implementation::GetPortGeometry() const {
return portGeometry;
}
const slsDetectorDefs::ROI Implementation::GetMaxROIPerPort() const {
return slsDetectorDefs::ROI{0, (int)generalData->nPixelsX - 1, 0,
(int)generalData->nPixelsY - 1};
}
void Implementation::setDetectorSize(const slsDetectorDefs::xy size) {
xy portGeometry = GetPortGeometry();
@ -458,6 +465,10 @@ void Implementation::setReceiverROI(const slsDetectorDefs::ROI arg) {
listener[i]->SetNoRoi(portRois[i].noRoi());
for (size_t i = 0; i != dataProcessor.size(); ++i)
dataProcessor[i]->SetReceiverROI(portRois[i]);
for (size_t i = 0; i != dataStreamer.size(); ++i) {
dataStreamer[i]->SetReceiverROI(
portRois[i].completeRoi() ? GetMaxROIPerPort() : portRois[i]);
}
LOG(logINFO) << "receiver roi: " << ToString(receiverRoi);
if (generalData->numUDPInterfaces == 2 &&
generalData->detType != slsDetectorDefs::GOTTHARD2) {

View File

@ -282,6 +282,7 @@ class Implementation : private virtual slsDetectorDefs {
void SetupFifoStructure();
const xy GetPortGeometry() const;
const ROI GetMaxROIPerPort() const;
void ResetParametersforNewAcquisition();
void CreateUDPSockets();
void SetupWriter();

View File

@ -19,8 +19,8 @@ namespace sls {
// files
// versions
#define HDF5_WRITER_VERSION (6.5) // 1 decimal places
#define BINARY_WRITER_VERSION (7.1) // 1 decimal places
#define HDF5_WRITER_VERSION (6.6) // 1 decimal places
#define BINARY_WRITER_VERSION (7.2) // 1 decimal places
#define MAX_FRAMES_PER_FILE 20000
#define SHORT_MAX_FRAMES_PER_FILE 100000

View File

@ -103,4 +103,13 @@ template <typename T> struct is_vector : public std::false_type {};
template <typename T>
struct is_vector<std::vector<T>> : public std::true_type {};
template <class...> struct Conjunction : std::true_type {};
template <class B1> struct Conjunction<B1> : B1 {};
template <class B1, class... Bn>
struct Conjunction<B1, Bn...>
: std::conditional<bool(B1::value), Conjunction<Bn...>, B1>::type {};
template <typename T, typename... Ts>
using AllSame =
typename std::enable_if<Conjunction<std::is_same<T, Ts>...>::value>::type;
} // namespace sls

View File

@ -12,6 +12,7 @@
#include "sls/container_utils.h"
#include "sls/sls_detector_exceptions.h"
#include <array>
#include <map>
#include <memory>
@ -83,6 +84,8 @@ struct zmqHeader {
bool completeImage{false};
/** additional json header */
std::map<std::string, std::string> addJsonHeader;
/** (xmin, xmax, ymin, ymax) roi only in files written */
std::array<int, 4> rx_roi{};
};
class ZmqSocket {

View File

@ -2,6 +2,7 @@
// Copyright (C) 2021 Contributors to the SLS Detector Package
#pragma once
#include <array>
#include <cstdint>
#include <iostream>
#include <string>
@ -87,5 +88,5 @@ IpAddr HostnameToIp(const char *hostname);
std::string IpToInterfaceName(const std::string &ip);
MacAddr InterfaceNameToMac(const std::string &inf);
IpAddr InterfaceNameToIp(const std::string &ifn);
void validatePortNumber(int port);
} // namespace sls

View File

@ -46,7 +46,7 @@
#define MAX_UDP_DESTINATION 32
#define SLS_DETECTOR_HEADER_VERSION 0x2
#define SLS_DETECTOR_JSON_HEADER_VERSION 0x4
#define SLS_DETECTOR_JSON_HEADER_VERSION 0x5
// ctb/ moench 1g udp (read from fifo)
#define UDP_PACKET_DATA_BYTES (1344)

View File

@ -1,13 +1,13 @@
// SPDX-License-Identifier: LGPL-3.0-or-other
// Copyright (C) 2021 Contributors to the SLS Detector Package
/** API versions */
#define RELEASE "7.0.0"
#define APICTB "7.0.0 0x230222"
#define APIGOTTHARD "7.0.0 0x230222"
#define APIGOTTHARD2 "7.0.0 0x230222"
#define APIJUNGFRAU "7.0.0 0x230222"
#define APIMYTHEN3 "7.0.0 0x230222"
#define APIMOENCH "7.0.0 0x230222"
#define APIEIGER "7.0.0 0x230222"
#define APILIB "7.0.0 0x230223"
#define APIRECEIVER "7.0.0 0x230222"
#define RELEASE "7.0.3"
#define APILIB "7.0.3 0x231108"
#define APIRECEIVER "7.0.3 0x231108"
#define APICTB "7.0.3 0x231109"
#define APIGOTTHARD "7.0.3 0x231109"
#define APIGOTTHARD2 "7.0.3 0x231109"
#define APIJUNGFRAU "7.0.3 0x231109"
#define APIMYTHEN3 "7.0.3 0x231109"
#define APIMOENCH "7.0.3 0x231109"
#define APIEIGER "7.0.3 0x231109"

View File

@ -254,6 +254,8 @@ int ZmqSocket::SendHeader(int index, zmqHeader header) {
}
oss << " } ";
}
oss << ", \"rx_roi\":[" << header.rx_roi[0] << ", " << header.rx_roi[1]
<< ", " << header.rx_roi[2] << ", " << header.rx_roi[3] << "]";
oss << "}\n";
std::string message = oss.str();
int length = message.length();
@ -375,6 +377,11 @@ int ZmqSocket::ParseHeader(const int index, int length, char *buff,
}
}
const Value &a = document["rx_roi"].GetArray();
for (SizeType i = 0; i != a.Size(); ++i) {
zHeader.rx_roi[i] = a[i].GetInt();
}
return 1;
}

View File

@ -10,6 +10,7 @@
#include <cstring>
#include <ifaddrs.h>
#include <iomanip>
#include <limits>
#include <net/if.h>
#include <netdb.h>
#include <sstream>
@ -203,4 +204,13 @@ MacAddr InterfaceNameToMac(const std::string &inf) {
return MacAddr(mac);
}
void validatePortNumber(int port) {
if (0 >= port || port > std::numeric_limits<uint16_t>::max()) {
std::ostringstream oss;
oss << "Invalid port number " << port << ". It must be in range 1 - "
<< std::numeric_limits<uint16_t>::max();
throw RuntimeError(oss.str());
}
}
} // namespace sls