* roi structure expanded to have ymin and ymax

* compile with 'detector roi'

* wip

* wip, rx_roi, rx_clearroi

* wip rxroi

* rxroi wip

* wip rxroi

* merge fix

* wip

* rx_roi works, impl wip, test

* tests in, impl left

* wip, rxroi impl

* wip, rxroi impl

* wip

* setrx_Roi works, getrx_roi, wip

* rx_roi impl done

* wip, rxroi

* wip, getrx_roi rxr ports

* fix ports

* wip

* wip

* fix positions on server side

* wip

* numports wip

* wip

* jungfrau top inner interface row increment

* x, y detpos, wip

* removed eiger row indices flipping in gui (bottom flipping maintained)

* wip

* wip, jungfrau numinterfaces2

* jungfrau virtual works

* eiger, jungfrau, g2 virtual server works

* eiger positions fix, wip

* binaries in

* minor printout

* binaries in

* merge fix

* merge fix

* removing getposition

* setrxroi wip

* set upto port

* get messed, wip

* roi multi to module works, wip

* wip

* roi dont return -1

* added rxroi metadata in master file

* added rxroifromshm, not yet in detector

* rx roi in gui with box, also for gap pixels (gappixels for jungfrau mess)

* fix for segfault in gui with detaching roi box in gui

* wip

* m3 gui: slave timing modes should be discarded when squashing

* fixed m3 virtual data, and fixed counters in gui asthetics

* m3 roi works

* wip, g2

* wip

* handling g225um boards, and showing roi for gainplot as well

* udpate python functions

* fix for 1d and a2d roi written

* fixed actual roi written to file

* no virtual hdf5 when handling rx roi

* test

* minor

* binarie in
This commit is contained in:
Dhanya Thattil 2022-05-16 12:35:06 +02:00 committed by GitHub
parent 9808376207
commit fcc7f7aef8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
53 changed files with 1713 additions and 859 deletions

View File

@ -59,6 +59,7 @@ This document describes the differences between v7.0.0 and v6.x.x
- gotthard 25 um image reconstructed in gui and virtual hdf5 (firmware updated for slave to reverse channels) - gotthard 25 um image reconstructed in gui and virtual hdf5 (firmware updated for slave to reverse channels)
- master binary file in json format now - master binary file in json format now
- fixed bug introduced in 6.0.0: hdf5 files created 1 file per frame after the initial file which had maxframesperfile - fixed bug introduced in 6.0.0: hdf5 files created 1 file per frame after the initial file which had maxframesperfile
- rx_roi
- m3 polarity, interpolation (enables all counters when enabled), pump probe, analog pulsing, digital pulsing - m3 polarity, interpolation (enables all counters when enabled), pump probe, analog pulsing, digital pulsing
- updatedetectorserver - removes old server current binary pointing to for blackfin - updatedetectorserver - removes old server current binary pointing to for blackfin
- removing copydetectorserver using tftp - removing copydetectorserver using tftp
@ -69,6 +70,7 @@ This document describes the differences between v7.0.0 and v6.x.x
- fixed row column indexing (mainly for multi module Jungfrau 2 interfaces ) - fixed row column indexing (mainly for multi module Jungfrau 2 interfaces )
- eiger gui row indices not flipped anymore (fix in config) - eiger gui row indices not flipped anymore (fix in config)
- m3 (settings dac check disabled temporarily?) - m3 (settings dac check disabled temporarily?)
- m3 virtual server sends the right pacets now
- gap pixels in gui enabled by default - gap pixels in gui enabled by default
2. Resolved Issues 2. Resolved Issues

View File

@ -786,6 +786,15 @@ void init_det(py::module &m) {
.def("setRxArping", .def("setRxArping",
(void (Detector::*)(bool, sls::Positions)) & Detector::setRxArping, (void (Detector::*)(bool, sls::Positions)) & Detector::setRxArping,
py::arg(), py::arg() = Positions{}) py::arg(), py::arg() = Positions{})
.def("getIndividualRxROIs",
(Result<defs::ROI>(Detector::*)(sls::Positions) const) &
Detector::getIndividualRxROIs,
py::arg())
.def("getRxROI", (defs::ROI(Detector::*)() const) & Detector::getRxROI)
.def("setRxROI",
(void (Detector::*)(const defs::ROI)) & Detector::setRxROI,
py::arg())
.def("clearRxROI", (void (Detector::*)()) & Detector::clearRxROI)
.def("getFileFormat", .def("getFileFormat",
(Result<defs::fileFormat>(Detector::*)(sls::Positions) const) & (Result<defs::fileFormat>(Detector::*)(sls::Positions) const) &
Detector::getFileFormat, Detector::getFileFormat,
@ -1602,11 +1611,6 @@ void init_det(py::module &m) {
.def("rebootController", .def("rebootController",
(void (Detector::*)(sls::Positions)) & Detector::rebootController, (void (Detector::*)(sls::Positions)) & Detector::rebootController,
py::arg() = Positions{}) py::arg() = Positions{})
.def("updateFirmwareAndServer",
(void (Detector::*)(const std::string &, const std::string &,
const std::string &, sls::Positions)) &
Detector::updateFirmwareAndServer,
py::arg(), py::arg(), py::arg(), py::arg() = Positions{})
.def("updateFirmwareAndServer", .def("updateFirmwareAndServer",
(void (Detector::*)(const std::string &, const std::string &, (void (Detector::*)(const std::string &, const std::string &,
sls::Positions)) & sls::Positions)) &

View File

@ -20,7 +20,105 @@
<string>Form</string> <string>Form</string>
</property> </property>
<layout class="QGridLayout" name="gridLayout"> <layout class="QGridLayout" name="gridLayout">
<item row="2" column="0" colspan="4"> <item row="1" column="5">
<widget class="QLabel" name="lblRxRoiEnabled">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>120</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="palette">
<palette>
<active>
<colorrole role="WindowText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>0</red>
<green>0</green>
<blue>255</blue>
</color>
</brush>
</colorrole>
</active>
<inactive>
<colorrole role="WindowText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>0</red>
<green>0</green>
<blue>255</blue>
</color>
</brush>
</colorrole>
</inactive>
<disabled>
<colorrole role="WindowText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>139</red>
<green>142</green>
<blue>142</blue>
</color>
</brush>
</colorrole>
</disabled>
</palette>
</property>
<property name="text">
<string>Rx Roi Enabled</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="0" column="0" colspan="7">
<widget class="QGroupBox" name="boxPlot">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<family>Sans Serif</family>
<pointsize>10</pointsize>
</font>
</property>
<property name="title">
<string>Sample Plot</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="flat">
<bool>true</bool>
</property>
<layout class="QGridLayout" name="plotLayout">
<property name="margin">
<number>9</number>
</property>
<property name="spacing">
<number>0</number>
</property>
</layout>
</widget>
</item>
<item row="2" column="0" colspan="7">
<widget class="QWidget" name="widgetStatistics" native="true"> <widget class="QWidget" name="widgetStatistics" native="true">
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed"> <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
@ -212,104 +310,6 @@
</property> </property>
</spacer> </spacer>
</item> </item>
<item row="0" column="0" colspan="4">
<widget class="QGroupBox" name="boxPlot">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="font">
<font>
<family>Sans Serif</family>
<pointsize>10</pointsize>
</font>
</property>
<property name="title">
<string>Sample Plot</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="flat">
<bool>true</bool>
</property>
<layout class="QGridLayout" name="plotLayout">
<property name="margin">
<number>9</number>
</property>
<property name="spacing">
<number>0</number>
</property>
</layout>
</widget>
</item>
<item row="1" column="2">
<widget class="QLabel" name="lblInCompleteImage">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>40</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="palette">
<palette>
<active>
<colorrole role="WindowText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>0</green>
<blue>0</blue>
</color>
</brush>
</colorrole>
</active>
<inactive>
<colorrole role="WindowText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>0</green>
<blue>0</blue>
</color>
</brush>
</colorrole>
</inactive>
<disabled>
<colorrole role="WindowText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>139</red>
<green>142</green>
<blue>142</blue>
</color>
</brush>
</colorrole>
</disabled>
</palette>
</property>
<property name="text">
<string>Missing Packets</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="1" column="1"> <item row="1" column="1">
<widget class="QLabel" name="lblCompleteImage"> <widget class="QLabel" name="lblCompleteImage">
<property name="sizePolicy"> <property name="sizePolicy">
@ -320,7 +320,7 @@
</property> </property>
<property name="minimumSize"> <property name="minimumSize">
<size> <size>
<width>40</width> <width>120</width>
<height>0</height> <height>0</height>
</size> </size>
</property> </property>
@ -375,6 +375,71 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="2">
<widget class="QLabel" name="lblInCompleteImage">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>110</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="palette">
<palette>
<active>
<colorrole role="WindowText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>0</green>
<blue>0</blue>
</color>
</brush>
</colorrole>
</active>
<inactive>
<colorrole role="WindowText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>0</green>
<blue>0</blue>
</color>
</brush>
</colorrole>
</inactive>
<disabled>
<colorrole role="WindowText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>139</red>
<green>142</green>
<blue>142</blue>
</color>
</brush>
</colorrole>
</disabled>
</palette>
</property>
<property name="text">
<string>Missing Packets</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
</layout> </layout>
</widget> </widget>
<resources/> <resources/>

View File

@ -7,7 +7,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>775</width> <width>775</width>
<height>380</height> <height>385</height>
</rect> </rect>
</property> </property>
<property name="sizePolicy"> <property name="sizePolicy">
@ -32,22 +32,25 @@
<string>Form</string> <string>Form</string>
</property> </property>
<layout class="QGridLayout" name="gridLayout_2"> <layout class="QGridLayout" name="gridLayout_2">
<item row="4" column="3"> <item row="2" column="0">
<widget class="QCheckBox" name="chkCounter2"> <widget class="QLabel" name="lblThreshold">
<property name="enabled"> <property name="enabled">
<bool>false</bool> <bool>false</bool>
</property> </property>
<property name="minimumSize">
<size>
<width>110</width>
<height>0</height>
</size>
</property>
<property name="maximumSize"> <property name="maximumSize">
<size> <size>
<width>50</width> <width>110</width>
<height>16777215</height> <height>16777215</height>
</size> </size>
</property> </property>
<property name="text"> <property name="text">
<string>2</string> <string>Threshold:</string>
</property>
<property name="checked">
<bool>true</bool>
</property> </property>
</widget> </widget>
</item> </item>
@ -70,237 +73,22 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="3" column="2" colspan="3"> <item row="2" column="14">
<widget class="QComboBox" name="comboDynamicRange"> <spacer name="horizontalSpacer_2">
<property name="enabled">
<bool>false</bool>
</property>
<property name="minimumSize">
<size>
<width>140</width>
<height>25</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>140</width>
<height>16777215</height>
</size>
</property>
<item>
<property name="text">
<string>1.67772e+07</string>
</property>
</item>
<item>
<property name="text">
<string>65535</string>
</property>
</item>
<item>
<property name="text">
<string>4095</string>
</property>
</item>
<item>
<property name="text">
<string>255</string>
</property>
</item>
<item>
<property name="text">
<string>7</string>
</property>
</item>
</widget>
</item>
<item row="2" column="2" colspan="3">
<widget class="QSpinBox" name="spinThreshold">
<property name="enabled">
<bool>false</bool>
</property>
<property name="minimumSize">
<size>
<width>140</width>
<height>25</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>140</width>
<height>16777215</height>
</size>
</property>
<property name="keyboardTracking">
<bool>false</bool>
</property>
<property name="suffix">
<string> eV</string>
</property>
<property name="minimum">
<number>-100000</number>
</property>
<property name="maximum">
<number>100000</number>
</property>
<property name="singleStep">
<number>100</number>
</property>
<property name="value">
<number>-1</number>
</property>
</widget>
</item>
<item row="2" column="6">
<widget class="QSpinBox" name="spinThreshold3">
<property name="enabled">
<bool>false</bool>
</property>
<property name="minimumSize">
<size>
<width>140</width>
<height>25</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>140</width>
<height>16777215</height>
</size>
</property>
<property name="keyboardTracking">
<bool>false</bool>
</property>
<property name="suffix">
<string> eV</string>
</property>
<property name="minimum">
<number>-100000</number>
</property>
<property name="maximum">
<number>100000</number>
</property>
<property name="singleStep">
<number>100</number>
</property>
<property name="value">
<number>-1</number>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="lblDynamicRange">
<property name="enabled">
<bool>false</bool>
</property>
<property name="minimumSize">
<size>
<width>110</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>110</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Dynamic Range:</string>
</property>
</widget>
</item>
<item row="5" column="2">
<spacer name="verticalSpacer">
<property name="orientation"> <property name="orientation">
<enum>Qt::Vertical</enum> <enum>Qt::Horizontal</enum>
</property> </property>
<property name="sizeType"> <property name="sizeType">
<enum>QSizePolicy::Fixed</enum> <enum>QSizePolicy::Expanding</enum>
</property> </property>
<property name="sizeHint" stdset="0"> <property name="sizeHint" stdset="0">
<size> <size>
<width>20</width> <width>20</width>
<height>190</height> <height>20</height>
</size> </size>
</property> </property>
</spacer> </spacer>
</item> </item>
<item row="2" column="8">
<widget class="QPushButton" name="btnSetThreshold">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>100</width>
<height>30</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>30</height>
</size>
</property>
<property name="palette">
<palette>
<active>
<colorrole role="Shadow">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>20</red>
<green>20</green>
<blue>20</blue>
</color>
</brush>
</colorrole>
</active>
<inactive>
<colorrole role="Shadow">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>20</red>
<green>20</green>
<blue>20</blue>
</color>
</brush>
</colorrole>
</inactive>
<disabled>
<colorrole role="Shadow">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>20</red>
<green>20</green>
<blue>20</blue>
</color>
</brush>
</colorrole>
</disabled>
</palette>
</property>
<property name="focusPolicy">
<enum>Qt::TabFocus</enum>
</property>
<property name="text">
<string>Set</string>
</property>
<property name="icon">
<iconset resource="../include/icons.qrc">
<normaloff>:/icons/images/rightArrow.png</normaloff>:/icons/images/rightArrow.png</iconset>
</property>
<property name="flat">
<bool>false</bool>
</property>
</widget>
</item>
<item row="0" column="0"> <item row="0" column="0">
<widget class="QLabel" name="lblSettings"> <widget class="QLabel" name="lblSettings">
<property name="enabled"> <property name="enabled">
@ -323,119 +111,6 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="0" column="1">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="2" column="0">
<widget class="QLabel" name="lblThreshold">
<property name="enabled">
<bool>false</bool>
</property>
<property name="minimumSize">
<size>
<width>110</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>110</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Threshold:</string>
</property>
</widget>
</item>
<item row="2" column="5">
<widget class="QSpinBox" name="spinThreshold2">
<property name="enabled">
<bool>false</bool>
</property>
<property name="minimumSize">
<size>
<width>140</width>
<height>25</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>140</width>
<height>16777215</height>
</size>
</property>
<property name="keyboardTracking">
<bool>false</bool>
</property>
<property name="suffix">
<string> eV</string>
</property>
<property name="minimum">
<number>-100000</number>
</property>
<property name="maximum">
<number>100000</number>
</property>
<property name="singleStep">
<number>100</number>
</property>
<property name="value">
<number>-1</number>
</property>
</widget>
</item>
<item row="2" column="9">
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Expanding</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="4" column="0">
<widget class="QLabel" name="lblCounter">
<property name="enabled">
<bool>false</bool>
</property>
<property name="minimumSize">
<size>
<width>110</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>110</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Counters:</string>
</property>
</widget>
</item>
<item row="4" column="2"> <item row="4" column="2">
<widget class="QCheckBox" name="chkCounter1"> <widget class="QCheckBox" name="chkCounter1">
<property name="enabled"> <property name="enabled">
@ -455,7 +130,7 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="0" column="2" colspan="3"> <item row="0" column="2" colspan="9">
<widget class="QComboBox" name="comboSettings"> <widget class="QComboBox" name="comboSettings">
<property name="enabled"> <property name="enabled">
<bool>true</bool> <bool>true</bool>
@ -594,6 +269,268 @@
</item> </item>
</widget> </widget>
</item> </item>
<item row="2" column="11">
<widget class="QSpinBox" name="spinThreshold2">
<property name="enabled">
<bool>false</bool>
</property>
<property name="minimumSize">
<size>
<width>140</width>
<height>25</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>140</width>
<height>16777215</height>
</size>
</property>
<property name="keyboardTracking">
<bool>false</bool>
</property>
<property name="suffix">
<string> eV</string>
</property>
<property name="minimum">
<number>-100000</number>
</property>
<property name="maximum">
<number>100000</number>
</property>
<property name="singleStep">
<number>100</number>
</property>
<property name="value">
<number>-1</number>
</property>
</widget>
</item>
<item row="2" column="13">
<widget class="QPushButton" name="btnSetThreshold">
<property name="enabled">
<bool>true</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>100</width>
<height>30</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>30</height>
</size>
</property>
<property name="palette">
<palette>
<active>
<colorrole role="Shadow">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>20</red>
<green>20</green>
<blue>20</blue>
</color>
</brush>
</colorrole>
</active>
<inactive>
<colorrole role="Shadow">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>20</red>
<green>20</green>
<blue>20</blue>
</color>
</brush>
</colorrole>
</inactive>
<disabled>
<colorrole role="Shadow">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>20</red>
<green>20</green>
<blue>20</blue>
</color>
</brush>
</colorrole>
</disabled>
</palette>
</property>
<property name="focusPolicy">
<enum>Qt::TabFocus</enum>
</property>
<property name="text">
<string>Set</string>
</property>
<property name="icon">
<iconset resource="../include/icons.qrc">
<normaloff>:/icons/images/rightArrow.png</normaloff>:/icons/images/rightArrow.png</iconset>
</property>
<property name="flat">
<bool>false</bool>
</property>
</widget>
</item>
<item row="0" column="1">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="2" column="12">
<widget class="QSpinBox" name="spinThreshold3">
<property name="enabled">
<bool>false</bool>
</property>
<property name="minimumSize">
<size>
<width>140</width>
<height>25</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>140</width>
<height>16777215</height>
</size>
</property>
<property name="keyboardTracking">
<bool>false</bool>
</property>
<property name="suffix">
<string> eV</string>
</property>
<property name="minimum">
<number>-100000</number>
</property>
<property name="maximum">
<number>100000</number>
</property>
<property name="singleStep">
<number>100</number>
</property>
<property name="value">
<number>-1</number>
</property>
</widget>
</item>
<item row="2" column="2" colspan="9">
<widget class="QSpinBox" name="spinThreshold">
<property name="enabled">
<bool>false</bool>
</property>
<property name="minimumSize">
<size>
<width>140</width>
<height>25</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>140</width>
<height>16777215</height>
</size>
</property>
<property name="keyboardTracking">
<bool>false</bool>
</property>
<property name="suffix">
<string> eV</string>
</property>
<property name="minimum">
<number>-100000</number>
</property>
<property name="maximum">
<number>100000</number>
</property>
<property name="singleStep">
<number>100</number>
</property>
<property name="value">
<number>-1</number>
</property>
</widget>
</item>
<item row="4" column="0">
<widget class="QLabel" name="lblCounter">
<property name="enabled">
<bool>false</bool>
</property>
<property name="minimumSize">
<size>
<width>110</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>110</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Counters:</string>
</property>
</widget>
</item>
<item row="3" column="0">
<widget class="QLabel" name="lblDynamicRange">
<property name="enabled">
<bool>false</bool>
</property>
<property name="minimumSize">
<size>
<width>110</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>110</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Dynamic Range:</string>
</property>
</widget>
</item>
<item row="5" column="2">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>190</height>
</size>
</property>
</spacer>
</item>
<item row="1" column="0"> <item row="1" column="0">
<widget class="QLabel" name="lblGainMode"> <widget class="QLabel" name="lblGainMode">
<property name="enabled"> <property name="enabled">
@ -616,7 +553,70 @@
</property> </property>
</widget> </widget>
</item> </item>
<item row="1" column="2"> <item row="3" column="2" colspan="9">
<widget class="QComboBox" name="comboDynamicRange">
<property name="enabled">
<bool>false</bool>
</property>
<property name="minimumSize">
<size>
<width>140</width>
<height>25</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>140</width>
<height>16777215</height>
</size>
</property>
<item>
<property name="text">
<string>1.67772e+07</string>
</property>
</item>
<item>
<property name="text">
<string>65535</string>
</property>
</item>
<item>
<property name="text">
<string>4095</string>
</property>
</item>
<item>
<property name="text">
<string>255</string>
</property>
</item>
<item>
<property name="text">
<string>7</string>
</property>
</item>
</widget>
</item>
<item row="4" column="3">
<widget class="QCheckBox" name="chkCounter2">
<property name="enabled">
<bool>false</bool>
</property>
<property name="maximumSize">
<size>
<width>50</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>2</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="1" column="2" colspan="9">
<widget class="QComboBox" name="comboGainMode"> <widget class="QComboBox" name="comboGainMode">
<property name="enabled"> <property name="enabled">
<bool>false</bool> <bool>false</bool>

View File

@ -55,6 +55,7 @@ class qDrawPlot : public QWidget, private Ui::PlotObject {
void EnableGainPlot(bool enable); void EnableGainPlot(bool enable);
void ClonePlot(); void ClonePlot();
void SavePlot(); void SavePlot();
void SetGapPixels(bool enable);
protected: protected:
void resizeEvent(QResizeEvent *event); void resizeEvent(QResizeEvent *event);
@ -160,6 +161,9 @@ class qDrawPlot : public QWidget, private Ui::PlotObject {
int64_t currentFrame{0}; int64_t currentFrame{0};
mutable std::mutex mPlots; mutable std::mutex mPlots;
int64_t currentAcqIndex{0}; int64_t currentAcqIndex{0};
slsDetectorDefs::ROI rxRoi{};
bool isRxRoiDisplayed{false};
bool isGapPixels{false};
unsigned int nPixelsX{0}; unsigned int nPixelsX{0};
unsigned int nPixelsY{0}; unsigned int nPixelsY{0};

View File

@ -9,6 +9,7 @@
#include <qwt_plot_curve.h> #include <qwt_plot_curve.h>
#include <qwt_plot_marker.h> #include <qwt_plot_marker.h>
#include <qwt_scale_div.h> #include <qwt_scale_div.h>
#include <qwt_plot_shapeitem.h>
class QPen; class QPen;
class SlsQt1DPlot; class SlsQt1DPlot;
@ -136,6 +137,9 @@ class SlsQt1DPlot : public QwtPlot {
void SetLogX(bool yes = 1); void SetLogX(bool yes = 1);
void SetLogY(bool yes = 1); void SetLogY(bool yes = 1);
void EnableRoiBox(std::array<int, 4> roi);
void DisableRoiBox();
private: private:
SlsQtH1DList *hist_list{nullptr}; SlsQtH1DList *hist_list{nullptr};
SlsQt1DZoomer *zoomer{nullptr}; SlsQt1DZoomer *zoomer{nullptr};
@ -159,6 +163,8 @@ class SlsQt1DPlot : public QwtPlot {
friend void SlsQtH1D::Attach(SlsQt1DPlot *p); friend void SlsQtH1D::Attach(SlsQt1DPlot *p);
friend void SlsQtH1D::Detach(SlsQt1DPlot *p); friend void SlsQtH1D::Detach(SlsQt1DPlot *p);
QwtPlotShapeItem *roiBox{nullptr};
public slots: public slots:
void UnZoom(); void UnZoom();
void Update(); void Update();

View File

@ -6,6 +6,7 @@
#include <qlist.h> #include <qlist.h>
#include <qwt_plot.h> #include <qwt_plot.h>
#include <qwt_plot_spectrogram.h> #include <qwt_plot_spectrogram.h>
#include <qwt_plot_shapeitem.h>
class QwtPlotPanner; class QwtPlotPanner;
class QwtScaleWidget; class QwtScaleWidget;
@ -67,6 +68,8 @@ class SlsQt2DPlot : public QwtPlot {
void SetLogz(bool enable, bool isMin, bool isMax, double min, double max); void SetLogz(bool enable, bool isMin, bool isMax, double min, double max);
void SetZRange(bool isMin, bool isMax, double min, double max); void SetZRange(bool isMin, bool isMax, double min, double max);
void LogZ(bool on = 1); void LogZ(bool on = 1);
void EnableRoiBox(std::array<int, 4> roi);
void DisableRoiBox();
public slots: public slots:
void showSpectrogram(bool on); void showSpectrogram(bool on);
@ -86,4 +89,5 @@ class SlsQt2DPlot : public QwtPlot {
QList<double> contourLevelsLog; QList<double> contourLevelsLog;
bool disableZoom{false}; bool disableZoom{false};
int isLog; int isLog;
QwtPlotShapeItem *roiBox{nullptr};
}; };

View File

@ -442,6 +442,28 @@ void SlsQt1DPlot::SetLog(int axisId, bool yes) {
Update(); Update();
} }
void SlsQt1DPlot::EnableRoiBox(std::array<int, 4> roi) {
if (roiBox == nullptr) {
roiBox = new QwtPlotShapeItem();
roiBox->attach(this);
roiBox->setPen(QColor(Qt::yellow), 2.0, Qt::SolidLine);
}
// TopLeft - BottomRight (max points are +1 on graph)
QRect myRect(QPoint(roi[0], roi[2]), QPoint(roi[1] - 1, roi[3] - 1));
roiBox->setRect( QRectF(myRect) );
replot();
}
void SlsQt1DPlot::DisableRoiBox() {
if (roiBox != nullptr) {
roiBox->detach();
replot();
}
}
void SlsQt1DPlot::UnZoom() { void SlsQt1DPlot::UnZoom() {
setAxisScale(QwtPlot::xBottom, zoomer->x(), zoomer->x() + zoomer->w()); setAxisScale(QwtPlot::xBottom, zoomer->x(), zoomer->x() + zoomer->w());
setAxisScale(QwtPlot::yLeft, zoomer->y(), zoomer->y() + zoomer->h()); setAxisScale(QwtPlot::yLeft, zoomer->y(), zoomer->y() + zoomer->h());

View File

@ -290,3 +290,25 @@ void SlsQt2DPlot::showSpectrogram(bool on) {
d_spectrogram->setDefaultContourPen(on ? QPen() : QPen(Qt::NoPen)); d_spectrogram->setDefaultContourPen(on ? QPen() : QPen(Qt::NoPen));
Update(); Update();
} }
void SlsQt2DPlot::EnableRoiBox(std::array<int, 4> roi) {
if (roiBox == nullptr) {
roiBox = new QwtPlotShapeItem();
}
roiBox->setPen(QColor(Qt::yellow), 2.0, Qt::SolidLine);
// TopLeft - BottomRight (max points are +1 on graph)
QRect myRect(QPoint(roi[0], roi[2]), QPoint(roi[1] - 1, roi[3] - 1));
roiBox->setRect( QRectF(myRect) );
roiBox->attach(this);
replot();
}
void SlsQt2DPlot::DisableRoiBox() {
if (roiBox != nullptr) {
roiBox->detach();
replot();
}
}

View File

@ -278,11 +278,13 @@ void qDrawPlot::Select1dPlot(bool enable) {
} }
void qDrawPlot::SetPlotTitlePrefix(QString title) { void qDrawPlot::SetPlotTitlePrefix(QString title) {
std::lock_guard<std::mutex> lock(mPlots);
LOG(logINFO) << "Setting Title to " << title.toAscii().constData(); LOG(logINFO) << "Setting Title to " << title.toAscii().constData();
plotTitlePrefix = title; plotTitlePrefix = title;
} }
void qDrawPlot::SetXAxisTitle(QString title) { void qDrawPlot::SetXAxisTitle(QString title) {
std::lock_guard<std::mutex> lock(mPlots);
LOG(logINFO) << "Setting X Axis Title to " << title.toAscii().constData(); LOG(logINFO) << "Setting X Axis Title to " << title.toAscii().constData();
if (is1d) { if (is1d) {
xTitle1d = title; xTitle1d = title;
@ -292,6 +294,7 @@ void qDrawPlot::SetXAxisTitle(QString title) {
} }
void qDrawPlot::SetYAxisTitle(QString title) { void qDrawPlot::SetYAxisTitle(QString title) {
std::lock_guard<std::mutex> lock(mPlots);
LOG(logINFO) << "Setting Y Axis Title to " << title.toAscii().constData(); LOG(logINFO) << "Setting Y Axis Title to " << title.toAscii().constData();
if (is1d) { if (is1d) {
yTitle1d = title; yTitle1d = title;
@ -301,6 +304,7 @@ void qDrawPlot::SetYAxisTitle(QString title) {
} }
void qDrawPlot::SetZAxisTitle(QString title) { void qDrawPlot::SetZAxisTitle(QString title) {
std::lock_guard<std::mutex> lock(mPlots);
LOG(logINFO) << "Setting Z Axis Title to " << title.toAscii().constData(); LOG(logINFO) << "Setting Z Axis Title to " << title.toAscii().constData();
zTitle2d = title; zTitle2d = title;
} }
@ -318,6 +322,7 @@ void qDrawPlot::SetXYRangeChanged(bool disable, double *xy, bool *isXY) {
} }
void qDrawPlot::SetZRange(double *z, bool *isZ) { void qDrawPlot::SetZRange(double *z, bool *isZ) {
std::lock_guard<std::mutex> lock(mPlots);
std::copy(z, z + 2, zRange); std::copy(z, z + 2, zRange);
std::copy(isZ, isZ + 2, isZRange); std::copy(isZ, isZ + 2, isZRange);
} }
@ -351,6 +356,7 @@ double qDrawPlot::GetYMaximum() {
} }
void qDrawPlot::SetDataCallBack(bool enable) { void qDrawPlot::SetDataCallBack(bool enable) {
std::lock_guard<std::mutex> lock(mPlots);
LOG(logINFO) << "Setting data call back to " << std::boolalpha << enable LOG(logINFO) << "Setting data call back to " << std::boolalpha << enable
<< std::noboolalpha; << std::noboolalpha;
try { try {
@ -369,6 +375,7 @@ void qDrawPlot::SetDataCallBack(bool enable) {
} }
void qDrawPlot::SetBinary(bool enable, int from, int to) { void qDrawPlot::SetBinary(bool enable, int from, int to) {
std::lock_guard<std::mutex> lock(mPlots);
LOG(logINFO) << (enable ? "Enabling" : "Disabling") LOG(logINFO) << (enable ? "Enabling" : "Disabling")
<< " Binary output from " << from << " to " << to; << " Binary output from " << from << " to " << to;
binaryFrom = from; binaryFrom = from;
@ -377,6 +384,7 @@ void qDrawPlot::SetBinary(bool enable, int from, int to) {
} }
void qDrawPlot::SetPersistency(int val) { void qDrawPlot::SetPersistency(int val) {
std::lock_guard<std::mutex> lock(mPlots);
LOG(logINFO) << "Setting Persistency to " << val; LOG(logINFO) << "Setting Persistency to " << val;
persistency = val; persistency = val;
} }
@ -458,17 +466,20 @@ void qDrawPlot::ResetAccumulate() {
} }
void qDrawPlot::DisplayStatistics(bool enable) { void qDrawPlot::DisplayStatistics(bool enable) {
std::lock_guard<std::mutex> lock(mPlots);
LOG(logINFO) << (enable ? "Enabling" : "Disabling") LOG(logINFO) << (enable ? "Enabling" : "Disabling")
<< " Statistics Display"; << " Statistics Display";
displayStatistics = enable; displayStatistics = enable;
} }
void qDrawPlot::SetNumDiscardBits(int value) { void qDrawPlot::SetNumDiscardBits(int value) {
std::lock_guard<std::mutex> lock(mPlots);
LOG(logINFO) << "Setting number of bits to discard: " << value; LOG(logINFO) << "Setting number of bits to discard: " << value;
numDiscardBits = value; numDiscardBits = value;
} }
void qDrawPlot::EnableGainPlot(bool enable) { void qDrawPlot::EnableGainPlot(bool enable) {
std::lock_guard<std::mutex> lock(mPlots);
LOG(logINFO) << (enable ? "Enabling" : "Disabling") << " Gain Plot"; LOG(logINFO) << (enable ? "Enabling" : "Disabling") << " Gain Plot";
hasGainData = enable; hasGainData = enable;
} }
@ -609,6 +620,13 @@ void qDrawPlot::SavePlot() {
} }
} }
void qDrawPlot::SetGapPixels(bool enable) {
LOG(logDEBUG) << "Gap pixels enabled";
std::lock_guard<std::mutex> lock(mPlots);
isGapPixels = enable;
}
void qDrawPlot::GetStatistics(double &min, double &max, double &sum) { void qDrawPlot::GetStatistics(double &min, double &max, double &sum) {
LOG(logDEBUG) << "Calculating Statistics"; LOG(logDEBUG) << "Calculating Statistics";
double *array = data2d; double *array = data2d;
@ -642,6 +660,7 @@ void qDrawPlot::StartAcquisition() {
currentFrame = 0; currentFrame = 0;
boxPlot->setTitle("Old Plot"); boxPlot->setTitle("Old Plot");
det->clearAcquiringFlag(); // (from previous exit) or if running det->clearAcquiringFlag(); // (from previous exit) or if running
isRxRoiDisplayed = false;
// ensure data streaming in receiver (if plot enabled) // ensure data streaming in receiver (if plot enabled)
if (isPlot) { if (isPlot) {
@ -742,6 +761,7 @@ void qDrawPlot::GetData(detectorData *data, uint64_t frameIndex,
<< " \t dynamic range: " << data->dynamicRange << std::endl << " \t dynamic range: " << data->dynamicRange << std::endl
<< " \t file index: " << data->fileIndex << std::endl << " \t file index: " << data->fileIndex << std::endl
<< " \t complete image: " << data->completeImage << std::endl << " \t complete image: " << data->completeImage << std::endl
<< " \t rx Roi: " << sls::ToString(data->rxRoi) << std::endl
<< " ]"; << " ]";
progress = data->progressIndex; progress = data->progressIndex;
@ -749,6 +769,22 @@ void qDrawPlot::GetData(detectorData *data, uint64_t frameIndex,
currentFrame = frameIndex; currentFrame = frameIndex;
LOG(logDEBUG) << "[ Progress:" << progress << "%, Frame:" << currentFrame LOG(logDEBUG) << "[ Progress:" << progress << "%, Frame:" << currentFrame
<< " ]"; << " ]";
if (!isRxRoiDisplayed) {
rxRoi.xmin = data->rxRoi[0];
rxRoi.xmax = data->rxRoi[1];
rxRoi.ymin = data->rxRoi[2];
rxRoi.ymax = data->rxRoi[3];
// only for 2d anyway
if (isGapPixels) {
rxRoi.xmin += ((rxRoi.xmin/1024) * 6 + (rxRoi.xmin/256) * 2);
rxRoi.xmax += ((rxRoi.xmax/1024) * 6 + (rxRoi.xmax/256) * 2);
rxRoi.ymin += ((rxRoi.ymin/512) * 34 + (rxRoi.ymin/256) * 2);
rxRoi.ymax += ((rxRoi.ymax/512) * 34 + (rxRoi.ymax/256) * 2);
LOG(logINFO) << "Rx_roi recalculated with gap pixels: " << sls::ToString(rxRoi);
}
LOG(logDEBUG) << "Rx_roi: " << sls::ToString(rxRoi);
}
// 1d check if npixelX has changed (m3 for different counters enabled) // 1d check if npixelX has changed (m3 for different counters enabled)
if (is1d && static_cast<int>(nPixelsX) != data->nx) { if (is1d && static_cast<int>(nPixelsX) != data->nx) {
@ -987,6 +1023,26 @@ void qDrawPlot::Update1dPlot() {
xyRangeChanged = false; xyRangeChanged = false;
} }
plot1d->DisableZoom(disableZoom); plot1d->DisableZoom(disableZoom);
if (!isRxRoiDisplayed) {
isRxRoiDisplayed = true;
if (rxRoi.completeRoi()) {
plot1d->DisableRoiBox();
if (isGainDataExtracted) {
gainplot1d->DisableRoiBox();
}
lblRxRoiEnabled->hide();
} else {
plot1d->EnableRoiBox(std::array<int, 4>{rxRoi.xmin, rxRoi.xmax, (int)plot1d->GetYMinimum(), (int)plot1d->GetYMaximum()});
if (isGainDataExtracted) {
gainplot1d->EnableRoiBox(std::array<int, 4>{rxRoi.xmin, rxRoi.xmax, 0, 3});
}
lblRxRoiEnabled->show();
}
}
// ymin and ymax could change (so replot roi every time)
if (!rxRoi.completeRoi()) {
plot1d->EnableRoiBox(std::array<int, 4>{rxRoi.xmin, rxRoi.xmax, (int)plot1d->GetYMinimum(), (int)plot1d->GetYMaximum()});
}
} }
void qDrawPlot::Update2dPlot() { void qDrawPlot::Update2dPlot() {
@ -1015,6 +1071,22 @@ void qDrawPlot::Update2dPlot() {
} }
plot2d->DisableZoom(disableZoom); plot2d->DisableZoom(disableZoom);
plot2d->SetZRange(isZRange[0], isZRange[1], zRange[0], zRange[1]); plot2d->SetZRange(isZRange[0], isZRange[1], zRange[0], zRange[1]);
if (!isRxRoiDisplayed) {
isRxRoiDisplayed = true;
if (rxRoi.completeRoi()) {
plot2d->DisableRoiBox();
if (isGainDataExtracted) {
gainplot2d->DisableRoiBox();
}
lblRxRoiEnabled->hide();
} else {
plot2d->EnableRoiBox(rxRoi.getIntArray());
if (isGainDataExtracted) {
gainplot2d->EnableRoiBox(rxRoi.getIntArray());
}
lblRxRoiEnabled->show();
}
}
} }
void qDrawPlot::Update1dXYRange() { void qDrawPlot::Update1dXYRange() {

View File

@ -331,6 +331,7 @@ void qTabPlot::SetGapPixels(bool enable) {
LOG(logINFO) << "Setting Gap Pixels Enable to " << enable; LOG(logINFO) << "Setting Gap Pixels Enable to " << enable;
try { try {
det->setGapPixelsinCallback(enable); det->setGapPixelsinCallback(enable);
plot->SetGapPixels(enable);
} }
CATCH_HANDLE("Could not set gap pixels enable.", "qTabPlot::SetGapPixels", CATCH_HANDLE("Could not set gap pixels enable.", "qTabPlot::SetGapPixels",
this, &qTabPlot::GetGapPixels) this, &qTabPlot::GetGapPixels)

View File

@ -432,6 +432,8 @@ void setupDetector() {
// roi, gbit readout // roi, gbit readout
rois.xmin = -1; rois.xmin = -1;
rois.xmax = -1; rois.xmax = -1;
rois.ymin = -1;
rois.ymax = -1;
setROI(rois); // set adcsyncreg, daqreg, chipofinterestreg, cleanfifos, setROI(rois); // set adcsyncreg, daqreg, chipofinterestreg, cleanfifos,
setGbitReadout(); setGbitReadout();
@ -857,8 +859,10 @@ int setROI(ROI arg) {
LOG(logINFO, ("Clearing ROI\n")); LOG(logINFO, ("Clearing ROI\n"));
rois.xmin = -1; rois.xmin = -1;
rois.xmax = -1; rois.xmax = -1;
rois.ymin = -1;
rois.ymax = -1;
} else { } else {
LOG(logINFO, ("Setting ROI:(%d, %d)\n", arg.xmin, arg.xmax)); LOG(logINFO, ("Setting ROI:(%d, %d, %d, %d)\n", arg.xmin, arg.xmax, arg.ymin, arg.ymax));
// validation // validation
// xmin divisible by 256 and less than 1280 // xmin divisible by 256 and less than 1280
if (((arg.xmin % NCHAN_PER_ADC) != 0) || if (((arg.xmin % NCHAN_PER_ADC) != 0) ||
@ -892,7 +896,7 @@ ROI getROI() {
if (rois.xmin == -1) { if (rois.xmin == -1) {
LOG(logINFO, ("\tROI: None\n")); LOG(logINFO, ("\tROI: None\n"));
} else { } else {
LOG(logINFO, ("ROI: (%d,%d)\n", rois.xmin, rois.xmax)); LOG(logINFO, ("ROI: (%d,%d,%d,%d)\n", rois.xmin, rois.xmax, rois.ymin, rois.ymax));
} }
return rois; return rois;
} }

View File

@ -25,7 +25,7 @@ target_include_directories(jungfrauDetectorServer_virtual
) )
target_compile_definitions(jungfrauDetectorServer_virtual target_compile_definitions(jungfrauDetectorServer_virtual
PUBLIC JUNGFRAUD VIRTUAL STOP_SERVER PUBLIC JUNGFRAUD VIRTUAL STOP_SERVER #TEST_MOD_GEOMETRY
) )
target_link_libraries(jungfrauDetectorServer_virtual target_link_libraries(jungfrauDetectorServer_virtual

View File

@ -2317,6 +2317,7 @@ void *start_timer(void *arg) {
if (dr == 32 && ncounters > 1) { if (dr == 32 && ncounters > 1) {
packetsPerFrame = 2; packetsPerFrame = 2;
} }
dataSize = imageSize / packetsPerFrame;
} }
// 1g // 1g
else { else {
@ -2338,29 +2339,24 @@ void *start_timer(void *arg) {
{ {
const int nchannels = NCHAN_1_COUNTER * NCHIP * ncounters; const int nchannels = NCHAN_1_COUNTER * NCHIP * ncounters;
switch (dr) {
/*case 1: // TODO: Not implemented in firmware yet
break;*/
case 8:
for (int i = 0; i < nchannels; ++i) { for (int i = 0; i < nchannels; ++i) {
switch (dr) {
//case 1: // TODO: Not implemented in firmware yet
// break;
case 8:
*((uint8_t *)(imageData + i)) = (uint8_t)i; *((uint8_t *)(imageData + i)) = (uint8_t)i;
}
break; break;
case 16: case 16:
for (int i = 0; i < nchannels; ++i) {
*((uint16_t *)(imageData + i * sizeof(uint16_t))) = (uint16_t)i; *((uint16_t *)(imageData + i * sizeof(uint16_t))) = (uint16_t)i;
}
break; break;
case 32: case 32:
for (int i = 0; i < nchannels; ++i) { *((uint32_t *)(imageData + i * sizeof(uint32_t))) = ((uint32_t)i & 0xFFFFFF); // 24 bit
*((uint32_t *)(imageData + i * sizeof(uint32_t))) =
((uint32_t)i & 0xFFFFFF); // 24 bit
}
break; break;
default: default:
break; break;
} }
} }
}
// Send data // Send data
// loop over number of frames // loop over number of frames
@ -2376,6 +2372,7 @@ void *start_timer(void *arg) {
clock_gettime(CLOCK_REALTIME, &begin); clock_gettime(CLOCK_REALTIME, &begin);
usleep(expUs); usleep(expUs);
int srcOffset = 0; int srcOffset = 0;
// loop packet // loop packet
for (int i = 0; i != packetsPerFrame; ++i) { for (int i = 0; i != packetsPerFrame; ++i) {
@ -2396,7 +2393,6 @@ void *start_timer(void *arg) {
memcpy(packetData + sizeof(sls_detector_header), memcpy(packetData + sizeof(sls_detector_header),
imageData + srcOffset, dataSize); imageData + srcOffset, dataSize);
srcOffset += dataSize; srcOffset += dataSize;
sendUDPPacket(0, 0, packetData, packetSize); sendUDPPacket(0, 0, packetData, packetSize);
} }
LOG(logINFO, ("Sent frame: %d [%lld]\n", frameNr, LOG(logINFO, ("Sent frame: %d [%lld]\n", frameNr,

View File

@ -2045,7 +2045,7 @@ int set_num_frames(int file_des) {
arg > MAX_FRAMES_IN_BURST_MODE) { arg > MAX_FRAMES_IN_BURST_MODE) {
ret = FAIL; ret = FAIL;
sprintf(mess, sprintf(mess,
"Could not set number of frames %lld. Must be <= %d in " "Could not set number of frames %lld. Must be less than equal to %d in "
"burst mode.\n", "burst mode.\n",
(long long unsigned int)arg, MAX_FRAMES_IN_BURST_MODE); (long long unsigned int)arg, MAX_FRAMES_IN_BURST_MODE);
LOG(logERROR, (mess)); LOG(logERROR, (mess));
@ -2863,7 +2863,12 @@ int set_roi(int file_des) {
return printSocketReadError(); return printSocketReadError();
if (receiveData(file_des, &arg.xmax, sizeof(int), INT32) < 0) if (receiveData(file_des, &arg.xmax, sizeof(int), INT32) < 0)
return printSocketReadError(); return printSocketReadError();
LOG(logDEBUG1, ("Set ROI: [%d, %d]\n", arg.xmin, arg.xmax)); if (receiveData(file_des, &arg.ymin, sizeof(int), INT32) < 0)
return printSocketReadError();
if (receiveData(file_des, &arg.ymax, sizeof(int), INT32) < 0)
return printSocketReadError();
LOG(logDEBUG1, ("Set ROI: [%d, %d, %d, %d]\n", arg.xmin, arg.xmax, arg.ymin,
arg.ymax));
#ifndef GOTTHARDD #ifndef GOTTHARDD
functionNotImplemented(); functionNotImplemented();
@ -2895,13 +2900,16 @@ int get_roi(int file_des) {
#else #else
// only get // only get
retval = getROI(); retval = getROI();
LOG(logDEBUG1, ("nRois: (%d, %d)\n", retval.xmin, retval.xmax)); LOG(logDEBUG1, ("nRois: (%d, %d, %d, %d)\n", retval.xmin, retval.xmax,
retval.ymin, retval.ymax));
#endif #endif
Server_SendResult(file_des, INT32, NULL, 0); Server_SendResult(file_des, INT32, NULL, 0);
if (ret != FAIL) { if (ret != FAIL) {
sendData(file_des, &retval.xmin, sizeof(int), INT32); sendData(file_des, &retval.xmin, sizeof(int), INT32);
sendData(file_des, &retval.xmax, sizeof(int), INT32); sendData(file_des, &retval.xmax, sizeof(int), INT32);
sendData(file_des, &retval.ymin, sizeof(int), INT32);
sendData(file_des, &retval.ymax, sizeof(int), INT32);
} }
return ret; return ret;
} }
@ -7134,6 +7142,8 @@ int get_receiver_parameters(int file_des) {
#else #else
roi.xmin = -1; roi.xmin = -1;
roi.xmax = -1; roi.xmax = -1;
roi.ymin = -1;
roi.ymax = -1;
#endif #endif
n += sendData(file_des, &roi.xmin, sizeof(int), INT32); n += sendData(file_des, &roi.xmin, sizeof(int), INT32);
if (n < 0) if (n < 0)
@ -7141,6 +7151,12 @@ int get_receiver_parameters(int file_des) {
n += sendData(file_des, &roi.xmax, sizeof(int), INT32); n += sendData(file_des, &roi.xmax, sizeof(int), INT32);
if (n < 0) if (n < 0)
return printSocketReadError(); return printSocketReadError();
n += sendData(file_des, &roi.ymin, sizeof(int), INT32);
if (n < 0)
return printSocketReadError();
n += sendData(file_des, &roi.ymax, sizeof(int), INT32);
if (n < 0)
return printSocketReadError();
} }
// counter mask // counter mask

View File

@ -899,6 +899,16 @@ class Detector {
* every minute. Useful in 10G mode. */ * every minute. Useful in 10G mode. */
void setRxArping(bool value, Positions pos = {}); void setRxArping(bool value, Positions pos = {});
/** at module level */
Result<defs::ROI> getIndividualRxROIs(Positions pos) const;
defs::ROI getRxROI() const;
/** only at multi module level without gap pixels */
void setRxROI(const defs::ROI value);
void clearRxROI();
///@} ///@}
/** @name File */ /** @name File */

View File

@ -9,27 +9,12 @@
*/ */
class detectorData { class detectorData {
public: public:
/** detectorData(double progressIndex, std::string fileName, int nx, int ny, char *data, int databytes, int dynamicRange, uint64_t fileIndex, bool completeImage)
* Constructor : progressIndex(progressIndex), fileName(fileName), fileIndex(fileIndex), nx(nx), ny(ny), data(data), databytes(databytes), dynamicRange(dynamicRange), completeImage(completeImage){};
* @param progress progress index
* @param fname file name prefix
* @param x number of detector channels (1D detector) or dimension in x (2D
* detector)
* @param y dimension in y (2D detector)
* @param d pointer to data in char* format
* @param dbytes number of bytes of image pointed to by cval pointer
* @param dr dynamic range or bits per pixel
* @param fIndex file index
* @param complete true if complete image, else missing packets
*/
detectorData(double progress, std::string fname, int x, int y, char *d,
int dbytes, int dr, uint64_t fIndex, bool complete)
: progressIndex(progress), fileName(fname), fileIndex(fIndex), nx(x),
ny(y), data(d), databytes(dbytes), dynamicRange(dr),
completeImage(complete){};
detectorData(double progressIndex, std::string fileName, int nx, int ny, char *data, int databytes, int dynamicRange, uint64_t fileIndex, bool completeImage, std::array<int, 4> rxRoi)
: progressIndex(progressIndex), fileName(fileName), fileIndex(fileIndex), nx(nx), ny(ny), data(data), databytes(databytes), dynamicRange(dynamicRange), completeImage(completeImage), rxRoi(rxRoi) {};
/** /**
* Destructor
* data has to be deleted by caller * data has to be deleted by caller
*/ */
~detectorData(){}; ~detectorData(){};
@ -60,8 +45,9 @@ class detectorData {
uint64_t fileIndex; uint64_t fileIndex;
int nx; int nx;
int ny; int ny;
char *data; char *data{nullptr};
int databytes; int databytes;
int dynamicRange; int dynamicRange;
bool completeImage; bool completeImage;
std::array<int,4> rxRoi{{-1, -1, -1, -1}};
}; };

View File

@ -354,7 +354,7 @@ std::string CmdProxy::DetectorSize(int action) {
WrongNumberOfParameters(0); WrongNumberOfParameters(0);
} }
auto t = det->getDetectorSize(); auto t = det->getDetectorSize();
os << "[" << t.x << ", " << t.y << "]\n"; os << t << '\n';
} else if (action == defs::PUT_ACTION) { } else if (action == defs::PUT_ACTION) {
if (args.size() != 2) { if (args.size() != 2) {
WrongNumberOfParameters(2); WrongNumberOfParameters(2);
@ -1152,7 +1152,8 @@ std::string CmdProxy::DacList(const int action) {
"names. Cannot change them."); "names. Cannot change them.");
} }
if (det_id != -1) { if (det_id != -1) {
throw sls::RuntimeError("Cannot configure dacnames at module level"); throw sls::RuntimeError(
"Cannot configure dacnames at module level");
} }
if (args.size() != 18) { if (args.size() != 18) {
WrongNumberOfParameters(18); WrongNumberOfParameters(18);
@ -1646,6 +1647,51 @@ std::string CmdProxy::ReceiverHostname(int action) {
} }
return os.str(); return os.str();
} }
std::string CmdProxy::Rx_ROI(int action) {
std::ostringstream os;
os << cmd << ' ';
if (action == defs::HELP_ACTION) {
os << "[xmin] [xmax] [ymin] [ymax]\n\tRegion of interest in "
"receiver.\n\tOnly allowed at multi module level and without gap pixels."
<< '\n';
} else if (action == defs::GET_ACTION) {
if (!args.empty()) {
WrongNumberOfParameters(0);
}
if (det_id == -1) {
auto t = det->getRxROI();
os << t << '\n';
} else {
auto t = det->getIndividualRxROIs(std::vector<int>{det_id});
os << t << '\n';
}
} else if (action == defs::PUT_ACTION) {
defs::ROI t;
// 2 or 4 arguments
if (args.size() != 2 && args.size() != 4) {
WrongNumberOfParameters(2);
}
if (args.size() == 2 || args.size() == 4) {
t.xmin = StringTo<int>(args[0]);
t.xmax = StringTo<int>(args[1]);
}
if (args.size() == 4) {
t.ymin = StringTo<int>(args[2]);
t.ymax = StringTo<int>(args[3]);
}
// only multi level
if (det_id != -1) {
throw RuntimeError("Cannot execute receiver ROI at module level");
}
det->setRxROI(t);
os << t << '\n';
} else {
throw sls::RuntimeError("Unknown action");
}
return os.str();
}
/* File */ /* File */
/* ZMQ Streaming Parameters (Receiver<->Client) */ /* ZMQ Streaming Parameters (Receiver<->Client) */
@ -1898,9 +1944,7 @@ std::string CmdProxy::ROI(int action) {
WrongNumberOfParameters(0); WrongNumberOfParameters(0);
} }
auto t = det->getROI(std::vector<int>{det_id}); auto t = det->getROI(std::vector<int>{det_id});
for (auto &it : t) { os << t << '\n';
os << '[' << it.xmin << ", " << it.xmax << "] \n";
}
} else if (action == defs::PUT_ACTION) { } else if (action == defs::PUT_ACTION) {
if (det_id == -1 && det->size() > 1) { if (det_id == -1 && det->size() > 1) {
throw sls::RuntimeError("Cannot execute ROI at multi module level"); throw sls::RuntimeError("Cannot execute ROI at multi module level");
@ -1910,28 +1954,7 @@ std::string CmdProxy::ROI(int action) {
} }
defs::ROI t(StringTo<int>(args[0]), StringTo<int>(args[1])); defs::ROI t(StringTo<int>(args[0]), StringTo<int>(args[1]));
det->setROI(t, det_id); det->setROI(t, det_id);
os << '[' << t.xmin << ", " << t.xmax << "]\n"; os << t << '\n';
} else {
throw sls::RuntimeError("Unknown action");
}
return os.str();
}
std::string CmdProxy::ClearROI(int action) {
std::ostringstream os;
os << cmd << ' ';
if (action == defs::HELP_ACTION) {
os << "\n\t[Gotthard] Resets Region of interest in detector. All "
"channels enabled. Default is all channels enabled."
<< '\n';
} else if (action == defs::GET_ACTION) {
throw sls::RuntimeError("Cannot get");
} else if (action == defs::PUT_ACTION) {
if (!args.empty()) {
WrongNumberOfParameters(0);
}
det->clearROI(std::vector<int>{det_id});
os << "[-1, -1]\n";
} else { } else {
throw sls::RuntimeError("Unknown action"); throw sls::RuntimeError("Unknown action");
} }
@ -2101,9 +2124,8 @@ std::string CmdProxy::VetoStreaming(int action) {
os << "[none|lll|10gbe|...]\n\t[Gotthard2] Enable or disable the 2 " os << "[none|lll|10gbe|...]\n\t[Gotthard2] Enable or disable the 2 "
"veto streaming interfaces available. Can include more than one " "veto streaming interfaces available. Can include more than one "
"interface. \n\tDefault: none. lll (low latency link) is the " "interface. \n\tDefault: none. lll (low latency link) is the "
"default " "default interface to work with. \n\t10GbE is for debugging and "
"interface to work with. \n\t10GbE is for debugging and also " "also enables second interface in receiver for listening to veto "
"enables second interface in receiver for listening to veto "
"packets (writes a separate file if writing enabled). Also " "packets (writes a separate file if writing enabled). Also "
"restarts client and receiver zmq sockets if zmq streaming " "restarts client and receiver zmq sockets if zmq streaming "
"enabled." "enabled."
@ -2294,9 +2316,9 @@ std::string CmdProxy::GateDelay(int action) {
os << cmd << ' '; os << cmd << ' ';
if (action == defs::HELP_ACTION) { if (action == defs::HELP_ACTION) {
if (cmd == "gatedelay") { if (cmd == "gatedelay") {
os << "[duration] [(optional unit) " os << "[duration] [(optional unit) ns|us|ms|s]\n\t[Mythen3] Gate "
"ns|us|ms|s]\n\t[Mythen3] Gate Delay of all gate signals in " "Delay of all gate signals in auto and trigger mode "
"auto and trigger mode (internal gating)." "(internal gating)."
<< '\n'; << '\n';
} else if (cmd == "gatedelay1") { } else if (cmd == "gatedelay1") {
os << "[n_value]\n\t[Mythen3] Gate Delay of gate signal 1 in auto " os << "[n_value]\n\t[Mythen3] Gate Delay of gate signal 1 in auto "
@ -2807,11 +2829,11 @@ std::string CmdProxy::AdditionalJsonHeader(int action) {
std::ostringstream os; std::ostringstream os;
os << cmd << ' '; os << cmd << ' ';
if (action == defs::HELP_ACTION) { if (action == defs::HELP_ACTION) {
os << "[key1] [value1] [key2] [value2]...[keyn] [valuen]" os << "[key1] [value1] [key2] [value2]...[keyn] [valuen]\n\tAdditional "
"\n\tAdditional json header to be streamed out from receiver via " "json header to be streamed out from receiver via zmq. Default "
"zmq. Default is empty. Max 20 characters for each key/value. " "is empty. Max 20 characters for each key/value. Use only if to "
"Use only if to be processed by an intermediate user process " "be processed by an intermediate user process listening to "
"listening to receiver zmq packets. Empty value deletes header. " "receiver zmq packets. Empty value deletes header. "
<< '\n'; << '\n';
} else if (action == defs::GET_ACTION) { } else if (action == defs::GET_ACTION) {
if (!args.empty()) { if (!args.empty()) {
@ -2921,10 +2943,10 @@ std::string CmdProxy::UpdateDetectorServer(int action) {
os << cmd << ' '; os << cmd << ' ';
if (action == defs::HELP_ACTION) { if (action == defs::HELP_ACTION) {
os << "[server_name with full " os << "[server_name with full "
"path]\n\t[Jungfrau][Eiger][Ctb][Moench][Mythen3][" "path]\n\t[Jungfrau][Eiger][Ctb][Moench][Mythen3][Gotthard2] "
"Gotthard2] Copies detector server via TCP (without tftp). Makes " "Copies detector server via TCP (without tftp). Makes a symbolic "
"a symbolic link with a shorter name (without vx.x.x). Then, " "link with a shorter name (without vx.x.x). Then, detector "
"detector controller reboots (except " "controller reboots (except "
"Eiger).\n\t[Jungfrau][Ctb][Moench]Also changes respawn server " "Eiger).\n\t[Jungfrau][Ctb][Moench]Also changes respawn server "
"to the link, which is effective after a reboot." "to the link, which is effective after a reboot."
<< '\n'; << '\n';
@ -2947,11 +2969,9 @@ std::string CmdProxy::UpdateKernel(int action) {
os << cmd << ' '; os << cmd << ' ';
if (action == defs::HELP_ACTION) { if (action == defs::HELP_ACTION) {
os << "[kernel_name with full " os << "[kernel_name with full "
"path]\n\t[Jungfrau][Ctb][Moench][Mythen3][" "path]\n\t[Jungfrau][Ctb][Moench][Mythen3][Gotthard2] Advanced "
"Gotthard2] Advanced Command!! You could damage the detector. " "Command!! You could damage the detector. Please use with "
"Please use" "caution.\n\tUpdates the kernel image. Then, detector controller "
" with caution.\n\tUpdates the kernel image. Then, detector "
"controller "
"reboots with new kernel." "reboots with new kernel."
<< '\n'; << '\n';
} else if (action == defs::GET_ACTION) { } else if (action == defs::GET_ACTION) {
@ -2972,16 +2992,15 @@ std::string CmdProxy::UpdateFirmwareAndDetectorServer(int action) {
std::ostringstream os; std::ostringstream os;
os << cmd << ' '; os << cmd << ' ';
if (action == defs::HELP_ACTION) { if (action == defs::HELP_ACTION) {
os << "\n\tWithout tftp: [server_name (incl fullpath)] " os << "\n\tWithout tftp: [server_name (incl fullpath)] [fname.pof "
"[fname.pof (incl full path)] " "(incl full path)] This does not use "
"This does not use tftp." "tftp.\n\t\t[Jungfrau][Gotthard][CTB][Moench] Updates the "
"\n\t\t[Jungfrau][Gotthard][CTB][Moench] Updates the " "firmware, detector server, deletes old server, creates the "
"firmware, detector server, deletes old server, creates the symbolic link and then " "symbolic link and then reboots detector controller. "
"reboots detector controller. \n\t\t[Mythen3][Gotthard2] will " "\n\t\t[Mythen3][Gotthard2] will require a script to start up "
"require a script to start up the shorter named server link at " "the shorter named server link at start up. \n\t\tserver_name is "
"start up. \n\t\tserver_name is full path name of detector server " "full path name of detector server binary\n\t\tfname is full "
"binary" "path of programming file"
"\n\t\tfname is full path of programming file"
<< '\n'; << '\n';
} else if (action == defs::GET_ACTION) { } else if (action == defs::GET_ACTION) {
throw sls::RuntimeError("Cannot get"); throw sls::RuntimeError("Cannot get");
@ -2989,7 +3008,6 @@ std::string CmdProxy::UpdateFirmwareAndDetectorServer(int action) {
if (args.size() != 2) { if (args.size() != 2) {
WrongNumberOfParameters(2); WrongNumberOfParameters(2);
} }
int fpos = args.size() - 1; int fpos = args.size() - 1;
if (args[fpos].find(".pof") == std::string::npos && if (args[fpos].find(".pof") == std::string::npos &&
args[fpos].find(".rbf") == std::string::npos) { args[fpos].find(".rbf") == std::string::npos) {
@ -3039,8 +3057,7 @@ std::string CmdProxy::AdcRegister(int action) {
os << cmd << ' '; os << cmd << ' ';
if (action == defs::HELP_ACTION) { if (action == defs::HELP_ACTION) {
os << "[address] [value]\n\t[Jungfrau][Ctb][Moench][Gotthard] Writes " os << "[address] [value]\n\t[Jungfrau][Ctb][Moench][Gotthard] Writes "
"to an adc " "to an adc register in hex. Advanced user Function!"
"register in hex. Advanced user Function!"
<< '\n'; << '\n';
} else if (action == defs::GET_ACTION) { } else if (action == defs::GET_ACTION) {
throw sls::RuntimeError("Cannot get."); throw sls::RuntimeError("Cannot get.");

View File

@ -747,7 +747,6 @@ class CmdProxy {
/* Advanced */ /* Advanced */
{"copydetectorserver", "updatedetectorserver"}, {"copydetectorserver", "updatedetectorserver"},
/* Insignificant */ /* Insignificant */
{"nframes", "framecounter"}, {"nframes", "framecounter"},
{"now", "runtime"}, {"now", "runtime"},
@ -910,6 +909,8 @@ class CmdProxy {
{"rx_lastclient", &CmdProxy::rx_lastclient}, {"rx_lastclient", &CmdProxy::rx_lastclient},
{"rx_threads", &CmdProxy::rx_threads}, {"rx_threads", &CmdProxy::rx_threads},
{"rx_arping", &CmdProxy::rx_arping}, {"rx_arping", &CmdProxy::rx_arping},
{"rx_roi", &CmdProxy::Rx_ROI},
{"rx_clearroi", &CmdProxy::rx_clearroi},
/* File */ /* File */
{"fformat", &CmdProxy::fformat}, {"fformat", &CmdProxy::fformat},
@ -965,7 +966,7 @@ class CmdProxy {
/* Gotthard Specific */ /* Gotthard Specific */
{"roi", &CmdProxy::ROI}, {"roi", &CmdProxy::ROI},
{"clearroi", &CmdProxy::ClearROI}, {"clearroi", &CmdProxy::clearroi},
{"exptimel", &CmdProxy::exptimel}, {"exptimel", &CmdProxy::exptimel},
/* Gotthard2 Specific */ /* Gotthard2 Specific */
@ -1150,6 +1151,7 @@ class CmdProxy {
std::string UDPDestinationIP2(int action); std::string UDPDestinationIP2(int action);
/* Receiver Config */ /* Receiver Config */
std::string ReceiverHostname(int action); std::string ReceiverHostname(int action);
std::string Rx_ROI(int action);
/* File */ /* File */
/* ZMQ Streaming Parameters (Receiver<->Client) */ /* ZMQ Streaming Parameters (Receiver<->Client) */
std::string ZMQHWM(int action); std::string ZMQHWM(int action);
@ -1164,7 +1166,6 @@ class CmdProxy {
std::string TemperatureEvent(int action); std::string TemperatureEvent(int action);
/* Gotthard Specific */ /* Gotthard Specific */
std::string ROI(int action); std::string ROI(int action);
std::string ClearROI(int action);
/* Gotthard2 Specific */ /* Gotthard2 Specific */
std::string InjectChannel(int action); std::string InjectChannel(int action);
std::string VetoPhoton(int action); std::string VetoPhoton(int action);
@ -1766,6 +1767,11 @@ class CmdProxy {
"the interface it is " "the interface it is "
"listening to every minute. Useful in 10G mode."); "listening to every minute. Useful in 10G mode.");
EXECUTE_SET_COMMAND_NOID(
rx_clearroi, clearRxROI,
"Resets Region of interest in receiver. Default is all "
"channels/pixels enabled.");
/* File */ /* File */
INTEGER_COMMAND_VEC_ID( INTEGER_COMMAND_VEC_ID(
@ -2001,6 +2007,10 @@ class CmdProxy {
"[(optional unit) ns|us|ms|s]\n\t[Gotthard] Exposure time " "[(optional unit) ns|us|ms|s]\n\t[Gotthard] Exposure time "
"left for current frame. "); "left for current frame. ");
EXECUTE_SET_COMMAND(clearroi, clearROI,
"[Gotthard] Resets Region of interest in detector. All "
"channels enabled. Default is all channels enabled.");
/* Gotthard2 Specific */ /* Gotthard2 Specific */
INTEGER_COMMAND_SET_NOID_GET_ID( INTEGER_COMMAND_SET_NOID_GET_ID(
bursts, getNumberOfBursts, setNumberOfBursts, StringTo<int64_t>, bursts, getNumberOfBursts, setNumberOfBursts, StringTo<int64_t>,

View File

@ -38,7 +38,7 @@ void freeSharedMemory(int detectorIndex, int moduleIndex) {
if (detectorShm.exists()) { if (detectorShm.exists()) {
detectorShm.openSharedMemory(false); detectorShm.openSharedMemory(false);
numDetectors = detectorShm()->numberOfModules; numDetectors = detectorShm()->totalNumberOfModules;
detectorShm.removeSharedMemory(); detectorShm.removeSharedMemory();
} }
@ -1211,6 +1211,16 @@ void Detector::setRxArping(bool value, Positions pos) {
pimpl->Parallel(&Module::setRxArping, pos, value); pimpl->Parallel(&Module::setRxArping, pos, value);
} }
Result<defs::ROI> Detector::getIndividualRxROIs(Positions pos) const {
return pimpl->Parallel(&Module::getRxROI, pos);
}
defs::ROI Detector::getRxROI() const { return pimpl->getRxROI(); }
void Detector::setRxROI(const defs::ROI value) { pimpl->setRxROI(value); }
void Detector::clearRxROI() { pimpl->clearRxROI(); }
// File // File
Result<defs::fileFormat> Detector::getFileFormat(Positions pos) const { Result<defs::fileFormat> Detector::getFileFormat(Positions pos) const {
@ -1777,7 +1787,7 @@ Detector::getVetoAlgorithm(const defs::streamingInterface interface,
void Detector::setVetoAlgorithm(const defs::vetoAlgorithm alg, void Detector::setVetoAlgorithm(const defs::vetoAlgorithm alg,
defs::streamingInterface interface, defs::streamingInterface interface,
Positions pos) { Positions pos) {
LOG(logINFOBLUE) << "alg:" << ToString(alg) LOG(logDEBUG) << "alg:" << ToString(alg)
<< " interface:" << ToString(interface); << " interface:" << ToString(interface);
pimpl->Parallel(&Module::setVetoAlgorithm, pos, alg, interface); pimpl->Parallel(&Module::setVetoAlgorithm, pos, alg, interface);
} }

View File

@ -70,7 +70,7 @@ void DetectorImpl::freeSharedMemory(int detectorIndex, int detPos) {
if (detectorShm.exists()) { if (detectorShm.exists()) {
detectorShm.openSharedMemory(false); detectorShm.openSharedMemory(false);
numModules = detectorShm()->numberOfModules; numModules = detectorShm()->totalNumberOfModules;
detectorShm.removeSharedMemory(); detectorShm.removeSharedMemory();
} }
@ -161,10 +161,10 @@ void DetectorImpl::initSharedMemory(bool verify) {
void DetectorImpl::initializeDetectorStructure() { void DetectorImpl::initializeDetectorStructure() {
shm()->shmversion = DETECTOR_SHMVERSION; shm()->shmversion = DETECTOR_SHMVERSION;
shm()->numberOfModules = 0; shm()->totalNumberOfModules = 0;
shm()->detType = GENERIC; shm()->detType = GENERIC;
shm()->numberOfModule.x = 0; shm()->numberOfModules.x = 0;
shm()->numberOfModule.y = 0; shm()->numberOfModules.y = 0;
shm()->numberOfChannels.x = 0; shm()->numberOfChannels.x = 0;
shm()->numberOfChannels.y = 0; shm()->numberOfChannels.y = 0;
shm()->acquiringFlag = false; shm()->acquiringFlag = false;
@ -172,6 +172,10 @@ void DetectorImpl::initializeDetectorStructure() {
shm()->gapPixels = false; shm()->gapPixels = false;
// zmqlib default // zmqlib default
shm()->zmqHwm = -1; shm()->zmqHwm = -1;
shm()->rx_roi.xmin = -1;
shm()->rx_roi.xmax = -1;
shm()->rx_roi.ymin = -1;
shm()->rx_roi.ymax = -1;
} }
void DetectorImpl::initializeMembers(bool verify) { void DetectorImpl::initializeMembers(bool verify) {
@ -179,7 +183,7 @@ void DetectorImpl::initializeMembers(bool verify) {
zmqSocket.clear(); zmqSocket.clear();
// get objects from single det shared memory (open) // get objects from single det shared memory (open)
for (int i = 0; i < shm()->numberOfModules; i++) { for (int i = 0; i < shm()->totalNumberOfModules; i++) {
try { try {
modules.push_back( modules.push_back(
sls::make_unique<Module>(detectorIndex, i, verify)); sls::make_unique<Module>(detectorIndex, i, verify));
@ -246,7 +250,7 @@ void DetectorImpl::setVirtualDetectorServers(const int numdet, const int port) {
void DetectorImpl::setHostname(const std::vector<std::string> &name) { void DetectorImpl::setHostname(const std::vector<std::string> &name) {
// this check is there only to allow the previous detsizechan command // this check is there only to allow the previous detsizechan command
if (shm()->numberOfModules != 0) { if (shm()->totalNumberOfModules != 0) {
LOG(logWARNING) << "There are already module(s) in shared memory." LOG(logWARNING) << "There are already module(s) in shared memory."
"Freeing Shared memory now."; "Freeing Shared memory now.";
bool initialChecks = shm()->initialChecks; bool initialChecks = shm()->initialChecks;
@ -305,7 +309,7 @@ void DetectorImpl::addModule(const std::string &hostname) {
auto pos = modules.size(); auto pos = modules.size();
modules.emplace_back( modules.emplace_back(
sls::make_unique<Module>(type, detectorIndex, pos, false)); sls::make_unique<Module>(type, detectorIndex, pos, false));
shm()->numberOfModules = modules.size(); shm()->totalNumberOfModules = modules.size();
modules[pos]->setControlPort(port); modules[pos]->setControlPort(port);
modules[pos]->setStopPort(port + 1); modules[pos]->setStopPort(port + 1);
modules[pos]->setHostname(host, shm()->initialChecks); modules[pos]->setHostname(host, shm()->initialChecks);
@ -328,9 +332,8 @@ void DetectorImpl::addModule(const std::string &hostname) {
void DetectorImpl::updateDetectorSize() { void DetectorImpl::updateDetectorSize() {
LOG(logDEBUG) << "Updating Detector Size: " << size(); LOG(logDEBUG) << "Updating Detector Size: " << size();
const slsDetectorDefs::xy det_size = modules[0]->getNumberOfChannels(); const slsDetectorDefs::xy modSize = modules[0]->getNumberOfChannels();
if (modSize.x == 0 || modSize.y == 0) {
if (det_size.x == 0 || det_size.y == 0) {
throw sls::RuntimeError( throw sls::RuntimeError(
"Module size for x or y dimensions is 0. Unable to proceed in " "Module size for x or y dimensions is 0. Unable to proceed in "
"updating detector size. "); "updating detector size. ");
@ -338,39 +341,39 @@ void DetectorImpl::updateDetectorSize() {
int maxx = shm()->numberOfChannels.x; int maxx = shm()->numberOfChannels.x;
int maxy = shm()->numberOfChannels.y; int maxy = shm()->numberOfChannels.y;
int ndetx = 0, ndety = 0; int nModx = 0, nMody = 0;
// 1d, add modules along x axis // 1d, add modules along x axis
if (det_size.y == 1) { if (modSize.y == 1) {
if (maxx == 0) { if (maxx == 0) {
maxx = det_size.x * size(); maxx = modSize.x * size();
} }
ndetx = maxx / det_size.x; nModx = maxx / modSize.x;
ndety = size() / ndetx; nMody = size() / nModx;
if ((maxx % det_size.x) > 0) { if ((maxx % modSize.x) > 0) {
++ndety; ++nMody;
} }
} }
// 2d, add modules along y axis (due to eiger top/bottom) // 2d, add modules along y axis (due to eiger top/bottom)
else { else {
if (maxy == 0) { if (maxy == 0) {
maxy = det_size.y * size(); maxy = modSize.y * size();
} }
ndety = maxy / det_size.y; nMody = maxy / modSize.y;
ndetx = size() / ndety; nModx = size() / nMody;
if ((maxy % det_size.y) > 0) { if ((maxy % modSize.y) > 0) {
++ndetx; ++nModx;
} }
} }
shm()->numberOfModule.x = ndetx; shm()->numberOfModules.x = nModx;
shm()->numberOfModule.y = ndety; shm()->numberOfModules.y = nMody;
shm()->numberOfChannels.x = det_size.x * ndetx; shm()->numberOfChannels.x = modSize.x * nModx;
shm()->numberOfChannels.y = det_size.y * ndety; shm()->numberOfChannels.y = modSize.y * nMody;
LOG(logDEBUG) << "\n\tNumber of Modules in X direction:" LOG(logDEBUG) << "\n\tNumber of Modules in X direction:"
<< shm()->numberOfModule.x << shm()->numberOfModules.x
<< "\n\tNumber of Modules in Y direction:" << "\n\tNumber of Modules in Y direction:"
<< shm()->numberOfModule.y << shm()->numberOfModules.y
<< "\n\tNumber of Channels in X direction:" << "\n\tNumber of Channels in X direction:"
<< shm()->numberOfChannels.x << shm()->numberOfChannels.x
<< "\n\tNumber of Channels in Y direction:" << "\n\tNumber of Channels in Y direction:"
@ -378,7 +381,7 @@ void DetectorImpl::updateDetectorSize() {
for (auto &module : modules) { for (auto &module : modules) {
if (module->getUpdateMode() == 0) { if (module->getUpdateMode() == 0) {
module->updateNumberOfModule(shm()->numberOfModule); module->updateNumberOfModule(shm()->numberOfModules);
} }
} }
} }
@ -386,7 +389,7 @@ void DetectorImpl::updateDetectorSize() {
int DetectorImpl::size() const { return modules.size(); } int DetectorImpl::size() const { return modules.size(); }
slsDetectorDefs::xy DetectorImpl::getNumberOfModules() const { slsDetectorDefs::xy DetectorImpl::getNumberOfModules() const {
return shm()->numberOfModule; return shm()->numberOfModules;
} }
slsDetectorDefs::xy DetectorImpl::getNumberOfChannels() const { slsDetectorDefs::xy DetectorImpl::getNumberOfChannels() const {
@ -412,7 +415,7 @@ void DetectorImpl::setGapPixelsinCallback(const bool enable) {
if (size() && modules[0]->getQuad()) { if (size() && modules[0]->getQuad()) {
break; break;
} }
if (shm()->numberOfModule.y % 2 != 0) { if (shm()->numberOfModules.y % 2 != 0) {
throw RuntimeError("Gap pixels can only be used " throw RuntimeError("Gap pixels can only be used "
"for full modules."); "for full modules.");
} }
@ -495,6 +498,7 @@ void DetectorImpl::readFrameFromReceiver() {
bool quadEnable = false; bool quadEnable = false;
// to flip image // to flip image
bool eiger = false; bool eiger = false;
std::array<int, 4> rxRoi = shm()->rx_roi.getIntArray();
std::vector<bool> runningList(zmqSocket.size()); std::vector<bool> runningList(zmqSocket.size());
std::vector<bool> connectList(zmqSocket.size()); std::vector<bool> connectList(zmqSocket.size());
@ -571,7 +575,7 @@ void DetectorImpl::readFrameFromReceiver() {
// shape // shape
nPixelsX = zHeader.npixelsx; nPixelsX = zHeader.npixelsx;
nPixelsY = zHeader.npixelsy; nPixelsY = zHeader.npixelsy;
// module shape (port) // port geometry
nX = zHeader.ndetx; nX = zHeader.ndetx;
nY = zHeader.ndety; nY = zHeader.ndety;
nDetPixelsX = nX * nPixelsX; nDetPixelsX = nX * nPixelsX;
@ -668,6 +672,7 @@ void DetectorImpl::readFrameFromReceiver() {
<< "\n\t databytes: " << multisize << "\n\t databytes: " << multisize
<< "\n\t dynamicRange: " << dynamicRange; << "\n\t dynamicRange: " << dynamicRange;
// send data to callback // send data to callback
if (data) { if (data) {
char *callbackImage = multiframe.get(); char *callbackImage = multiframe.get();
@ -691,7 +696,7 @@ void DetectorImpl::readFrameFromReceiver() {
thisData = new detectorData(currentProgress, currentFileName, thisData = new detectorData(currentProgress, currentFileName,
nDetActualPixelsX, nDetActualPixelsY, nDetActualPixelsX, nDetActualPixelsY,
callbackImage, imagesize, dynamicRange, callbackImage, imagesize, dynamicRange,
currentFileIndex, completeImage); currentFileIndex, completeImage, rxRoi);
try { try {
dataReady( dataReady(
thisData, currentFrameIndex, thisData, currentFrameIndex,
@ -1094,9 +1099,6 @@ int DetectorImpl::acquire() {
return FAIL; return FAIL;
} }
// We need this to handle Mythen3 synchronization
auto detector_type = Parallel(&Module::getDetectorType, {}).squash();
try { try {
struct timespec begin, end; struct timespec begin, end;
clock_gettime(CLOCK_REALTIME, &begin); clock_gettime(CLOCK_REALTIME, &begin);
@ -1174,6 +1176,7 @@ int DetectorImpl::acquire() {
} }
void DetectorImpl::startAcquisition(bool blocking, std::vector<int> positions) { void DetectorImpl::startAcquisition(bool blocking, std::vector<int> positions) {
// handle Mythen3 synchronization
if (shm()->detType == defs::MYTHEN3 && size() > 1) { if (shm()->detType == defs::MYTHEN3 && size() > 1) {
std::vector<int> master; std::vector<int> master;
std::vector<int> slaves; std::vector<int> slaves;
@ -1425,6 +1428,218 @@ void DetectorImpl::setDefaultDac(defs::dacIndex index, int defaultValue,
Parallel(&Module::setDefaultDac, pos, index, defaultValue, sett); Parallel(&Module::setDefaultDac, pos, index, defaultValue, sett);
} }
defs::xy DetectorImpl::getPortGeometry() const {
defs::xy portGeometry(1, 1);
switch (shm()->detType) {
case EIGER:
portGeometry.x = modules[0]->getNumberofUDPInterfacesFromShm();
break;
case JUNGFRAU:
portGeometry.y = modules[0]->getNumberofUDPInterfacesFromShm();
break;
default:
break;
}
return portGeometry;
}
defs::xy DetectorImpl::calculatePosition(int moduleIndex,
defs::xy geometry) const {
defs::xy pos{};
int maxYMods = shm()->numberOfModules.y;
pos.y = (moduleIndex % maxYMods) * geometry.y;
pos.x = (moduleIndex / maxYMods) * geometry.x;
return pos;
}
defs::ROI DetectorImpl::getRxROI() const {
if (shm()->detType == CHIPTESTBOARD || shm()->detType == MOENCH) {
throw RuntimeError("RxRoi not implemented for this Detector");
}
if (modules.size() == 0) {
throw RuntimeError("No Modules added");
}
// complete detector in roi
auto t = Parallel(&Module::getRxROI, {});
if (t.equal() && t.front().completeRoi()) {
LOG(logDEBUG) << "no roi";
return defs::ROI (0, shm()->numberOfChannels.x - 1, 0, shm()->numberOfChannels.y - 1);
}
defs::xy numChansPerMod = modules[0]->getNumberOfChannels();
bool is2D = (numChansPerMod.y > 1 ? true : false);
defs::xy geometry = getPortGeometry();
defs::ROI retval{};
for (size_t iModule = 0; iModule != modules.size(); ++iModule) {
defs::ROI moduleRoi = modules[iModule]->getRxROI();
if (moduleRoi.noRoi()) {
LOG(logDEBUG) << iModule << ": no roi";
} else {
// expand complete roi
if (moduleRoi.completeRoi()) {
moduleRoi.xmin = 0;
moduleRoi.xmax = numChansPerMod.x;
if (is2D) {
moduleRoi.ymin = 0;
moduleRoi.ymax = numChansPerMod.y;
}
}
LOG(logDEBUG) << iModule << ": " << moduleRoi;
// get roi at detector level
defs::xy pos = calculatePosition(iModule, geometry);
defs::ROI moduleFullRoi{};
moduleFullRoi.xmin = numChansPerMod.x * pos.x + moduleRoi.xmin;
moduleFullRoi.xmax = numChansPerMod.x * pos.x + moduleRoi.xmax;
if (is2D) {
moduleFullRoi.ymin = numChansPerMod.y * pos.y + moduleRoi.ymin;
moduleFullRoi.ymax = numChansPerMod.y * pos.y + moduleRoi.ymax;
}
LOG(logDEBUG) << iModule << ": (full roi)" << moduleFullRoi;
// get min and max
if (retval.xmin == -1 || moduleFullRoi.xmin < retval.xmin) {
LOG(logDEBUG) << iModule << ": xmin updated";
retval.xmin = moduleFullRoi.xmin;
}
if (retval.xmax == -1 || moduleFullRoi.xmax > retval.xmax) {
LOG(logDEBUG) << iModule << ": xmax updated";
retval.xmax = moduleFullRoi.xmax;
}
if (retval.ymin == -1 || moduleFullRoi.ymin < retval.ymin) {
LOG(logDEBUG) << iModule << ": ymin updated";
retval.ymin = moduleFullRoi.ymin;
}
if (retval.ymax == -1 || moduleFullRoi.ymax > retval.ymax) {
LOG(logDEBUG) << iModule << ": ymax updated";
retval.ymax = moduleFullRoi.ymax;
}
}
LOG(logDEBUG) << iModule << ": (retval): " << retval;
}
if (retval.ymin == -1) {
retval.ymin = 0;
retval.ymax = 0;
}
return retval;
}
void DetectorImpl::setRxROI(const defs::ROI arg) {
if (shm()->detType == CHIPTESTBOARD || shm()->detType == MOENCH) {
throw RuntimeError("RxRoi not implemented for this Detector");
}
if (modules.size() == 0) {
throw RuntimeError("No Modules added");
}
if (arg.noRoi()) {
throw RuntimeError("Invalid Roi of size 0.");
}
if (arg.completeRoi()) {
throw RuntimeError("Did you mean the clear roi command (API: clearRxROI, cmd: rx_clearroi)?");
}
if (arg.xmin > arg.xmax || arg.ymin > arg.ymax) {
throw RuntimeError("Invalid Receiver Roi. xmin/ymin exceeds xmax/ymax.");
}
defs::xy numChansPerMod = modules[0]->getNumberOfChannels();
bool is2D = (numChansPerMod.y > 1 ? true : false);
defs::xy geometry = getPortGeometry();
if (!is2D && ((arg.ymin != -1 && arg.ymin != 0) || (arg.ymax != -1 && arg.ymax != 0))) {
throw RuntimeError("Invalid Receiver roi. Cannot set 2d roi for a 1d detector.");
}
if (arg.xmin < 0 || arg.xmax >= shm()->numberOfChannels.x || (is2D && (arg.ymin < 0 || arg.ymax >= shm()->numberOfChannels.y))) {
throw RuntimeError("Invalid Receiver Roi. Outside detector range.");
}
for (size_t iModule = 0; iModule != modules.size(); ++iModule) {
// default init = complete roi
defs::ROI moduleRoi{};
// incomplete roi
if (!arg.completeRoi()) {
// multi module Gotthard2
if (shm()->detType == GOTTHARD2 && size() > 1) {
moduleRoi.xmin = arg.xmin / 2;
moduleRoi.xmax = arg.xmax / 2;
if (iModule == 0) {
// all should be even
if (arg.xmin % 2 != 0) {
++moduleRoi.xmin;
}
} else if (iModule == 1) {
// all should be odd
if (arg.xmax % 2 == 0) {
--moduleRoi.xmax;
}
} else {
throw RuntimeError("Cannot have more than 2 modules for a Gotthard2 detector");
}
} else {
// get module limits
defs::xy pos = calculatePosition(iModule, geometry);
defs::ROI moduleFullRoi{};
moduleFullRoi.xmin = numChansPerMod.x * pos.x;
moduleFullRoi.xmax = numChansPerMod.x * (pos.x + 1) - 1;
if (is2D) {
moduleFullRoi.ymin = numChansPerMod.y * pos.y;
moduleFullRoi.ymax = numChansPerMod.y * (pos.y + 1) - 1;
}
// no roi
if (arg.xmin > moduleFullRoi.xmax ||
arg.xmax < moduleFullRoi.xmin ||
(is2D && (arg.ymin > moduleFullRoi.ymax ||
arg.ymax < moduleFullRoi.ymin))) {
moduleRoi.setNoRoi();
}
// incomplete module roi
else if (arg.xmin > moduleFullRoi.xmin ||
arg.xmax < moduleFullRoi.xmax ||
(is2D && (arg.ymin > moduleFullRoi.ymin ||
arg.ymax < moduleFullRoi.ymax))) {
moduleRoi.xmin = (arg.xmin <= moduleFullRoi.xmin)
? 0
: (arg.xmin % numChansPerMod.x);
moduleRoi.xmax = (arg.xmax >= moduleFullRoi.xmax)
? numChansPerMod.x - 1
: (arg.xmax % numChansPerMod.x);
if (is2D) {
moduleRoi.ymin = (arg.ymin <= moduleFullRoi.ymin)
? 0
: (arg.ymin % numChansPerMod.y);
moduleRoi.ymax = (arg.ymax >= moduleFullRoi.ymax)
? numChansPerMod.y - 1
: (arg.ymax % numChansPerMod.y);
}
}
}
}
modules[iModule]->setRxROI(moduleRoi);
}
// updating shm rx_roi for gui purposes
shm()->rx_roi = arg;
// metadata
if (arg.completeRoi()) {
modules[0]->setRxROIMetadata(defs::ROI (0, shm()->numberOfChannels.x - 1, 0, shm()->numberOfChannels.y - 1));
} else {
modules[0]->setRxROIMetadata(arg);
}
}
void DetectorImpl::clearRxROI() {
Parallel(&Module::setRxROI, {}, defs::ROI{});
shm()->rx_roi.xmin = -1;
shm()->rx_roi.ymin = -1;
shm()->rx_roi.xmax = -1;
shm()->rx_roi.ymax = -1;
}
std::vector<std::string> DetectorImpl::getCtbDacNames() const { std::vector<std::string> DetectorImpl::getCtbDacNames() const {
return ctb_shm()->getDacNames(); return ctb_shm()->getDacNames();
} }

View File

@ -7,7 +7,6 @@
#include "sls/logger.h" #include "sls/logger.h"
#include "sls/sls_detector_defs.h" #include "sls/sls_detector_defs.h"
#include "CtbConfig.h" #include "CtbConfig.h"
class ZmqSocket; class ZmqSocket;
class detectorData; class detectorData;
@ -20,7 +19,7 @@ class detectorData;
#include <vector> #include <vector>
#define DETECTOR_SHMAPIVERSION 0x190809 #define DETECTOR_SHMAPIVERSION 0x190809
#define DETECTOR_SHMVERSION 0x201007 #define DETECTOR_SHMVERSION 0x220505
#define SHORT_STRING_LENGTH 50 #define SHORT_STRING_LENGTH 50
#include <future> #include <future>
@ -51,14 +50,14 @@ struct sharedDetector {
/** last time stamp when accessing the shared memory */ /** last time stamp when accessing the shared memory */
char lastDate[SHORT_STRING_LENGTH]; char lastDate[SHORT_STRING_LENGTH];
int numberOfModules; int totalNumberOfModules;
slsDetectorDefs::detectorType detType; slsDetectorDefs::detectorType detType;
/** END OF FIXED PATTERN /** END OF FIXED PATTERN
* -----------------------------------------------*/ * -----------------------------------------------*/
/** Number of modules operated at once */ /** Number of modules operated at once */
slsDetectorDefs::xy numberOfModule; slsDetectorDefs::xy numberOfModules;
/** max number of channels for complete detector*/ /** max number of channels for complete detector*/
slsDetectorDefs::xy numberOfChannels; slsDetectorDefs::xy numberOfChannels;
@ -68,6 +67,8 @@ struct sharedDetector {
bool gapPixels; bool gapPixels;
/** high water mark of listening tcp port (only data) */ /** high water mark of listening tcp port (only data) */
int zmqHwm; int zmqHwm;
/** in shm for gui purposes */
defs::ROI rx_roi{};
}; };
class DetectorImpl : public virtual slsDetectorDefs { class DetectorImpl : public virtual slsDetectorDefs {
@ -302,7 +303,9 @@ class DetectorImpl : public virtual slsDetectorDefs {
Positions pos = {}); Positions pos = {});
void setDefaultDac(defs::dacIndex index, int defaultValue, void setDefaultDac(defs::dacIndex index, int defaultValue,
defs::detectorSettings sett, Positions pos); defs::detectorSettings sett, Positions pos);
defs::ROI getRxROI() const;
void setRxROI(const defs::ROI arg);
void clearRxROI();
std::vector<std::string> getCtbDacNames() const; std::vector<std::string> getCtbDacNames() const;
std::string getCtbDacName(defs::dacIndex i) const; std::string getCtbDacName(defs::dacIndex i) const;
@ -389,6 +392,9 @@ class DetectorImpl : public virtual slsDetectorDefs {
*/ */
int kbhit(); int kbhit();
defs::xy getPortGeometry() const;
defs::xy calculatePosition(int moduleIndex, defs::xy geometry) const;
const int detectorIndex{0}; const int detectorIndex{0};
sls::SharedMemory<sharedDetector> shm{0, -1}; sls::SharedMemory<sharedDetector> shm{0, -1};
sls::SharedMemory<CtbConfig> ctb_shm{0, -1, CtbConfig::shm_tag()}; sls::SharedMemory<CtbConfig> ctb_shm{0, -1, CtbConfig::shm_tag()};

View File

@ -1410,6 +1410,19 @@ void Module::setRxArping(bool enable) {
sendToReceiver(F_SET_RECEIVER_ARPING, static_cast<int>(enable), nullptr); sendToReceiver(F_SET_RECEIVER_ARPING, static_cast<int>(enable), nullptr);
} }
defs::ROI Module::getRxROI() const {
return sendToReceiver<slsDetectorDefs::ROI>(F_RECEIVER_GET_RECEIVER_ROI);
}
void Module::setRxROI(const slsDetectorDefs::ROI arg) {
LOG(logDEBUG) << moduleIndex << ": " << arg;
sendToReceiver(F_RECEIVER_SET_RECEIVER_ROI, arg, nullptr);
}
void Module::setRxROIMetadata(const slsDetectorDefs::ROI arg) {
sendToReceiver(F_RECEIVER_SET_RECEIVER_ROI_METADATA, arg, nullptr);
}
// File // File
slsDetectorDefs::fileFormat Module::getFileFormat() const { slsDetectorDefs::fileFormat Module::getFileFormat() const {
return sendToReceiver<fileFormat>(F_GET_RECEIVER_FILE_FORMAT); return sendToReceiver<fileFormat>(F_GET_RECEIVER_FILE_FORMAT);
@ -1837,7 +1850,7 @@ void Module::setROI(slsDetectorDefs::ROI arg) {
} }
sendToDetector(F_SET_ROI, arg, nullptr); sendToDetector(F_SET_ROI, arg, nullptr);
if (shm()->useReceiverFlag) { if (shm()->useReceiverFlag) {
sendToReceiver(F_RECEIVER_SET_ROI, arg, nullptr); sendToReceiver(F_RECEIVER_SET_DETECTOR_ROI, arg, nullptr);
} }
} }

View File

@ -290,6 +290,9 @@ class Module : public virtual slsDetectorDefs {
std::array<pid_t, NUM_RX_THREAD_IDS> getReceiverThreadIds() const; std::array<pid_t, NUM_RX_THREAD_IDS> getReceiverThreadIds() const;
bool getRxArping() const; bool getRxArping() const;
void setRxArping(bool enable); void setRxArping(bool enable);
defs::ROI getRxROI() const;
void setRxROI(const slsDetectorDefs::ROI arg);
void setRxROIMetadata(const slsDetectorDefs::ROI arg);
/************************************************** /**************************************************
* * * *

View File

@ -440,6 +440,79 @@ TEST_CASE("rx_arping", "[.cmd][.rx]") {
} }
} }
TEST_CASE("rx_roi", "[.cmd]") {
Detector det;
CmdProxy proxy(&det);
auto det_type = det.getDetectorType().squash();
if (det_type == defs::CHIPTESTBOARD || det_type == defs::MOENCH) {
REQUIRE_THROWS(proxy.Call("rx_roi", {"5", "10"}, -1, PUT));
} else {
auto prev_val = det.getRxROI();
defs::xy detsize = det.getDetectrSize();
// 1d
if (det_type == defs::GOTTHARD || det_type == defs::GOTTHARD2 ||
det_type == defs::MYTHEN3) {
{
std::ostringstream oss;
proxy.Call("rx_roi", {"5", "10"}, -1, PUT, oss);
REQUIRE(oss.str() == "rx_roi [5, 10]\n");
}
{
std::ostringstream oss;
proxy.Call("rx_roi", {"10", "15"}, -1, PUT, oss);
REQUIRE(oss.str() == "rx_roi [10, 15]\n");
}
REQUIRE_THROWS(proxy.Call("rx_roi", {"-1", "-1"}, -1, PUT));
REQUIRE_THROWS(proxy.Call("rx_roi", {"10", "15", "25", "30"}, -1, PUT));
}
// 2d
else {
{
std::ostringstream oss;
proxy.Call("rx_roi", {"10", "15", "1", "5"}, -1, PUT, oss);
REQUIRE(oss.str() == "rx_roi [10, 15, 1, 5]\n");
}
{
std::ostringstream oss;
proxy.Call("rx_roi", {"10", "22", "18", "19"}, -1, PUT, oss);
REQUIRE(oss.str() == "rx_roi [10, 22, 18, 19]\n");
}
{
std::ostringstream oss;
proxy.Call("rx_roi", {"1", std::to_string(detsize.x - 5), "1", std::to_string(detsize.y - 5)}, -1, PUT, oss);
REQUIRE(oss.str() == std::string("rx_roi [1, ") + std::to_string(detsize.x - 5) + std::string(", ") + std::to_string(detsize.y - 5) + std::string(", 1]\n"));
}
REQUIRE_THROWS(proxy.Call("rx_roi", {"-1", "-1", "-1", "-1"}, -1, PUT));
}
for (int i = 0; i != det.size(); ++i) {
det.setRxROI(prev_val);
}
}
}
TEST_CASE("rx_clearroi", "[.cmd]") {
Detector det;
CmdProxy proxy(&det);
auto det_type = det.getDetectorType().squash();
if (det_type == defs::CHIPTESTBOARD || det_type == defs::MOENCH) {
REQUIRE_THROWS(proxy.Call("rx_clearroi", {}, -1, PUT));
} else {
auto prev_val = det.getRxROI();
{
std::ostringstream oss;
proxy.Call("rx_clearroi", {}, -1, PUT, oss);
REQUIRE(oss.str() == "rx_clearroi successful\n");
}
for (int i = 0; i != det.size(); ++i) {
det.setRxROI(prev_val);
}
}
}
/* File */ /* File */
TEST_CASE("fformat", "[.cmd]") { TEST_CASE("fformat", "[.cmd]") {

View File

@ -55,7 +55,8 @@ int64_t ClientInterface::getReceiverVersion() { return APIRECEIVER; }
/***callback functions***/ /***callback functions***/
void ClientInterface::registerCallBackStartAcquisition( void ClientInterface::registerCallBackStartAcquisition(
int (*func)(const std::string &, const std::string &, uint64_t, size_t, void *), int (*func)(const std::string &, const std::string &, uint64_t, size_t,
void *),
void *arg) { void *arg) {
startAcquisitionCallBack = func; startAcquisitionCallBack = func;
pStartAcquisition = arg; pStartAcquisition = arg;
@ -122,7 +123,7 @@ int ClientInterface::functionTable(){
flist[F_GET_LAST_RECEIVER_CLIENT_IP] = &ClientInterface::get_last_client_ip; flist[F_GET_LAST_RECEIVER_CLIENT_IP] = &ClientInterface::get_last_client_ip;
flist[F_GET_RECEIVER_VERSION] = &ClientInterface::get_version; flist[F_GET_RECEIVER_VERSION] = &ClientInterface::get_version;
flist[F_SETUP_RECEIVER] = &ClientInterface::setup_receiver; flist[F_SETUP_RECEIVER] = &ClientInterface::setup_receiver;
flist[F_RECEIVER_SET_ROI] = &ClientInterface::set_roi; flist[F_RECEIVER_SET_DETECTOR_ROI] = &ClientInterface::set_detector_roi;
flist[F_RECEIVER_SET_NUM_FRAMES] = &ClientInterface::set_num_frames; flist[F_RECEIVER_SET_NUM_FRAMES] = &ClientInterface::set_num_frames;
flist[F_SET_RECEIVER_NUM_TRIGGERS] = &ClientInterface::set_num_triggers; flist[F_SET_RECEIVER_NUM_TRIGGERS] = &ClientInterface::set_num_triggers;
flist[F_SET_RECEIVER_NUM_BURSTS] = &ClientInterface::set_num_bursts; flist[F_SET_RECEIVER_NUM_BURSTS] = &ClientInterface::set_num_bursts;
@ -217,6 +218,9 @@ int ClientInterface::functionTable(){
flist[F_RECEIVER_SET_DATASTREAM] = &ClientInterface::set_detector_datastream; flist[F_RECEIVER_SET_DATASTREAM] = &ClientInterface::set_detector_datastream;
flist[F_GET_RECEIVER_ARPING] = &ClientInterface::get_arping; flist[F_GET_RECEIVER_ARPING] = &ClientInterface::get_arping;
flist[F_SET_RECEIVER_ARPING] = &ClientInterface::set_arping; flist[F_SET_RECEIVER_ARPING] = &ClientInterface::set_arping;
flist[F_RECEIVER_GET_RECEIVER_ROI] = &ClientInterface::get_receiver_roi;
flist[F_RECEIVER_SET_RECEIVER_ROI] = &ClientInterface::set_receiver_roi;
flist[F_RECEIVER_SET_RECEIVER_ROI_METADATA] = &ClientInterface::set_receiver_roi_metadata;
for (int i = NUM_DET_FUNCTIONS + 1; i < NUM_REC_FUNCTIONS ; i++) { for (int i = NUM_DET_FUNCTIONS + 1; i < NUM_REC_FUNCTIONS ; i++) {
LOG(logDEBUG1) << "function fnum: " << i << " (" << LOG(logDEBUG1) << "function fnum: " << i << " (" <<
@ -247,7 +251,7 @@ int ClientInterface::decodeFunction(Interface &socket) {
void ClientInterface::functionNotImplemented() { void ClientInterface::functionNotImplemented() {
std::ostringstream os; std::ostringstream os;
os << "Function: " << getFunctionNameFromEnum((enum detFuncs)fnum) os << "Function: " << getFunctionNameFromEnum((enum detFuncs)fnum)
<< ", is is not implemented for this detector"; << " is not implemented for this detector";
throw RuntimeError(os.str()); throw RuntimeError(os.str());
} }
@ -455,7 +459,7 @@ int ClientInterface::setup_receiver(Interface &socket) {
} }
if (detType == GOTTHARD) { if (detType == GOTTHARD) {
try { try {
impl()->setROI(arg.roi); impl()->setDetectorROI(arg.roi);
} catch (const RuntimeError &e) { } catch (const RuntimeError &e) {
throw RuntimeError("Could not set ROI"); throw RuntimeError("Could not set ROI");
} }
@ -497,8 +501,11 @@ void ClientInterface::setDetectorType(detectorType arg) {
detType = GENERIC; detType = GENERIC;
receiver = sls::make_unique<Implementation>(arg); receiver = sls::make_unique<Implementation>(arg);
detType = arg; detType = arg;
} catch (...) { } catch (std::exception &e) {
throw RuntimeError("Could not set detector type"); std::ostringstream os;
os << "Could not set detector type in the receiver. ";
os << e.what();
throw RuntimeError(os.str());
} }
// callbacks after (in setdetectortype, the object is reinitialized) // callbacks after (in setdetectortype, the object is reinitialized)
@ -518,16 +525,16 @@ void ClientInterface::setDetectorType(detectorType arg) {
impl()->setThreadIds(parentThreadId, tcpThreadId); impl()->setThreadIds(parentThreadId, tcpThreadId);
} }
int ClientInterface::set_roi(Interface &socket) { int ClientInterface::set_detector_roi(Interface &socket) {
auto arg = socket.Receive<ROI>(); auto arg = socket.Receive<ROI>();
LOG(logDEBUG1) << "Set ROI: [" << arg.xmin << ", " << arg.xmax << "]"; LOG(logDEBUG1) << "Set Detector ROI: " << sls::ToString(arg);
if (detType != GOTTHARD) if (detType != GOTTHARD)
functionNotImplemented(); functionNotImplemented();
verifyIdle(socket); verifyIdle(socket);
try { try {
impl()->setROI(arg); impl()->setDetectorROI(arg);
} catch (const RuntimeError &e) { } catch (const RuntimeError &e) {
throw RuntimeError("Could not set ROI"); throw RuntimeError("Could not set ROI");
} }
@ -1736,3 +1743,37 @@ int ClientInterface::set_arping(Interface &socket) {
impl()->setArping(value, udpips); impl()->setArping(value, udpips);
return socket.Send(OK); return socket.Send(OK);
} }
int ClientInterface::get_receiver_roi(Interface &socket) {
auto retval = impl()->getReceiverROI();
LOG(logDEBUG1) << "Receiver roi retval:" << sls::ToString(retval);
return socket.sendResult(retval);
}
int ClientInterface::set_receiver_roi(Interface &socket) {
auto arg = socket.Receive<ROI>();
if (detType == CHIPTESTBOARD || detType == MOENCH)
functionNotImplemented();
LOG(logDEBUG1) << "Set Receiver ROI: " << sls::ToString(arg);
verifyIdle(socket);
try {
impl()->setReceiverROI(arg);
} catch (const RuntimeError &e) {
throw RuntimeError("Could not set ReceiverROI");
}
return socket.Send(OK);
}
int ClientInterface::set_receiver_roi_metadata(Interface &socket) {
auto arg = socket.Receive<ROI>();
if (detType == CHIPTESTBOARD || detType == MOENCH)
functionNotImplemented();
LOG(logDEBUG1) << "Set Receiver ROI Metadata: " << sls::ToString(arg);
verifyIdle(socket);
try {
impl()->setReceiverROIMetadata(arg);
} catch (const RuntimeError &e) {
throw RuntimeError("Could not set ReceiverROI metadata");
}
return socket.Send(OK);
}

View File

@ -66,7 +66,7 @@ class ClientInterface : private virtual slsDetectorDefs {
int get_version(sls::ServerInterface &socket); int get_version(sls::ServerInterface &socket);
int setup_receiver(sls::ServerInterface &socket); int setup_receiver(sls::ServerInterface &socket);
void setDetectorType(detectorType arg); void setDetectorType(detectorType arg);
int set_roi(sls::ServerInterface &socket); int set_detector_roi(sls::ServerInterface &socket);
int set_num_frames(sls::ServerInterface &socket); int set_num_frames(sls::ServerInterface &socket);
int set_num_triggers(sls::ServerInterface &socket); int set_num_triggers(sls::ServerInterface &socket);
int set_num_bursts(sls::ServerInterface &socket); int set_num_bursts(sls::ServerInterface &socket);
@ -164,6 +164,9 @@ class ClientInterface : private virtual slsDetectorDefs {
int set_detector_datastream(sls::ServerInterface &socket); int set_detector_datastream(sls::ServerInterface &socket);
int get_arping(sls::ServerInterface &socket); int get_arping(sls::ServerInterface &socket);
int set_arping(sls::ServerInterface &socket); int set_arping(sls::ServerInterface &socket);
int get_receiver_roi(sls::ServerInterface &socket);
int set_receiver_roi(sls::ServerInterface &socket);
int set_receiver_roi_metadata(sls::ServerInterface &socket);
Implementation *impl() { Implementation *impl() {
if (receiver != nullptr) { if (receiver != nullptr) {

View File

@ -27,19 +27,19 @@
const std::string DataProcessor::typeName_ = "DataProcessor"; const std::string DataProcessor::typeName_ = "DataProcessor";
DataProcessor::DataProcessor(int index, detectorType detectorType, Fifo *fifo, DataProcessor::DataProcessor(int index, detectorType detectorType, Fifo *fifo,
bool *activated, bool *dataStreamEnable, bool *dataStreamEnable,
uint32_t *streamingFrequency, uint32_t *streamingFrequency,
uint32_t *streamingTimerInMs, uint32_t *streamingTimerInMs,
uint32_t *streamingStartFnum, bool *framePadding, uint32_t *streamingStartFnum, bool *framePadding,
std::vector<int> *ctbDbitList, int *ctbDbitOffset, std::vector<int> *ctbDbitList, int *ctbDbitOffset,
int *ctbAnalogDataBytes) int *ctbAnalogDataBytes)
: ThreadObject(index, typeName_), fifo_(fifo), detectorType_(detectorType), : ThreadObject(index, typeName_), fifo_(fifo), detectorType_(detectorType),
dataStreamEnable_(dataStreamEnable), activated_(activated), dataStreamEnable_(dataStreamEnable),
streamingFrequency_(streamingFrequency), streamingFrequency_(streamingFrequency),
streamingTimerInMs_(streamingTimerInMs), streamingTimerInMs_(streamingTimerInMs),
streamingStartFnum_(streamingStartFnum), framePadding_(framePadding), streamingStartFnum_(streamingStartFnum), framePadding_(framePadding),
ctbDbitList_(ctbDbitList), ctbDbitOffset_(ctbDbitOffset), ctbDbitList_(ctbDbitList), ctbDbitOffset_(ctbDbitOffset),
ctbAnalogDataBytes_(ctbAnalogDataBytes), firstStreamerFrame_(false) { ctbAnalogDataBytes_(ctbAnalogDataBytes) {
LOG(logDEBUG) << "DataProcessor " << index << " created"; LOG(logDEBUG) << "DataProcessor " << index << " created";
} }
@ -50,6 +50,13 @@ bool DataProcessor::GetStartedFlag() const { return startedFlag_; }
void DataProcessor::SetFifo(Fifo *fifo) { fifo_ = fifo; } void DataProcessor::SetFifo(Fifo *fifo) { fifo_ = fifo; }
void DataProcessor::SetActivate(bool enable) { activated_ = enable; }
void DataProcessor::SetReceiverROI(ROI roi) {
receiverRoi_ = roi;
receiverRoiEnabled_ = receiverRoi_.completeRoi() ? false : true;
}
void DataProcessor::ResetParametersforNewAcquisition() { void DataProcessor::ResetParametersforNewAcquisition() {
StopRunning(); StopRunning();
startedFlag_ = false; startedFlag_ = false;
@ -57,6 +64,8 @@ void DataProcessor::ResetParametersforNewAcquisition() {
firstIndex_ = 0; firstIndex_ = 0;
currentFrameIndex_ = 0; currentFrameIndex_ = 0;
firstStreamerFrame_ = true; firstStreamerFrame_ = true;
streamCurrentFrame_ = false;
completeImageToStreamBeforeCropping = sls::make_unique<char[]>(generalData_->imageSize);
} }
void DataProcessor::RecordFirstIndex(uint64_t fnum) { void DataProcessor::RecordFirstIndex(uint64_t fnum) {
@ -115,18 +124,28 @@ void DataProcessor::CreateFirstFiles(
CloseFiles(); CloseFiles();
// deactivated (half module/ single port), dont write file // deactivated (half module/ single port), dont write file
if ((!*activated_) || (!detectorDataStream)) { if (!activated_ || !detectorDataStream) {
return; return;
} }
#ifdef HDF5C
int nx = generalData_->nPixelsX;
int ny = generalData_->nPixelsY;
if (receiverRoiEnabled_) {
nx = receiverRoi_.xmax - receiverRoi_.xmin + 1;
ny = receiverRoi_.ymax - receiverRoi_.ymin + 1;
if (receiverRoi_.ymax == -1 || receiverRoi_.ymin == -1) {
ny = 1;
}
}
#endif
switch (dataFile_->GetFileFormat()) { switch (dataFile_->GetFileFormat()) {
#ifdef HDF5C #ifdef HDF5C
case HDF5: case HDF5:
dataFile_->CreateFirstHDF5DataFile( dataFile_->CreateFirstHDF5DataFile(
filePath, fileNamePrefix, fileIndex, overWriteEnable, silentMode, filePath, fileNamePrefix, fileIndex, overWriteEnable, silentMode,
modulePos, numUnitsPerReadout, udpPortNumber, maxFramesPerFile, modulePos, numUnitsPerReadout, udpPortNumber, maxFramesPerFile,
numImages, generalData_->nPixelsX, generalData_->nPixelsY, numImages, nx, ny, dynamicRange);
dynamicRange);
break; break;
#endif #endif
case BINARY: case BINARY:
@ -156,6 +175,10 @@ std::array<std::string, 2> DataProcessor::CreateVirtualFile(
const int numModX, const int numModY, const uint32_t dynamicRange, const int numModX, const int numModY, const uint32_t dynamicRange,
std::mutex *hdf5LibMutex) { std::mutex *hdf5LibMutex) {
if (receiverRoiEnabled_) {
throw std::runtime_error("Skipping virtual hdf5 file since rx_roi is enabled.");
}
bool gotthard25um = bool gotthard25um =
((detectorType_ == GOTTHARD || detectorType_ == GOTTHARD2) && ((detectorType_ == GOTTHARD || detectorType_ == GOTTHARD2) &&
(numModX * numModY) == 2); (numModX * numModY) == 2);
@ -182,6 +205,10 @@ void DataProcessor::LinkFileInMaster(const std::string &masterFileName,
const std::string &virtualDatasetName, const std::string &virtualDatasetName,
const bool silentMode, const bool silentMode,
std::mutex *hdf5LibMutex) { std::mutex *hdf5LibMutex) {
if (receiverRoiEnabled_) {
throw std::runtime_error("Should not be here, roi with hdf5 virtual should throw.");
}
std::string fname{virtualFileName}, datasetName{virtualDatasetName}; std::string fname{virtualFileName}, datasetName{virtualDatasetName};
// if no virtual file, link data file // if no virtual file, link data file
if (virtualFileName.empty()) { if (virtualFileName.empty()) {
@ -234,21 +261,19 @@ void DataProcessor::ThreadExecution() {
return; return;
} }
uint64_t fnum = 0;
try { try {
fnum = ProcessAnImage(buffer); ProcessAnImage(buffer);
} catch (const std::exception &e) { } catch (const std::exception &e) {
fifo_->FreeAddress(buffer); fifo_->FreeAddress(buffer);
return; return;
} }
// stream (if time/freq to stream) or free // stream (if time/freq to stream) or free
if (*dataStreamEnable_ && SendToStreamer()) { if (streamCurrentFrame_) {
// if first frame to stream, add frame index to fifo header (might // copy the complete image back if roi enabled
// not be the first) if (receiverRoiEnabled_) {
if (firstStreamerFrame_) { (*((uint32_t *)buffer)) = generalData_->imageSize;
firstStreamerFrame_ = false; memcpy(buffer + generalData_->fifoBufferHeaderSize, &completeImageToStreamBeforeCropping[0], generalData_->imageSize);
(*((uint32_t *)(buffer + FIFO_DATASIZE_NUMBYTES))) =
(uint32_t)(fnum - firstIndex_);
} }
fifo_->PushAddressToStream(buffer); fifo_->PushAddressToStream(buffer);
} else { } else {
@ -270,9 +295,10 @@ void DataProcessor::StopProcessing(char *buf) {
LOG(logDEBUG1) << index << ": Processing Completed"; LOG(logDEBUG1) << index << ": Processing Completed";
} }
uint64_t DataProcessor::ProcessAnImage(char *buf) { void DataProcessor::ProcessAnImage(char *buf) {
auto *rheader = reinterpret_cast<sls_receiver_header *>(buf + FIFO_HEADER_NUMBYTES); auto *rheader =
reinterpret_cast<sls_receiver_header *>(buf + FIFO_HEADER_NUMBYTES);
sls_detector_header header = rheader->detHeader; sls_detector_header header = rheader->detHeader;
uint64_t fnum = header.frameNumber; uint64_t fnum = header.frameNumber;
currentFrameIndex_ = fnum; currentFrameIndex_ = fnum;
@ -295,7 +321,7 @@ uint64_t DataProcessor::ProcessAnImage(char *buf) {
} }
// frame padding // frame padding
if (*activated_ && *framePadding_ && nump < generalData_->packetsPerFrame) if (activated_ && *framePadding_ && nump < generalData_->packetsPerFrame)
PadMissingPackets(buf); PadMissingPackets(buf);
// rearrange ctb digital bits (if ctbDbitlist is not empty) // rearrange ctb digital bits (if ctbDbitlist is not empty)
@ -303,6 +329,30 @@ uint64_t DataProcessor::ProcessAnImage(char *buf) {
RearrangeDbitData(buf); RearrangeDbitData(buf);
} }
// 'stream Image' check has to be done here before crop image
// stream (if time/freq to stream) or free
if (*dataStreamEnable_ && SendToStreamer()) {
// if first frame to stream, add frame index to fifo header (might
// not be the first)
if (firstStreamerFrame_) {
firstStreamerFrame_ = false;
(*((uint32_t *)(buf + FIFO_DATASIZE_NUMBYTES))) =
(uint32_t)(fnum - firstIndex_);
}
streamCurrentFrame_ = true;
} else {
streamCurrentFrame_ = false;
}
if (receiverRoiEnabled_) {
// copy the complete image to stream before cropping
if (streamCurrentFrame_) {
memcpy(&completeImageToStreamBeforeCropping[0], buf + generalData_->fifoBufferHeaderSize, generalData_->imageSize);
}
CropImage(buf);
}
try { try {
// normal call back // normal call back
if (rawDataReadyCallBack != nullptr) { if (rawDataReadyCallBack != nullptr) {
@ -341,7 +391,6 @@ uint64_t DataProcessor::ProcessAnImage(char *buf) {
// via stopReceiver tcp) // via stopReceiver tcp)
} }
} }
return fnum;
} }
bool DataProcessor::SendToStreamer() { bool DataProcessor::SendToStreamer() {
@ -508,3 +557,44 @@ void DataProcessor::RearrangeDbitData(char *buf) {
memcpy(buf + digOffset, result.data(), numResult8Bits * sizeof(uint8_t)); memcpy(buf + digOffset, result.data(), numResult8Bits * sizeof(uint8_t));
(*((uint32_t *)buf)) = numResult8Bits * sizeof(uint8_t); (*((uint32_t *)buf)) = numResult8Bits * sizeof(uint8_t);
} }
void DataProcessor::CropImage(char *buf) {
LOG(logDEBUG) << "Cropping Image to ROI " << sls::ToString(receiverRoi_);
int nPixelsX = generalData_->nPixelsX;
int xmin = receiverRoi_.xmin;
int xmax = receiverRoi_.xmax;
int ymin = receiverRoi_.ymin;
int ymax = receiverRoi_.ymax;
int xwidth = xmax - xmin + 1;
int ywidth = ymax - ymin + 1;
if (ymin == -1 || ymax == -1) {
ywidth = 1;
ymin = 0;
}
// calculate total roi size
double bytesPerPixel = generalData_->dynamicRange / 8.00;
int startOffset = (int)((nPixelsX * ymin + xmin) * bytesPerPixel);
// write size into fifo buffer header
std::size_t roiImageSize = xwidth * ywidth * bytesPerPixel;
LOG(logDEBUG) << "roiImageSize:" << roiImageSize;
(*((uint32_t *)buf)) = roiImageSize;
// copy the roi to the beginning of the image
char *dstOffset = buf + generalData_->fifoBufferHeaderSize;
char *srcOffset = dstOffset + startOffset;
// entire width
if (xwidth == nPixelsX) {
memcpy(dstOffset, srcOffset, roiImageSize);
}
// width is cropped
else {
for (int y = 0; y != ywidth; ++y) {
memcpy(dstOffset, srcOffset, xwidth * bytesPerPixel);
dstOffset += (int)(xwidth * bytesPerPixel);
srcOffset += (int)(generalData_->nPixelsX * bytesPerPixel);
}
}
}

View File

@ -28,17 +28,18 @@ class DataProcessor : private virtual slsDetectorDefs, public ThreadObject {
public: public:
DataProcessor(int index, detectorType detectorType, Fifo *fifo, DataProcessor(int index, detectorType detectorType, Fifo *fifo,
bool *activated, bool *dataStreamEnable, bool *dataStreamEnable, uint32_t *streamingFrequency,
uint32_t *streamingFrequency, uint32_t *streamingTimerInMs, uint32_t *streamingTimerInMs, uint32_t *streamingStartFnum,
uint32_t *streamingStartFnum, bool *framePadding, bool *framePadding, std::vector<int> *ctbDbitList,
std::vector<int> *ctbDbitList, int *ctbDbitOffset, int *ctbDbitOffset, int *ctbAnalogDataBytes);
int *ctbAnalogDataBytes);
~DataProcessor() override; ~DataProcessor() override;
bool GetStartedFlag() const; bool GetStartedFlag() const;
void SetFifo(Fifo *f); void SetFifo(Fifo *f);
void SetActivate(bool enable);
void SetReceiverROI(ROI roi);
void ResetParametersforNewAcquisition(); void ResetParametersforNewAcquisition();
void SetGeneralData(GeneralData *generalData); void SetGeneralData(GeneralData *generalData);
@ -85,7 +86,8 @@ class DataProcessor : private virtual slsDetectorDefs, public ThreadObject {
char *, size_t, void *), char *, size_t, void *),
void *arg); void *arg);
/** params: sls_receiver_header pointer, pointer to data, reference to image size */ /** params: sls_receiver_header pointer, pointer to data, reference to image
* size */
void registerCallBackRawDataModifyReady(void (*func)(sls_receiver_header *, void registerCallBackRawDataModifyReady(void (*func)(sls_receiver_header *,
char *, size_t &, char *, size_t &,
void *), void *),
@ -110,9 +112,8 @@ class DataProcessor : private virtual slsDetectorDefs, public ThreadObject {
/** /**
* Process an image popped from fifo, * Process an image popped from fifo,
* write to file if fw enabled & update parameters * write to file if fw enabled & update parameters
* @returns frame number
*/ */
uint64_t ProcessAnImage(char *buf); void ProcessAnImage(char *buf);
/** /**
* Calls CheckTimer and CheckCount for streaming frequency and timer * Calls CheckTimer and CheckCount for streaming frequency and timer
@ -143,13 +144,18 @@ class DataProcessor : private virtual slsDetectorDefs, public ThreadObject {
*/ */
void RearrangeDbitData(char *buf); void RearrangeDbitData(char *buf);
void CropImage(char *buf);
static const std::string typeName_; static const std::string typeName_;
const GeneralData *generalData_{nullptr}; const GeneralData *generalData_{nullptr};
Fifo *fifo_; Fifo *fifo_;
detectorType detectorType_; detectorType detectorType_;
bool *dataStreamEnable_; bool *dataStreamEnable_;
bool *activated_; bool activated_{false};
ROI receiverRoi_{};
bool receiverRoiEnabled_{false};
std::unique_ptr<char[]> completeImageToStreamBeforeCropping;
/** if 0, sending random images with a timer */ /** if 0, sending random images with a timer */
uint32_t *streamingFrequency_; uint32_t *streamingFrequency_;
uint32_t *streamingTimerInMs_; uint32_t *streamingTimerInMs_;
@ -164,7 +170,6 @@ class DataProcessor : private virtual slsDetectorDefs, public ThreadObject {
std::atomic<uint64_t> firstIndex_{0}; std::atomic<uint64_t> firstIndex_{0};
// for statistics // for statistics
/** Number of frames caught */
uint64_t numFramesCaught_{0}; uint64_t numFramesCaught_{0};
/** Frame Number of latest processed frame number */ /** Frame Number of latest processed frame number */
@ -173,6 +178,8 @@ class DataProcessor : private virtual slsDetectorDefs, public ThreadObject {
/** first streamer frame to add frame index in fifo header */ /** first streamer frame to add frame index in fifo header */
bool firstStreamerFrame_{false}; bool firstStreamerFrame_{false};
bool streamCurrentFrame_{false};
File *dataFile_{nullptr}; File *dataFile_{nullptr};
// call back // call back

View File

@ -19,7 +19,7 @@ const std::string DataStreamer::TypeName = "DataStreamer";
DataStreamer::DataStreamer(int ind, Fifo *f, uint32_t *dr, ROI *r, uint64_t *fi, DataStreamer::DataStreamer(int ind, Fifo *f, uint32_t *dr, ROI *r, uint64_t *fi,
bool fr, slsDetectorDefs::xy np, bool *qe, bool fr, slsDetectorDefs::xy np, bool *qe,
uint64_t *tot) uint64_t *tot)
: ThreadObject(ind, TypeName), fifo(f), dynamicRange(dr), roi(r), : ThreadObject(ind, TypeName), fifo(f), dynamicRange(dr), detectorRoi(r),
fileIndex(fi), flipRows(fr), numPorts(np), quadEnable(qe), fileIndex(fi), flipRows(fr), numPorts(np), quadEnable(qe),
totalNumFrames(tot) { totalNumFrames(tot) {
@ -43,8 +43,8 @@ void DataStreamer::ResetParametersforNewAcquisition(const std::string &fname) {
delete[] completeBuffer; delete[] completeBuffer;
completeBuffer = nullptr; completeBuffer = nullptr;
} }
if (generalData->myDetectorType == GOTTHARD && roi->xmin != -1) { if (generalData->myDetectorType == GOTTHARD && detectorRoi->xmin != -1) {
adcConfigured = generalData->GetAdcConfigured(index, *roi); adcConfigured = generalData->GetAdcConfigured(index, *detectorRoi);
completeBuffer = new char[generalData->imageSizeComplete]; completeBuffer = new char[generalData->imageSizeComplete];
memset(completeBuffer, 0, generalData->imageSizeComplete); memset(completeBuffer, 0, generalData->imageSizeComplete);
} }
@ -114,7 +114,7 @@ void DataStreamer::ThreadExecution() {
<< std::hex << (void *)(buffer) << std::dec << ":" << buffer; << std::hex << (void *)(buffer) << std::dec << ":" << buffer;
// check dummy // check dummy
uint32_t numBytes = (uint32_t)(*((uint32_t *)buffer)); auto numBytes = *reinterpret_cast<uint32_t *>(buffer);
LOG(logDEBUG1) << "DataStreamer " << index << ", Numbytes:" << numBytes; LOG(logDEBUG1) << "DataStreamer " << index << ", Numbytes:" << numBytes;
if (numBytes == DUMMY_PACKET_VALUE) { if (numBytes == DUMMY_PACKET_VALUE) {
StopProcessing(buffer); StopProcessing(buffer);
@ -153,6 +153,7 @@ void DataStreamer::ProcessAnImage(char *buf) {
if (!startedFlag) { if (!startedFlag) {
RecordFirstIndex(fnum, buf); RecordFirstIndex(fnum, buf);
} }
auto numBytes = *reinterpret_cast<uint32_t *>(buf);
// shortframe gotthard // shortframe gotthard
if (completeBuffer) { if (completeBuffer) {
@ -170,7 +171,7 @@ void DataStreamer::ProcessAnImage(char *buf) {
} }
memcpy(completeBuffer + ((generalData->imageSize) * adcConfigured), memcpy(completeBuffer + ((generalData->imageSize) * adcConfigured),
buf + FIFO_HEADER_NUMBYTES + sizeof(sls_receiver_header), buf + FIFO_HEADER_NUMBYTES + sizeof(sls_receiver_header),
(uint32_t)(*((uint32_t *)buf))); numBytes);
if (!zmqSocket->SendData(completeBuffer, if (!zmqSocket->SendData(completeBuffer,
generalData->imageSizeComplete)) { generalData->imageSizeComplete)) {
@ -182,16 +183,15 @@ void DataStreamer::ProcessAnImage(char *buf) {
// normal // normal
else { else {
if (!SendHeader(header, (uint32_t)(*((uint32_t *)buf)), if (!SendHeader(header, numBytes, generalData->nPixelsX,
generalData->nPixelsX, generalData->nPixelsY, generalData->nPixelsY,
false)) { // new size possibly from callback false)) { // new size possibly from callback
LOG(logERROR) << "Could not send zmq header for fnum " << fnum LOG(logERROR) << "Could not send zmq header for fnum " << fnum
<< " and streamer " << index; << " and streamer " << index;
} }
if (!zmqSocket->SendData( if (!zmqSocket->SendData(buf + FIFO_HEADER_NUMBYTES +
buf + FIFO_HEADER_NUMBYTES + sizeof(sls_receiver_header), sizeof(sls_receiver_header),
(uint32_t)(*( numBytes)) { // new size possibly from callback
(uint32_t *)buf)))) { // new size possibly from callback
LOG(logERROR) << "Could not send zmq data for fnum " << fnum LOG(logERROR) << "Could not send zmq data for fnum " << fnum
<< " and streamer " << index; << " and streamer " << index;
} }

View File

@ -30,7 +30,7 @@ class DataStreamer : private virtual slsDetectorDefs, public ThreadObject {
* @param ind self index * @param ind self index
* @param f address of Fifo pointer * @param f address of Fifo pointer
* @param dr pointer to dynamic range * @param dr pointer to dynamic range
* @param r roi * @param r detectorRoi
* @param fi pointer to file index * @param fi pointer to file index
* @param fr flip rows * @param fr flip rows
* @param nm number of ports in each dimension * @param nm number of ports in each dimension
@ -64,15 +64,7 @@ class DataStreamer : private virtual slsDetectorDefs, public ThreadObject {
*/ */
void CreateZmqSockets(int *nunits, uint32_t port, const sls::IpAddr ip, void CreateZmqSockets(int *nunits, uint32_t port, const sls::IpAddr ip,
int hwm); int hwm);
/**
* Shuts down and deletes Zmq Sockets
*/
void CloseZmqSocket(); void CloseZmqSocket();
/**
* Restream stop dummy packet
*/
void RestreamStop(); void RestreamStop();
private: private:
@ -82,24 +74,17 @@ class DataStreamer : private virtual slsDetectorDefs, public ThreadObject {
* @param buf get frame index from buffer to calculate first index to record * @param buf get frame index from buffer to calculate first index to record
*/ */
void RecordFirstIndex(uint64_t fnum, char *buf); void RecordFirstIndex(uint64_t fnum, char *buf);
/**
* Thread Exeution for DataStreamer Class
* Stream an image via zmq
*/
void ThreadExecution(); void ThreadExecution();
/** /**
* Frees dummy buffer, * Frees dummy buffer,
* reset running mask by calling StopRunning() * reset running mask by calling StopRunning()
* @param buf address of pointer
*/ */
void StopProcessing(char *buf); void StopProcessing(char *buf);
/** /**
* Process an image popped from fifo, * Process an image popped from fifo,
* write to file if fw enabled & update parameters * write to file if fw enabled & update parameters
* @param buf address of pointer
*/ */
void ProcessAnImage(char *buf); void ProcessAnImage(char *buf);
@ -120,11 +105,10 @@ class DataStreamer : private virtual slsDetectorDefs, public ThreadObject {
Fifo *fifo; Fifo *fifo;
ZmqSocket *zmqSocket{nullptr}; ZmqSocket *zmqSocket{nullptr};
uint32_t *dynamicRange; uint32_t *dynamicRange;
ROI *roi; ROI *detectorRoi;
int adcConfigured{-1}; int adcConfigured{-1};
uint64_t *fileIndex; uint64_t *fileIndex;
bool flipRows; bool flipRows;
std::map<std::string, std::string> additionalJsonHeader; std::map<std::string, std::string> additionalJsonHeader;
/** Used by streamer thread to update local copy (reduce number of locks /** Used by streamer thread to update local copy (reduce number of locks
@ -137,15 +121,10 @@ class DataStreamer : private virtual slsDetectorDefs, public ThreadObject {
/** local copy of additional json header (it can be update on the fly) */ /** local copy of additional json header (it can be update on the fly) */
std::map<std::string, std::string> localAdditionalJsonHeader; std::map<std::string, std::string> localAdditionalJsonHeader;
/** Aquisition Started flag */
bool startedFlag{false}; bool startedFlag{false};
/** Frame Number of First Frame */
uint64_t firstIndex{0}; uint64_t firstIndex{0};
std::string fileNametoStream; std::string fileNametoStream;
/** Complete buffer used for detectorRoi, eg. shortGotthard */
/** Complete buffer used for roi, eg. shortGotthard */
char *completeBuffer{nullptr}; char *completeBuffer{nullptr};
xy numPorts{1, 1}; xy numPorts{1, 1};

View File

@ -72,7 +72,7 @@ class GeneralData {
void ThrowGenericError(std::string msg) const { void ThrowGenericError(std::string msg) const {
throw sls::RuntimeError( throw sls::RuntimeError(
msg + std::string("SetROI is a generic function that should be " msg + std::string("This is a generic function that should be "
"overloaded by a derived class")); "overloaded by a derived class"));
} }
@ -96,8 +96,8 @@ class GeneralData {
bunchId = -1; bunchId = -1;
} }
virtual void SetROI(slsDetectorDefs::ROI i) { virtual void SetDetectorROI(slsDetectorDefs::ROI i) {
ThrowGenericError("SetROI"); ThrowGenericError("SetDetectorROI");
}; };
/**@returns adc configured */ /**@returns adc configured */
@ -248,7 +248,7 @@ class GotthardData : public GeneralData {
return oddStartingPacket; return oddStartingPacket;
}; };
void SetROI(slsDetectorDefs::ROI i) { void SetDetectorROI(slsDetectorDefs::ROI i) {
roi = i; roi = i;
UpdateImageSize(); UpdateImageSize();
}; };

View File

@ -165,7 +165,7 @@ void Implementation::setDetectorType(const detectorType d) {
readoutType = generalData->readoutType; readoutType = generalData->readoutType;
adcEnableMaskOneGiga = generalData->adcEnableMaskOneGiga; adcEnableMaskOneGiga = generalData->adcEnableMaskOneGiga;
adcEnableMaskTenGiga = generalData->adcEnableMaskTenGiga; adcEnableMaskTenGiga = generalData->adcEnableMaskTenGiga;
roi = generalData->roi; detectorRoi = generalData->roi;
counterMask = generalData->counterMask; counterMask = generalData->counterMask;
SetLocalNetworkParameters(); SetLocalNetworkParameters();
@ -179,17 +179,16 @@ void Implementation::setDetectorType(const detectorType d) {
listener.push_back(sls::make_unique<Listener>( listener.push_back(sls::make_unique<Listener>(
i, detType, fifo_ptr, &status, &udpPortNum[i], &eth[i], i, detType, fifo_ptr, &status, &udpPortNum[i], &eth[i],
&udpSocketBufferSize, &actualUDPSocketBufferSize, &udpSocketBufferSize, &actualUDPSocketBufferSize,
&framesPerFile, &frameDiscardMode, &activated, &framesPerFile, &frameDiscardMode, &detectorDataStream[i],
&detectorDataStream[i], &silentMode)); &silentMode));
int ctbAnalogDataBytes = 0; int ctbAnalogDataBytes = 0;
if (detType == CHIPTESTBOARD) { if (detType == CHIPTESTBOARD) {
ctbAnalogDataBytes = generalData->GetNumberOfAnalogDatabytes(); ctbAnalogDataBytes = generalData->GetNumberOfAnalogDatabytes();
} }
dataProcessor.push_back(sls::make_unique<DataProcessor>( dataProcessor.push_back(sls::make_unique<DataProcessor>(
i, detType, fifo_ptr, &activated, &dataStreamEnable, i, detType, fifo_ptr, &dataStreamEnable, &streamingFrequency,
&streamingFrequency, &streamingTimerInMs, &streamingStartFnum, &streamingTimerInMs, &streamingStartFnum, &framePadding,
&framePadding, &ctbDbitList, &ctbDbitOffset, &ctbDbitList, &ctbDbitOffset, &ctbAnalogDataBytes));
&ctbAnalogDataBytes));
} catch (...) { } catch (...) {
listener.clear(); listener.clear();
dataProcessor.clear(); dataProcessor.clear();
@ -200,10 +199,14 @@ void Implementation::setDetectorType(const detectorType d) {
} }
// set up writer and callbacks // set up writer and callbacks
for (const auto &it : listener) for (const auto &it : listener) {
it->SetGeneralData(generalData); it->SetGeneralData(generalData);
for (const auto &it : dataProcessor) it->SetActivate(activated);
}
for (const auto &it : dataProcessor) {
it->SetGeneralData(generalData); it->SetGeneralData(generalData);
it->SetActivate(activated);
}
SetThreadPriorities(); SetThreadPriorities();
LOG(logDEBUG) << " Detector type set to " << sls::ToString(d); LOG(logDEBUG) << " Detector type set to " << sls::ToString(d);
@ -213,7 +216,7 @@ slsDetectorDefs::xy Implementation::getDetectorSize() const {
return numModules; return numModules;
} }
slsDetectorDefs::xy Implementation::GetPortGeometry() { const slsDetectorDefs::xy Implementation::GetPortGeometry() const {
xy portGeometry{1, 1}; xy portGeometry{1, 1};
if (detType == EIGER) if (detType == EIGER)
portGeometry.x = numUDPInterfaces; portGeometry.x = numUDPInterfaces;
@ -363,6 +366,91 @@ void Implementation::setArping(const bool i,
} }
} }
slsDetectorDefs::ROI Implementation::getReceiverROI() const {
return receiverRoi;
}
void Implementation::setReceiverROI(const slsDetectorDefs::ROI arg) {
receiverRoi = arg;
if (numUDPInterfaces == 1 || detType == slsDetectorDefs::GOTTHARD2) {
portRois[0] = arg;
} else {
slsDetectorDefs::xy nPortDim(generalData->nPixelsX,
generalData->nPixelsY);
for (int iPort = 0; iPort != numUDPInterfaces; ++iPort) {
// default init = complete roi
slsDetectorDefs::ROI portRoi{};
// no roi
if (arg.noRoi()) {
portRoi.setNoRoi();
}
// incomplete roi
else if (!arg.completeRoi()) {
// get port limits
slsDetectorDefs::ROI portFullRoi{0, nPortDim.x - 1, 0,
nPortDim.y - 1};
if (iPort == 1) {
// left right (eiger)
if (GetPortGeometry().x == 2) {
portFullRoi.xmin += nPortDim.x;
portFullRoi.xmax += nPortDim.x;
}
// top bottom (jungfrau)
else {
portFullRoi.ymin += nPortDim.y;
portFullRoi.ymax += nPortDim.y;
}
}
LOG(logDEBUG)
<< iPort << ": portfullroi:" << sls::ToString(portFullRoi);
// no roi
if (arg.xmin > portFullRoi.xmax ||
arg.xmax < portFullRoi.xmin ||
arg.ymin > portFullRoi.ymax ||
arg.ymax < portFullRoi.ymin) {
portRoi.setNoRoi();
}
// incomplete module roi
else if (arg.xmin > portFullRoi.xmin ||
arg.xmax < portFullRoi.xmax ||
arg.ymin > portFullRoi.ymin ||
arg.ymax < portFullRoi.ymax) {
portRoi.xmin = (arg.xmin <= portFullRoi.xmin)
? 0
: (arg.xmin % nPortDim.x);
portRoi.xmax = (arg.xmax >= portFullRoi.xmax)
? nPortDim.x - 1
: (arg.xmax % nPortDim.x);
portRoi.ymin = (arg.ymin <= portFullRoi.ymin)
? 0
: (arg.ymin % nPortDim.y);
portRoi.ymax = (arg.ymax >= portFullRoi.ymax)
? nPortDim.y - 1
: (arg.ymax % nPortDim.y);
}
}
portRois[iPort] = portRoi;
}
}
for (size_t i = 0; i != dataProcessor.size(); ++i)
dataProcessor[i]->SetReceiverROI(portRois[i]);
LOG(logINFO) << "receiver roi: " << sls::ToString(receiverRoi);
if (numUDPInterfaces == 2 && detType != slsDetectorDefs::GOTTHARD2) {
LOG(logINFO) << "port rois: " << sls::ToString(portRois);
}
}
void Implementation::setReceiverROIMetadata(const ROI arg) {
receiverRoiMetadata = arg;
LOG(logINFO) << "receiver roi Metadata: " << sls::ToString(receiverRoiMetadata);
}
/************************************************** /**************************************************
* * * *
* File Parameters * * File Parameters *
@ -775,6 +863,8 @@ void Implementation::StartMasterWriter() {
masterAttributes.framePadding = framePadding; masterAttributes.framePadding = framePadding;
masterAttributes.scanParams = scanParams; masterAttributes.scanParams = scanParams;
masterAttributes.totalFrames = numberOfTotalFrames; masterAttributes.totalFrames = numberOfTotalFrames;
masterAttributes.receiverRoi =
receiverRoiMetadata;
masterAttributes.exptime = acquisitionTime; masterAttributes.exptime = acquisitionTime;
masterAttributes.period = acquisitionPeriod; masterAttributes.period = acquisitionPeriod;
masterAttributes.burstMode = burstMode; masterAttributes.burstMode = burstMode;
@ -805,7 +895,7 @@ void Implementation::StartMasterWriter() {
for (auto &i : ctbDbitList) { for (auto &i : ctbDbitList) {
masterAttributes.dbitlist |= (1 << i); masterAttributes.dbitlist |= (1 << i);
} }
masterAttributes.roi = roi; masterAttributes.detectorRoi = detectorRoi;
masterAttributes.counterMask = counterMask; masterAttributes.counterMask = counterMask;
masterAttributes.exptimeArray[0] = acquisitionTime1; masterAttributes.exptimeArray[0] = acquisitionTime1;
masterAttributes.exptimeArray[1] = acquisitionTime2; masterAttributes.exptimeArray[1] = acquisitionTime2;
@ -842,8 +932,9 @@ void Implementation::StartMasterWriter() {
} }
} }
#endif #endif
} catch (...) { } catch (std::exception &e) {
; // ignore it and just print it // ignore it and just print it
LOG(logWARNING) << "Caught exception when handling virtual hdf5 file [" << e.what() << "]";
} }
} }
@ -895,6 +986,8 @@ void Implementation::setNumberofUDPInterfaces(const int n) {
// fifo // fifo
udpSocketBufferSize = generalData->defaultUdpSocketBufferSize; udpSocketBufferSize = generalData->defaultUdpSocketBufferSize;
SetupFifoStructure(); SetupFifoStructure();
// recalculate port rois
setReceiverROI(receiverRoi);
// create threads // create threads
for (int i = 0; i < numUDPInterfaces; ++i) { for (int i = 0; i < numUDPInterfaces; ++i) {
@ -904,9 +997,10 @@ void Implementation::setNumberofUDPInterfaces(const int n) {
listener.push_back(sls::make_unique<Listener>( listener.push_back(sls::make_unique<Listener>(
i, detType, fifo_ptr, &status, &udpPortNum[i], &eth[i], i, detType, fifo_ptr, &status, &udpPortNum[i], &eth[i],
&udpSocketBufferSize, &actualUDPSocketBufferSize, &udpSocketBufferSize, &actualUDPSocketBufferSize,
&framesPerFile, &frameDiscardMode, &activated, &framesPerFile, &frameDiscardMode, &detectorDataStream[i],
&detectorDataStream[i], &silentMode)); &silentMode));
listener[i]->SetGeneralData(generalData); listener[i]->SetGeneralData(generalData);
listener[i]->SetActivate(activated);
int ctbAnalogDataBytes = 0; int ctbAnalogDataBytes = 0;
if (detType == CHIPTESTBOARD) { if (detType == CHIPTESTBOARD) {
@ -914,11 +1008,13 @@ void Implementation::setNumberofUDPInterfaces(const int n) {
generalData->GetNumberOfAnalogDatabytes(); generalData->GetNumberOfAnalogDatabytes();
} }
dataProcessor.push_back(sls::make_unique<DataProcessor>( dataProcessor.push_back(sls::make_unique<DataProcessor>(
i, detType, fifo_ptr, &activated, &dataStreamEnable, i, detType, fifo_ptr, &dataStreamEnable,
&streamingFrequency, &streamingTimerInMs, &streamingFrequency, &streamingTimerInMs,
&streamingStartFnum, &framePadding, &ctbDbitList, &streamingStartFnum, &framePadding, &ctbDbitList,
&ctbDbitOffset, &ctbAnalogDataBytes)); &ctbDbitOffset, &ctbAnalogDataBytes));
dataProcessor[i]->SetGeneralData(generalData); dataProcessor[i]->SetGeneralData(generalData);
dataProcessor[i]->SetActivate(activated);
dataProcessor[i]->SetReceiverROI(portRois[i]);
} catch (...) { } catch (...) {
listener.clear(); listener.clear();
dataProcessor.clear(); dataProcessor.clear();
@ -934,15 +1030,15 @@ void Implementation::setNumberofUDPInterfaces(const int n) {
flip = (i == 1 ? true : false); flip = (i == 1 ? true : false);
} }
dataStreamer.push_back(sls::make_unique<DataStreamer>( dataStreamer.push_back(sls::make_unique<DataStreamer>(
i, fifo[i].get(), &dynamicRange, &roi, &fileIndex, flip, i, fifo[i].get(), &dynamicRange, &detectorRoi,
numPorts, &quadEnable, &numberOfTotalFrames)); &fileIndex, flip, numPorts, &quadEnable,
&numberOfTotalFrames));
dataStreamer[i]->SetGeneralData(generalData); dataStreamer[i]->SetGeneralData(generalData);
dataStreamer[i]->CreateZmqSockets( dataStreamer[i]->CreateZmqSockets(
&numUDPInterfaces, streamingPort, streamingSrcIP, &numUDPInterfaces, streamingPort, streamingSrcIP,
streamingHwm); streamingHwm);
dataStreamer[i]->SetAdditionalJsonHeader( dataStreamer[i]->SetAdditionalJsonHeader(
additionalJsonHeader); additionalJsonHeader);
} catch (...) { } catch (...) {
if (dataStreamEnable) { if (dataStreamEnable) {
dataStreamer.clear(); dataStreamer.clear();
@ -1061,8 +1157,9 @@ void Implementation::setDataStreamEnable(const bool enable) {
flip = (i == 1 ? true : false); flip = (i == 1 ? true : false);
} }
dataStreamer.push_back(sls::make_unique<DataStreamer>( dataStreamer.push_back(sls::make_unique<DataStreamer>(
i, fifo[i].get(), &dynamicRange, &roi, &fileIndex, flip, i, fifo[i].get(), &dynamicRange, &detectorRoi,
numPorts, &quadEnable, &numberOfTotalFrames)); &fileIndex, flip, numPorts, &quadEnable,
&numberOfTotalFrames));
dataStreamer[i]->SetGeneralData(generalData); dataStreamer[i]->SetGeneralData(generalData);
dataStreamer[i]->CreateZmqSockets( dataStreamer[i]->CreateZmqSockets(
&numUDPInterfaces, streamingPort, streamingSrcIP, &numUDPInterfaces, streamingPort, streamingSrcIP,
@ -1420,20 +1517,20 @@ void Implementation::setDynamicRange(const uint32_t i) {
LOG(logINFO) << "Dynamic Range: " << dynamicRange; LOG(logINFO) << "Dynamic Range: " << dynamicRange;
} }
slsDetectorDefs::ROI Implementation::getROI() const { return roi; } slsDetectorDefs::ROI Implementation::getROI() const { return detectorRoi; }
void Implementation::setROI(slsDetectorDefs::ROI arg) { void Implementation::setDetectorROI(slsDetectorDefs::ROI arg) {
if (roi.xmin != arg.xmin || roi.xmax != arg.xmax) { if (detectorRoi.xmin != arg.xmin || detectorRoi.xmax != arg.xmax) {
roi.xmin = arg.xmin; detectorRoi.xmin = arg.xmin;
roi.xmax = arg.xmax; detectorRoi.xmax = arg.xmax;
// only for gotthard // only for gotthard
generalData->SetROI(arg); generalData->SetDetectorROI(arg);
framesPerFile = generalData->maxFramesPerFile; framesPerFile = generalData->maxFramesPerFile;
SetupFifoStructure(); SetupFifoStructure();
} }
LOG(logINFO) << "ROI: [" << roi.xmin << ", " << roi.xmax << "]"; LOG(logINFO) << "Detector ROI: " << sls::ToString(detectorRoi);
LOG(logINFO) << "Packets per Frame: " << (generalData->packetsPerFrame); LOG(logINFO) << "Packets per Frame: " << (generalData->packetsPerFrame);
} }
@ -1509,6 +1606,11 @@ bool Implementation::getActivate() const { return activated; }
void Implementation::setActivate(bool enable) { void Implementation::setActivate(bool enable) {
activated = enable; activated = enable;
for (const auto &it : listener)
it->SetActivate(enable);
for (const auto &it : dataProcessor)
it->SetActivate(enable);
LOG(logINFO) << "Activation: " << (activated ? "enabled" : "disabled"); LOG(logINFO) << "Activation: " << (activated ? "enabled" : "disabled");
} }

View File

@ -53,6 +53,9 @@ class Implementation : private virtual slsDetectorDefs {
bool getArping() const; bool getArping() const;
pid_t getArpingThreadId() const; pid_t getArpingThreadId() const;
void setArping(const bool i, const std::vector<std::string> ips); void setArping(const bool i, const std::vector<std::string> ips);
ROI getReceiverROI() const;
void setReceiverROI(const ROI arg);
void setReceiverROIMetadata(const ROI arg);
/************************************************** /**************************************************
* * * *
@ -204,7 +207,7 @@ class Implementation : private virtual slsDetectorDefs {
void setDynamicRange(const uint32_t i); void setDynamicRange(const uint32_t i);
ROI getROI() const; ROI getROI() const;
/* [Gotthard] */ /* [Gotthard] */
void setROI(ROI arg); void setDetectorROI(ROI arg);
bool getTenGigaEnable() const; bool getTenGigaEnable() const;
/* [Eiger][Ctb] */ /* [Eiger][Ctb] */
void setTenGigaEnable(const bool b); void setTenGigaEnable(const bool b);
@ -253,7 +256,8 @@ class Implementation : private virtual slsDetectorDefs {
* * * *
* ************************************************/ * ************************************************/
/** params: file path, file name, file index, image size */ /** params: file path, file name, file index, image size */
void registerCallBackStartAcquisition(int (*func)(const std::string &, const std::string &, void registerCallBackStartAcquisition(int (*func)(const std::string &,
const std::string &,
uint64_t, size_t, void *), uint64_t, size_t, void *),
void *arg); void *arg);
/** params: total frames caught */ /** params: total frames caught */
@ -263,7 +267,8 @@ class Implementation : private virtual slsDetectorDefs {
void registerCallBackRawDataReady(void (*func)(sls_receiver_header *, void registerCallBackRawDataReady(void (*func)(sls_receiver_header *,
char *, size_t, void *), char *, size_t, void *),
void *arg); void *arg);
/** params: sls_receiver_header pointer, pointer to data, reference to image size */ /** params: sls_receiver_header pointer, pointer to data, reference to image
* size */
void registerCallBackRawDataModifyReady(void (*func)(sls_receiver_header *, void registerCallBackRawDataModifyReady(void (*func)(sls_receiver_header *,
char *, size_t &, char *, size_t &,
void *), void *),
@ -274,7 +279,7 @@ class Implementation : private virtual slsDetectorDefs {
void SetThreadPriorities(); void SetThreadPriorities();
void SetupFifoStructure(); void SetupFifoStructure();
xy GetPortGeometry(); const xy GetPortGeometry() const;
void ResetParametersforNewAcquisition(); void ResetParametersforNewAcquisition();
void CreateUDPSockets(); void CreateUDPSockets();
void SetupWriter(); void SetupWriter();
@ -299,6 +304,10 @@ class Implementation : private virtual slsDetectorDefs {
bool framePadding{true}; bool framePadding{true};
pid_t parentThreadId; pid_t parentThreadId;
pid_t tcpThreadId; pid_t tcpThreadId;
ROI receiverRoi{};
std::array<ROI, 2> portRois{};
// receiver roi for complete detector for metadata
ROI receiverRoiMetadata{};
// file parameters // file parameters
fileFormat fileFormatType{BINARY}; fileFormat fileFormatType{BINARY};
@ -356,13 +365,14 @@ class Implementation : private virtual slsDetectorDefs {
uint32_t numberOfDigitalSamples{0}; uint32_t numberOfDigitalSamples{0};
uint32_t counterMask{0}; uint32_t counterMask{0};
uint32_t dynamicRange{16}; uint32_t dynamicRange{16};
ROI roi{}; ROI detectorRoi{};
bool tengigaEnable{false}; bool tengigaEnable{false};
bool flipRows{false}; bool flipRows{false};
bool quadEnable{false}; bool quadEnable{false};
bool activated{true}; bool activated{true};
std::array<bool, 2> detectorDataStream = {{true, true}}; std::array<bool, 2> detectorDataStream = {{true, true}};
std::array<bool, 2> detectorDataStream10GbE = {{true, true}}; std::array<bool, 2> detectorDataStream10GbE = {{true, true}};
std::array<bool, 2> portStream = {{true, true}};
int readNRows{0}; int readNRows{0};
int thresholdEnergyeV{-1}; int thresholdEnergyeV{-1};
std::array<int, 3> thresholdAllEnergyeV = {{-1, -1, -1}}; std::array<int, 3> thresholdAllEnergyeV = {{-1, -1, -1}};
@ -374,8 +384,8 @@ class Implementation : private virtual slsDetectorDefs {
int ctbDbitOffset{0}; int ctbDbitOffset{0};
// callbacks // callbacks
int (*startAcquisitionCallBack)(const std::string &, const std::string &, uint64_t, size_t, int (*startAcquisitionCallBack)(const std::string &, const std::string &,
void *){nullptr}; uint64_t, size_t, void *){nullptr};
void *pStartAcquisition{nullptr}; void *pStartAcquisition{nullptr};
void (*acquisitionFinishedCallBack)(uint64_t, void *){nullptr}; void (*acquisitionFinishedCallBack)(uint64_t, void *){nullptr};
void *pAcquisitionFinished{nullptr}; void *pAcquisitionFinished{nullptr};

View File

@ -24,11 +24,11 @@ const std::string Listener::TypeName = "Listener";
Listener::Listener(int ind, detectorType dtype, Fifo *f, Listener::Listener(int ind, detectorType dtype, Fifo *f,
std::atomic<runStatus> *s, uint32_t *portno, std::string *e, std::atomic<runStatus> *s, uint32_t *portno, std::string *e,
int *us, int *as, uint32_t *fpf, frameDiscardPolicy *fdp, int *us, int *as, uint32_t *fpf, frameDiscardPolicy *fdp,
bool *act, bool *detds, bool *sm) bool *detds, bool *sm)
: ThreadObject(ind, TypeName), fifo(f), myDetectorType(dtype), status(s), : ThreadObject(ind, TypeName), fifo(f), myDetectorType(dtype), status(s),
udpPortNumber(portno), eth(e), udpSocketBufferSize(us), udpPortNumber(portno), eth(e), udpSocketBufferSize(us),
actualUDPSocketBufferSize(as), framesPerFile(fpf), frameDiscardMode(fdp), actualUDPSocketBufferSize(as), framesPerFile(fpf), frameDiscardMode(fdp),
activated(act), detectorDataStream(detds), silentMode(sm) { detectorDataStream(detds), silentMode(sm) {
LOG(logDEBUG) << "Listener " << ind << " created"; LOG(logDEBUG) << "Listener " << ind << " created";
} }
@ -115,8 +115,10 @@ void Listener::RecordFirstIndex(uint64_t fnum) {
void Listener::SetGeneralData(GeneralData *g) { generalData = g; } void Listener::SetGeneralData(GeneralData *g) { generalData = g; }
void Listener::SetActivate(bool enable) { activated = enable; }
void Listener::CreateUDPSockets() { void Listener::CreateUDPSockets() {
if (!(*activated) || !(*detectorDataStream)) { if (!activated || !(*detectorDataStream)) {
return; return;
} }
@ -166,7 +168,7 @@ void Listener::CreateDummySocketForUDPSocketBufferSize(int s) {
LOG(logINFO) << "Testing UDP Socket Buffer size " << s << " with test port " LOG(logINFO) << "Testing UDP Socket Buffer size " << s << " with test port "
<< *udpPortNumber; << *udpPortNumber;
if (!(*activated) || !(*detectorDataStream)) { if (!activated || !(*detectorDataStream)) {
*actualUDPSocketBufferSize = (s * 2); *actualUDPSocketBufferSize = (s * 2);
return; return;
} }
@ -225,8 +227,7 @@ void Listener::ThreadExecution() {
<< std::hex << (void *)(buffer) << std::dec << ":" << buffer; << std::hex << (void *)(buffer) << std::dec << ":" << buffer;
// udpsocket doesnt exist // udpsocket doesnt exist
if (*activated && *detectorDataStream && !udpSocketAlive && if (activated && *detectorDataStream && !udpSocketAlive && !carryOverFlag) {
!carryOverFlag) {
// LOG(logERROR) << "Listening_Thread " << index << ": UDP Socket not // LOG(logERROR) << "Listening_Thread " << index << ": UDP Socket not
// created or shut down earlier"; // created or shut down earlier";
(*((uint32_t *)buffer)) = 0; (*((uint32_t *)buffer)) = 0;
@ -236,7 +237,7 @@ void Listener::ThreadExecution() {
// get data // get data
if ((*status != TRANSMITTING && if ((*status != TRANSMITTING &&
(!(*activated) || !(*detectorDataStream) || udpSocketAlive)) || (!activated || !(*detectorDataStream) || udpSocketAlive)) ||
carryOverFlag) { carryOverFlag) {
rc = ListenToAnImage(buffer); rc = ListenToAnImage(buffer);
} }
@ -319,7 +320,7 @@ uint32_t Listener::ListenToAnImage(char *buf) {
return 0; return 0;
} }
// deactivated (eiger) // deactivated (eiger)
if (!(*activated)) { if (!activated) {
return 0; return 0;
} }

View File

@ -37,13 +37,12 @@ class Listener : private virtual slsDetectorDefs, public ThreadObject {
* @param as pointer to actual udp socket buffer size * @param as pointer to actual udp socket buffer size
* @param fpf pointer to frames per file * @param fpf pointer to frames per file
* @param fdp frame discard policy * @param fdp frame discard policy
* @param act pointer to activated
* @param detds pointer to detector data stream * @param detds pointer to detector data stream
* @param sm pointer to silent mode * @param sm pointer to silent mode
*/ */
Listener(int ind, detectorType dtype, Fifo *f, std::atomic<runStatus> *s, Listener(int ind, detectorType dtype, Fifo *f, std::atomic<runStatus> *s,
uint32_t *portno, std::string *e, int *us, int *as, uint32_t *fpf, uint32_t *portno, std::string *e, int *us, int *as, uint32_t *fpf,
frameDiscardPolicy *fdp, bool *act, bool *detds, bool *sm); frameDiscardPolicy *fdp, bool *detds, bool *sm);
/** /**
* Destructor * Destructor
@ -63,6 +62,7 @@ class Listener : private virtual slsDetectorDefs, public ThreadObject {
void SetFifo(Fifo *f); void SetFifo(Fifo *f);
void ResetParametersforNewAcquisition(); void ResetParametersforNewAcquisition();
void SetGeneralData(GeneralData *g); void SetGeneralData(GeneralData *g);
void SetActivate(bool enable);
void CreateUDPSockets(); void CreateUDPSockets();
void ShutDownUDPSocket(); void ShutDownUDPSocket();
@ -76,8 +76,8 @@ class Listener : private virtual slsDetectorDefs, public ThreadObject {
/** /**
* Set hard coded (calculated but not from detector) row and column * Set hard coded (calculated but not from detector) row and column
* r is in row index if detector has not send them yet in firmware, * r is in row index if detector has not send them yet in firmware,
* c is in col index for jungfrau and eiger (for missing packets/deactivated * c is in col index for jungfrau and eiger (for missing
* eiger) c when used is in 2d * packets/deactivated) c when used is in 2d
*/ */
void SetHardCodedPosition(uint16_t r, uint16_t c); void SetHardCodedPosition(uint16_t r, uint16_t c);
@ -125,7 +125,7 @@ class Listener : private virtual slsDetectorDefs, public ThreadObject {
int *actualUDPSocketBufferSize; int *actualUDPSocketBufferSize;
uint32_t *framesPerFile; uint32_t *framesPerFile;
frameDiscardPolicy *frameDiscardMode; frameDiscardPolicy *frameDiscardMode;
bool *activated; bool activated{false};
bool *detectorDataStream; bool *detectorDataStream;
bool *silentMode; bool *silentMode;
@ -135,7 +135,7 @@ class Listener : private virtual slsDetectorDefs, public ThreadObject {
uint16_t row{0}; uint16_t row{0};
/** column hardcoded as 2D, /** column hardcoded as 2D,
* deactivated eiger/missing packets (eiger/jungfrau sends 2d pos) **/ * deactivated/missing packets (eiger/jungfrau sends 2d pos) **/
uint16_t column{0}; uint16_t column{0};
// acquisition start // acquisition start

View File

@ -109,6 +109,17 @@ void MasterAttributes::GetCommonBinaryAttributes(
w->String(sls::ToString(scanParams).c_str()); w->String(sls::ToString(scanParams).c_str());
w->Key("Total Frames"); w->Key("Total Frames");
w->Uint64(totalFrames); w->Uint64(totalFrames);
w->Key("Receiver Roi");
w->StartObject();
w->Key("xmin");
w->Uint(receiverRoi.xmin);
w->Key("xmax");
w->Uint(receiverRoi.xmax);
w->Key("ymin");
w->Uint(receiverRoi.ymin);
w->Key("ymax");
w->Uint(receiverRoi.ymax);
w->EndObject();
} }
void MasterAttributes::GetFinalBinaryAttributes( void MasterAttributes::GetFinalBinaryAttributes(
@ -274,6 +285,34 @@ void MasterAttributes::WriteCommonHDF5Attributes(H5File *fd, Group *group) {
PredType::STD_U64LE, dataspace); PredType::STD_U64LE, dataspace);
dataset.write(&totalFrames, PredType::STD_U64LE); dataset.write(&totalFrames, PredType::STD_U64LE);
} }
// Receiver Roi xmin
{
DataSpace dataspace = DataSpace(H5S_SCALAR);
DataSet dataset = group->createDataSet("receiver roi xmin",
PredType::NATIVE_INT, dataspace);
dataset.write(&receiverRoi.xmin, PredType::NATIVE_INT);
}
// Receiver Roi xmax
{
DataSpace dataspace = DataSpace(H5S_SCALAR);
DataSet dataset = group->createDataSet("receiver roi xmax",
PredType::NATIVE_INT, dataspace);
dataset.write(&receiverRoi.xmax, PredType::NATIVE_INT);
}
// Receiver Roi ymin
{
DataSpace dataspace = DataSpace(H5S_SCALAR);
DataSet dataset = group->createDataSet("receiver roi ymin",
PredType::NATIVE_INT, dataspace);
dataset.write(&receiverRoi.ymin, PredType::NATIVE_INT);
}
// Receiver Roi ymax
{
DataSpace dataspace = DataSpace(H5S_SCALAR);
DataSet dataset = group->createDataSet("receiver roi ymax",
PredType::NATIVE_INT, dataspace);
dataset.write(&receiverRoi.ymax, PredType::NATIVE_INT);
}
} }
void MasterAttributes::WriteFinalHDF5Attributes(H5File *fd, Group *group) { void MasterAttributes::WriteFinalHDF5Attributes(H5File *fd, Group *group) {
@ -343,14 +382,14 @@ void MasterAttributes::WriteHDF5ROI(H5File *fd, Group *group) {
DataSpace dataspace = DataSpace(H5S_SCALAR); DataSpace dataspace = DataSpace(H5S_SCALAR);
DataSet dataset = DataSet dataset =
group->createDataSet("roi xmin", PredType::NATIVE_INT, dataspace); group->createDataSet("roi xmin", PredType::NATIVE_INT, dataspace);
dataset.write(&roi.xmin, PredType::NATIVE_INT); dataset.write(&detectorRoi.xmin, PredType::NATIVE_INT);
} }
// Roi xmax // Roi xmax
{ {
DataSpace dataspace = DataSpace(H5S_SCALAR); DataSpace dataspace = DataSpace(H5S_SCALAR);
DataSet dataset = DataSet dataset =
group->createDataSet("roi xmax", PredType::NATIVE_INT, dataspace); group->createDataSet("roi xmax", PredType::NATIVE_INT, dataspace);
dataset.write(&roi.xmax, PredType::NATIVE_INT); dataset.write(&detectorRoi.xmax, PredType::NATIVE_INT);
} }
} }
@ -533,8 +572,13 @@ void MasterAttributes::GetGotthardBinaryAttributes(
w->String(sls::ToString(exptime).c_str()); w->String(sls::ToString(exptime).c_str());
w->Key("Period"); w->Key("Period");
w->String(sls::ToString(period).c_str()); w->String(sls::ToString(period).c_str());
w->Key("Roi (xmin, xmax)"); w->Key("Detector Roi");
w->String(sls::ToString(roi).c_str()); w->StartObject();
w->Key("xmin");
w->Uint(detectorRoi.xmin);
w->Key("xmax");
w->Uint(detectorRoi.xmax);
w->EndObject();
}; };
#ifdef HDF5C #ifdef HDF5C

View File

@ -7,8 +7,8 @@
#include "sls/logger.h" #include "sls/logger.h"
#include "sls/sls_detector_defs.h" #include "sls/sls_detector_defs.h"
#include <rapidjson/stringbuffer.h>
#include <rapidjson/prettywriter.h> #include <rapidjson/prettywriter.h>
#include <rapidjson/stringbuffer.h>
#ifdef HDF5C #ifdef HDF5C
#include "H5Cpp.h" #include "H5Cpp.h"
@ -54,7 +54,8 @@ class MasterAttributes {
uint32_t digitalSamples{0}; uint32_t digitalSamples{0};
uint32_t dbitoffset{0}; uint32_t dbitoffset{0};
uint64_t dbitlist{0}; uint64_t dbitlist{0};
slsDetectorDefs::ROI roi{}; slsDetectorDefs::ROI detectorRoi{};
slsDetectorDefs::ROI receiverRoi{};
uint32_t counterMask{0}; uint32_t counterMask{0};
std::array<ns, 3> exptimeArray{}; std::array<ns, 3> exptimeArray{};
std::array<ns, 3> gateDelayArray{}; std::array<ns, 3> gateDelayArray{};
@ -65,15 +66,16 @@ class MasterAttributes {
MasterAttributes() = default; MasterAttributes() = default;
~MasterAttributes() = default; ~MasterAttributes() = default;
void GetBinaryAttributes(rapidjson::PrettyWriter<rapidjson::StringBuffer> *w); void
GetBinaryAttributes(rapidjson::PrettyWriter<rapidjson::StringBuffer> *w);
#ifdef HDF5C #ifdef HDF5C
void WriteHDF5Attributes(H5File *fd, Group *group); void WriteHDF5Attributes(H5File *fd, Group *group);
#endif #endif
void void GetCommonBinaryAttributes(
GetCommonBinaryAttributes(rapidjson::PrettyWriter<rapidjson::StringBuffer> *w); rapidjson::PrettyWriter<rapidjson::StringBuffer> *w);
void void GetFinalBinaryAttributes(
GetFinalBinaryAttributes(rapidjson::PrettyWriter<rapidjson::StringBuffer> *w); rapidjson::PrettyWriter<rapidjson::StringBuffer> *w);
#ifdef HDF5C #ifdef HDF5C
void WriteCommonHDF5Attributes(H5File *fd, Group *group); void WriteCommonHDF5Attributes(H5File *fd, Group *group);
void WriteFinalHDF5Attributes(H5File *fd, Group *group); void WriteFinalHDF5Attributes(H5File *fd, Group *group);
@ -104,43 +106,44 @@ class MasterAttributes {
void WriteHDF5DbitList(H5File *fd, Group *group); void WriteHDF5DbitList(H5File *fd, Group *group);
#endif #endif
void void GetGotthardBinaryAttributes(
GetGotthardBinaryAttributes(rapidjson::PrettyWriter<rapidjson::StringBuffer> *w); rapidjson::PrettyWriter<rapidjson::StringBuffer> *w);
#ifdef HDF5C #ifdef HDF5C
void WriteGotthardHDF5Attributes(H5File *fd, Group *group); void WriteGotthardHDF5Attributes(H5File *fd, Group *group);
#endif #endif
void void GetJungfrauBinaryAttributes(
GetJungfrauBinaryAttributes(rapidjson::PrettyWriter<rapidjson::StringBuffer> *w); rapidjson::PrettyWriter<rapidjson::StringBuffer> *w);
#ifdef HDF5C #ifdef HDF5C
void WriteJungfrauHDF5Attributes(H5File *fd, Group *group); void WriteJungfrauHDF5Attributes(H5File *fd, Group *group);
#endif #endif
void void GetEigerBinaryAttributes(
GetEigerBinaryAttributes(rapidjson::PrettyWriter<rapidjson::StringBuffer> *w); rapidjson::PrettyWriter<rapidjson::StringBuffer> *w);
#ifdef HDF5C #ifdef HDF5C
void WriteEigerHDF5Attributes(H5File *fd, Group *group); void WriteEigerHDF5Attributes(H5File *fd, Group *group);
#endif #endif
void void GetMythen3BinaryAttributes(
GetMythen3BinaryAttributes(rapidjson::PrettyWriter<rapidjson::StringBuffer> *w); rapidjson::PrettyWriter<rapidjson::StringBuffer> *w);
#ifdef HDF5C #ifdef HDF5C
void WriteMythen3HDF5Attributes(H5File *fd, Group *group); void WriteMythen3HDF5Attributes(H5File *fd, Group *group);
#endif #endif
void void GetGotthard2BinaryAttributes(
GetGotthard2BinaryAttributes(rapidjson::PrettyWriter<rapidjson::StringBuffer> *w); rapidjson::PrettyWriter<rapidjson::StringBuffer> *w);
#ifdef HDF5C #ifdef HDF5C
void WriteGotthard2HDF5Attributes(H5File *fd, Group *group); void WriteGotthard2HDF5Attributes(H5File *fd, Group *group);
#endif #endif
void void GetMoenchBinaryAttributes(
GetMoenchBinaryAttributes(rapidjson::PrettyWriter<rapidjson::StringBuffer> *w); rapidjson::PrettyWriter<rapidjson::StringBuffer> *w);
#ifdef HDF5C #ifdef HDF5C
void WriteMoenchHDF5Attributes(H5File *fd, Group *group); void WriteMoenchHDF5Attributes(H5File *fd, Group *group);
#endif #endif
void GetCtbBinaryAttributes(rapidjson::PrettyWriter<rapidjson::StringBuffer> *w); void
GetCtbBinaryAttributes(rapidjson::PrettyWriter<rapidjson::StringBuffer> *w);
#ifdef HDF5C #ifdef HDF5C
void WriteCtbHDF5Attributes(H5File *fd, Group *group); void WriteCtbHDF5Attributes(H5File *fd, Group *group);
#endif #endif

View File

@ -17,8 +17,8 @@
// files // files
// versions // versions
#define HDF5_WRITER_VERSION (6.4) // 1 decimal places #define HDF5_WRITER_VERSION (6.5) // 1 decimal places
#define BINARY_WRITER_VERSION (7.0) // 1 decimal places #define BINARY_WRITER_VERSION (7.1) // 1 decimal places
#define MAX_FRAMES_PER_FILE 20000 #define MAX_FRAMES_PER_FILE 20000
#define SHORT_MAX_FRAMES_PER_FILE 100000 #define SHORT_MAX_FRAMES_PER_FILE 100000

View File

@ -49,9 +49,6 @@
// ctb/ moench 1g udp (read from fifo) // ctb/ moench 1g udp (read from fifo)
#define UDP_PACKET_DATA_BYTES (1344) #define UDP_PACKET_DATA_BYTES (1344)
/** maximum rois */
#define MAX_ROIS 100
/** maximum trim en */ /** maximum trim en */
#define MAX_TRIMEN 100 #define MAX_TRIMEN 100
@ -172,13 +169,38 @@ class slsDetectorDefs {
struct ROI { struct ROI {
int xmin{-1}; int xmin{-1};
int xmax{-1}; int xmax{-1};
int ymin{-1};
int ymax{-1};
ROI() = default; ROI() = default;
ROI(int xmin, int xmax) : xmin(xmin), xmax(xmax){}; ROI(int xmin, int xmax) : xmin(xmin), xmax(xmax){};
ROI(int xmin, int xmax, int ymin, int ymax)
: xmin(xmin), xmax(xmax), ymin(ymin), ymax(ymax){};
constexpr std::array<int, 4> getIntArray() const {
return std::array<int, 4> ({xmin, xmax, ymin, ymax});
}
constexpr bool completeRoi() const {
return (xmin == -1 && xmax == -1 && ymin == -1 && ymax == -1);
}
constexpr bool noRoi() const {
return (xmin == 0 && xmax == 0 && ymin == 0 && ymax == 0);
}
void setNoRoi() {
xmin = 0;
xmax = 0;
ymin = 0;
ymax = 0;
}
constexpr bool operator==(const ROI &other) const {
return ((xmin == other.xmin) && (xmax == other.xmax) &&
(ymin == other.ymin) && (ymax == other.ymax));
}
} __attribute__((packed)); } __attribute__((packed));
#else #else
typedef struct { typedef struct {
int xmin; int xmin;
int xmax; int xmax;
int ymin;
int ymax;
} ROI; } ROI;
#endif #endif

View File

@ -279,7 +279,7 @@ enum detFuncs {
F_LOCK_RECEIVER, F_LOCK_RECEIVER,
F_GET_LAST_RECEIVER_CLIENT_IP, F_GET_LAST_RECEIVER_CLIENT_IP,
F_GET_RECEIVER_VERSION, F_GET_RECEIVER_VERSION,
F_RECEIVER_SET_ROI, F_RECEIVER_SET_DETECTOR_ROI,
F_RECEIVER_SET_NUM_FRAMES, F_RECEIVER_SET_NUM_FRAMES,
F_SET_RECEIVER_NUM_TRIGGERS, F_SET_RECEIVER_NUM_TRIGGERS,
F_SET_RECEIVER_NUM_BURSTS, F_SET_RECEIVER_NUM_BURSTS,
@ -375,6 +375,9 @@ enum detFuncs {
F_RECEIVER_SET_DATASTREAM, F_RECEIVER_SET_DATASTREAM,
F_GET_RECEIVER_ARPING, F_GET_RECEIVER_ARPING,
F_SET_RECEIVER_ARPING, F_SET_RECEIVER_ARPING,
F_RECEIVER_GET_RECEIVER_ROI,
F_RECEIVER_SET_RECEIVER_ROI,
F_RECEIVER_SET_RECEIVER_ROI_METADATA,
NUM_REC_FUNCTIONS NUM_REC_FUNCTIONS
}; };
@ -652,7 +655,7 @@ const char* getFunctionNameFromEnum(enum detFuncs func) {
case F_LOCK_RECEIVER: return "F_LOCK_RECEIVER"; case F_LOCK_RECEIVER: return "F_LOCK_RECEIVER";
case F_GET_LAST_RECEIVER_CLIENT_IP: return "F_GET_LAST_RECEIVER_CLIENT_IP"; case F_GET_LAST_RECEIVER_CLIENT_IP: return "F_GET_LAST_RECEIVER_CLIENT_IP";
case F_GET_RECEIVER_VERSION: return "F_GET_RECEIVER_VERSION"; case F_GET_RECEIVER_VERSION: return "F_GET_RECEIVER_VERSION";
case F_RECEIVER_SET_ROI: return "F_RECEIVER_SET_ROI"; case F_RECEIVER_SET_DETECTOR_ROI: return "F_RECEIVER_SET_DETECTOR_ROI";
case F_RECEIVER_SET_NUM_FRAMES: return "F_RECEIVER_SET_NUM_FRAMES"; case F_RECEIVER_SET_NUM_FRAMES: return "F_RECEIVER_SET_NUM_FRAMES";
case F_SET_RECEIVER_NUM_TRIGGERS: return "F_SET_RECEIVER_NUM_TRIGGERS"; case F_SET_RECEIVER_NUM_TRIGGERS: return "F_SET_RECEIVER_NUM_TRIGGERS";
case F_SET_RECEIVER_NUM_BURSTS: return "F_SET_RECEIVER_NUM_BURSTS"; case F_SET_RECEIVER_NUM_BURSTS: return "F_SET_RECEIVER_NUM_BURSTS";
@ -748,6 +751,9 @@ const char* getFunctionNameFromEnum(enum detFuncs func) {
case F_RECEIVER_SET_DATASTREAM: return "F_RECEIVER_SET_DATASTREAM"; case F_RECEIVER_SET_DATASTREAM: return "F_RECEIVER_SET_DATASTREAM";
case F_GET_RECEIVER_ARPING: return "F_GET_RECEIVER_ARPING"; case F_GET_RECEIVER_ARPING: return "F_GET_RECEIVER_ARPING";
case F_SET_RECEIVER_ARPING: return "F_SET_RECEIVER_ARPING"; case F_SET_RECEIVER_ARPING: return "F_SET_RECEIVER_ARPING";
case F_RECEIVER_GET_RECEIVER_ROI: return "F_RECEIVER_GET_RECEIVER_ROI";
case F_RECEIVER_SET_RECEIVER_ROI: return "F_RECEIVER_SET_RECEIVER_ROI";
case F_RECEIVER_SET_RECEIVER_ROI_METADATA: return "F_RECEIVER_SET_RECEIVER_ROI_METADATA";
case NUM_REC_FUNCTIONS: return "NUM_REC_FUNCTIONS"; case NUM_REC_FUNCTIONS: return "NUM_REC_FUNCTIONS";
default: return "Unknown Function"; default: return "Unknown Function";

View File

@ -5,11 +5,10 @@
#define APILIB 0x220408 #define APILIB 0x220408
#define APIRECEIVER 0x220408 #define APIRECEIVER 0x220408
#define APIGUI 0x220328 #define APIGUI 0x220328
#define APICTB 0x220516
#define APICTB 0x220428 #define APIGOTTHARD 0x220516
#define APIGOTTHARD 0x220428 #define APIGOTTHARD2 0x220516
#define APIGOTTHARD2 0x220428 #define APIJUNGFRAU 0x220516
#define APIJUNGFRAU 0x220428 #define APIMYTHEN3 0x220516
#define APIMOENCH 0x220427 #define APIMOENCH 0x220503
#define APIEIGER 0x220428 #define APIEIGER 0x220516
#define APIMYTHEN3 0x220510

View File

@ -31,8 +31,10 @@ ServerSocket::ServerSocket(int port)
if (bind(getSocketId(), (struct sockaddr *)&serverAddr, if (bind(getSocketId(), (struct sockaddr *)&serverAddr,
sizeof(serverAddr)) != 0) { sizeof(serverAddr)) != 0) {
close(); close();
throw sls::SocketError("Server ERROR: cannot bind socket. Please check " throw sls::SocketError(
"if another instance is running."); std::string("Server ERROR: cannot bind socket with port number ") +
std::to_string(port) +
std::string(". Please check if another instance is running."));
} }
if (listen(getSocketId(), DEFAULT_BACKLOG) != 0) { if (listen(getSocketId(), DEFAULT_BACKLOG) != 0) {
close(); close();

View File

@ -17,7 +17,11 @@ std::ostream &operator<<(std::ostream &os, const slsDetectorDefs::xy &coord) {
std::string ToString(const slsDetectorDefs::ROI &roi) { std::string ToString(const slsDetectorDefs::ROI &roi) {
std::ostringstream oss; std::ostringstream oss;
oss << '[' << roi.xmin << ", " << roi.xmax << ']'; oss << '[' << roi.xmin << ", " << roi.xmax;
if (roi.ymin != -1 || roi.ymax != -1) {
oss << ", " << roi.ymin << ", " << roi.ymax;
}
oss << ']';
return oss.str(); return oss.str();
} }

View File

@ -131,82 +131,57 @@ int ZmqSocket::Connect() {
} }
int ZmqSocket::SendHeader(int index, zmqHeader header) { int ZmqSocket::SendHeader(int index, zmqHeader header) {
std::ostringstream oss;
oss << "{\"jsonversion\":" << header.jsonversion
<< ", \"bitmode\":" << header.dynamicRange
<< ", \"fileIndex\":" << header.fileIndex << ", \"detshape\":["
<< header.ndetx << ", " << header.ndety << ']' << ", \"shape\":["
<< header.npixelsx << ", " << header.npixelsy << ']'
<< ", \"size\":" << header.imageSize
<< ", \"acqIndex\":" << header.acqIndex
<< ", \"frameIndex\":" << header.frameIndex
<< ", \"progress\":" << header.progress << ", \"fname\":\""
<< header.fname << '\"' << ", \"data\":" << (header.data ? 1 : 0)
<< ", \"completeImage\":" << (header.completeImage ? 1 : 0)
/** Json Header Format */ << ", \"frameNumber\":" << header.frameNumber
const char jsonHeaderFormat[] = "{" << ", \"expLength\":" << header.expLength
"\"jsonversion\":%u, " << ", \"packetNumber\":" << header.packetNumber
"\"bitmode\":%u, " << ", \"bunchId\":" << header.bunchId
"\"fileIndex\":%lu, " << ", \"timestamp\":" << header.timestamp
"\"detshape\":[%u, %u], " << ", \"modId\":" << header.modId << ", \"row\":" << header.row
"\"shape\":[%u, %u], " << ", \"column\":" << header.column
"\"size\":%u, " << ", \"reserved\":" << header.reserved
"\"acqIndex\":%lu, " << ", \"debug\":" << header.debug
"\"frameIndex\":%lu, " << ", \"roundRNumber\":" << header.roundRNumber
"\"progress\":%lf, " << ", \"detType\":" << static_cast<int>(header.detType)
"\"fname\":\"%s\", " << ", \"version\":"
"\"data\": %d, " << static_cast<int>(header.version)
"\"completeImage\": %d, "
"\"frameNumber\":%lu, "
"\"expLength\":%u, "
"\"packetNumber\":%u, "
"\"bunchId\":%lu, "
"\"timestamp\":%lu, "
"\"modId\":%u, "
"\"row\":%u, "
"\"column\":%u, "
"\"reserved\":%u, "
"\"debug\":%u, "
"\"roundRNumber\":%u, "
"\"detType\":%u, "
"\"version\":%u, "
// additional stuff // additional stuff
"\"flipRows\":%u, " << ", \"flipRows\":" << header.flipRows << ", \"quad\":" << header.quad;
"\"quad\":%u"
; //"}\n";
memset(header_buffer.get(), '\0', MAX_STR_LENGTH); // TODO! Do we need this
sprintf(header_buffer.get(), jsonHeaderFormat, header.jsonversion,
header.dynamicRange, header.fileIndex, header.ndetx, header.ndety,
header.npixelsx, header.npixelsy, header.imageSize, header.acqIndex,
header.frameIndex, header.progress, header.fname.c_str(),
header.data ? 1 : 0, header.completeImage ? 1 : 0,
header.frameNumber, header.expLength, header.packetNumber,
header.bunchId, header.timestamp, header.modId, header.row,
header.column, header.reserved, header.debug, header.roundRNumber,
header.detType, header.version,
// additional stuff
header.flipRows, header.quad);
if (!header.addJsonHeader.empty()) { if (!header.addJsonHeader.empty()) {
strcat(header_buffer.get(), ", "); oss << ", \"addJsonHeader\": {";
strcat(header_buffer.get(), "\"addJsonHeader\": {");
for (auto it = header.addJsonHeader.begin(); for (auto it = header.addJsonHeader.begin();
it != header.addJsonHeader.end(); ++it) { it != header.addJsonHeader.end(); ++it) {
if (it != header.addJsonHeader.begin()) { if (it != header.addJsonHeader.begin()) {
strcat(header_buffer.get(), ", "); oss << ", ";
} }
strcat(header_buffer.get(), "\""); oss << "\"" << it->first.c_str() << "\":\"" << it->second.c_str()
strcat(header_buffer.get(), it->first.c_str()); << "\"";
strcat(header_buffer.get(), "\":\"");
strcat(header_buffer.get(), it->second.c_str());
strcat(header_buffer.get(), "\"");
} }
strcat(header_buffer.get(), " } "); oss << " } ";
} }
oss << "}\n";
strcat(header_buffer.get(), "}\n"); std::string message = oss.str();
int length = strlen(header_buffer.get()); int length = message.length();
#ifdef ZMQ_DETAIL
#ifdef VERBOSE
// if(!index) // if(!index)
cprintf(BLUE, "%d : Streamer: buf: %s\n", index, buf); LOG(logINFOBLUE) << index << " : Streamer: buf: " << message;
#endif #endif
if (zmq_send(sockfd.socketDescriptor, header_buffer.get(), length, if (zmq_send(sockfd.socketDescriptor, message.c_str(), length,
header.data ? ZMQ_SNDMORE : 0) < 0) { header.data ? ZMQ_SNDMORE : 0) < 0) {
PrintError(); PrintError();
return 0; return 0;
@ -232,13 +207,13 @@ int ZmqSocket::ReceiveHeader(const int index, zmqHeader &zHeader,
if (bytes_received > 0) { if (bytes_received > 0) {
#ifdef ZMQ_DETAIL #ifdef ZMQ_DETAIL
cprintf(BLUE, "Header %d [%d] Length: %d Header:%s \n", index, portno, cprintf(BLUE, "Header %d [%d] Length: %d Header:%s \n", index, portno,
bytes_received, buffer.data()); bytes_received, header_buffer.get());
#endif #endif
if (ParseHeader(index, bytes_received, header_buffer.get(), zHeader, if (ParseHeader(index, bytes_received, header_buffer.get(), zHeader,
version)) { version)) {
#ifdef ZMQ_DETAIL #ifdef ZMQ_DETAIL
cprintf(RED, "Parsed Header %d [%d] Length: %d Header:%s \n", index, cprintf(RED, "Parsed Header %d [%d] Length: %d Header:%s \n", index,
portno, bytes_received, buffer.data()); portno, bytes_received, header_buffer.get());
#endif #endif
if (!zHeader.data) { if (!zHeader.data) {
#ifdef ZMQ_DETAIL #ifdef ZMQ_DETAIL
@ -333,7 +308,7 @@ int ZmqSocket::ReceiveData(const int index, char *buf, const int size) {
memset(buf + length, 0xFF, size - length); memset(buf + length, 0xFF, size - length);
} else { } else {
LOG(logERROR) << "Received weird packet size " << length LOG(logERROR) << "Received weird packet size " << length
<< " for socket " << index; << " (expected " << size << ") for socket " << index;
memset(buf, 0xFF, size); memset(buf, 0xFF, size);
} }

View File

@ -227,14 +227,19 @@ TEST_CASE("Detector type") {
TEST_CASE("Formatting slsDetectorDefs::ROI") { TEST_CASE("Formatting slsDetectorDefs::ROI") {
slsDetectorDefs::ROI roi(5, 159); slsDetectorDefs::ROI roi(5, 159);
REQUIRE(ToString(roi) == "[5, 159]"); REQUIRE(ToString(roi) == "[5, 159]");
slsDetectorDefs::ROI roi1(5, 159, 6, 170);
REQUIRE(ToString(roi1) == "[5, 159, 6, 170]");
} }
TEST_CASE("Streaming of slsDetectorDefs::ROI") { TEST_CASE("Streaming of slsDetectorDefs::ROI") {
using namespace sls; using namespace sls;
slsDetectorDefs::ROI roi(-10, 1); slsDetectorDefs::ROI roi(-10, 1);
std::ostringstream oss; std::ostringstream oss, oss1;
oss << roi; oss << roi;
REQUIRE(oss.str() == "[-10, 1]"); REQUIRE(oss.str() == "[-10, 1]");
slsDetectorDefs::ROI roi1(-10, 1, 5, 11);
oss1 << roi1;
REQUIRE(oss1.str() == "[-10, 1, 5, 11]");
} }
TEST_CASE("std::array") { TEST_CASE("std::array") {