This commit is contained in:
maliakal_d 2020-09-21 17:09:39 +02:00
parent 569c014d3c
commit 54ca9f7ebb
6 changed files with 174 additions and 70 deletions

View File

@ -131,7 +131,15 @@ class Detector(CppDetectorApi):
@property
def hostname(self):
"""Frees shared memory and sets hostname (or IP address) of all modules concatenated by + """
"""Frees shared memory and sets hostname (or IP address) of all modules concatenated by +
Virtual servers can already use the port in hostname separated by ':' and ports incremented by 2 to accomodate the stop server as well.
Example
-------
>>> d.hostname = 'beb031+beb032+'
>>> d.hostname = 'localhost:1912+localhost:1914+'
>>> d.hostname
['localhost']
"""
return self.getHostname()
@hostname.setter
@ -165,16 +173,35 @@ class Detector(CppDetectorApi):
@property
def firmwareversion(self):
"""
Fimware version of detector in format [0xYYMMDD] or an increasing 2 digit number for Eiger.
Example
-------
>>> hex(d.firmwareversion)
'0x200910'
"""
return element_if_equal(self.getFirmwareVersion())
@property
def detectorserverversion(self):
"""
On-board detector server software version in format [0xYYMMDD]
Example
-------
>>> hex(d.detectorserverversion)
'0x200910'
"""
# TODO! handle hex print
return element_if_equal(self.getDetectorServerVersion())
@property
def clientversion(self):
"""Client software version in format [YYMMDD]"""
"""Client software version in format [YYMMDD]
Example
-------
>>> hex(d.clientversion)
'0x200810'
"""
return self.getClientVersion()
@property
@ -206,6 +233,7 @@ class Detector(CppDetectorApi):
@property
def drlist(self):
"""List of possible dynamic ranges for this detector"""
return self.getDynamicRangeList()
@property
@ -219,6 +247,18 @@ class Detector(CppDetectorApi):
@property
def detsize(self):
"""
Sets the detector size in both dimensions (number of channels).
Note
-----
This value is used to calculate row and column positions for each module and included into udp data packet header. \n
By default, it adds modules in y dimension for 2d detectors and in x dimension for 1d detectors.
:setter: Not implemented
Example
-------
>>> d.detsize
Geometry(x=3840, y=1)
"""
return to_geo(self.getDetectorSize())
@property
@ -247,8 +287,8 @@ class Detector(CppDetectorApi):
Note
-----
Cannot be set in modular level. ????
In scan mode, number of frames is set to number of steps.
Cannot be set in modular level. \n
In scan mode, number of frames is set to number of steps. \n
[Gotthard2] Burst mode has a maximum of 2720 frames.
"""
return element_if_equal(self.getNumberOfFrames())
@ -260,6 +300,10 @@ class Detector(CppDetectorApi):
@property
@element
def framesl(self):
"""
[Gotthard][Jungfrau][Mythen3][Gotthard2][CTB][Moench] Number of frames left in acquisition.\n
[Gotthard2] only in continuous mode.
"""
return self.getNumberOfFramesLeft()
@property
@ -393,9 +437,9 @@ class Detector(CppDetectorApi):
Example
-----------
>>> d.delay
>>> d.delayl
181.23
>>> d.getDelayAfterTrigger()
>>> d.getDelayAfterTriggerLeft()
[datetime.timedelta(seconds=181, microseconds=230000)]
"""
return ut.reduce_time(self.getDelayAfterTriggerLeft())
@ -623,7 +667,11 @@ class Detector(CppDetectorApi):
@property
@element
def findex(self):
"""File or Acquisition index in receiver."""
"""File or Acquisition index in receiver.
Note
----
File name: [file name prefix]_d[detector index]_f[sub file index]_[acquisition/file index].[raw/h5].
"""
return self.getAcquisitionIndex()
@findex.setter
@ -651,8 +699,7 @@ class Detector(CppDetectorApi):
@property
def fpath(self):
"""Directory where output data files are written in receiver.
"""Directory where output data files are written in receiver. Default is "/".
Note
----
If path does not exist, it will try to create it.
@ -1846,6 +1893,11 @@ class Detector(CppDetectorApi):
@property
@element
def filter(self):
"""[Gotthard2] Set filter resistor.
Note
----
Default is 0. Options: 0-3.
"""
return self.getFilter()
@filter.setter
@ -2636,6 +2688,19 @@ class Detector(CppDetectorApi):
@property
def clkdiv(self):
"""
[Gotthard2][Mythen3] Clock Divider of 5 clocks. Must be greater than 1.
Example
-------
>>> d.clkdiv[0] = 20
>>> d.clkdiv
0: 20
1: 10
2: 20
3: 10
4: 10
5: 5
"""
return ClkDivProxy(self)
@ -2645,6 +2710,18 @@ class Detector(CppDetectorApi):
@property
def exptimel(self):
"""[Gotthard] Exposure time left for current frame.
Note
-----
:getter: always returns in seconds. To get in datetime.delta, use getExptimeLeft
Example
-----------
>>> d.exptimel
181.23
>>> d.getExptimeLeft()
[datetime.timedelta(seconds=181, microseconds=230000)]
"""
t = self.getExptimeLeft()
return reduce_time(t)
@ -2656,6 +2733,7 @@ class Detector(CppDetectorApi):
@property
@element
def gates(self):
"""[Mythen3] Number of external gates in gating or trigger_gating mode (external gating)."""
return self.getNumberOfGates()
@gates.setter
@ -2665,6 +2743,16 @@ class Detector(CppDetectorApi):
@property
def clkfreq(self):
"""
[Gotthard2][Mythen3] Frequency of clock in Hz.
Note
-----
:setter: Not implemented. Use clkdiv to set frequency
Example
-------
>>> d.clkfreq[0]
50000000
"""
return ClkFreqProxy(self)
"""

View File

@ -4223,6 +4223,7 @@ int copy_detector_server(int file_des) {
strcat(cmd, sname);
executeCommand(cmd, retvals, logDEBUG1);
#if !defined(GOTTHAR2D) && !defined(MYTHEN3D)
// edit /etc/inittab
// find line numbers in /etc/inittab where DetectorServer
strcpy(cmd, "sed -n '/DetectorServer/=' /etc/inittab");
@ -4247,6 +4248,7 @@ int copy_detector_server(int file_des) {
executeCommand(cmd, retvals, logDEBUG1);
LOG(logINFO, ("/etc/inittab modified to have %s\n", sname));
#endif
}
}
#endif

View File

@ -58,7 +58,7 @@ class Detector {
Result<std::string> getHostname(Positions pos = {}) const;
/**Frees shared memory, adds detectors to the list */
/**Frees shared memory, adds detectors to the list. */
void setHostname(const std::vector<std::string> &hostname);
/** connects to n servers at local host starting at specific control port */
@ -98,8 +98,10 @@ class Detector {
defs::xy getDetectorSize() const;
/**
* Sets the detector size in both dimensions. \n
* This value is used to calculate row and column positions for each module.
* Sets the detector size in both dimensions (number of channels). \n
* This value is used to calculate row and column positions for each module
* and included into udp data packet header. \n By default, it adds modules
* in y dimension for 2d detectors and in x dimension for 1d detectors.
*/
void setDetectorSize(const defs::xy value);
@ -183,7 +185,8 @@ class Detector {
Result<int64_t> getNumberOfFrames(Positions pos = {}) const;
/** In trigger mode, number of frames per trigger. In scan mode, number of
* frames is set to number of steps */
* frames is set to number of steps \n [Gotthard2] Burst mode has a maximum
* of 2720 frames. */
void setNumberOfFrames(int64_t value);
Result<int64_t> getNumberOfTriggers(Positions pos = {}) const;
@ -228,8 +231,8 @@ class Detector {
Result<int> getDynamicRange(Positions pos = {}) const;
/**
* [Eiger] Options: 4, 8, 16, 32. If i is 32, also sets clkdivider to 2, if
* 16, sets clkdivider to 1 \n [Mythen3] Options: 8, 16, 32 \n
* [Eiger] Options: 4, 8, 16, 32. If i is 32, also sets clkdivider to 2,
* else sets clkdivider to 1 \n [Mythen3] Options: 8, 16, 32 \n
* [Jungfrau][Gotthard][Ctb][Moench][Mythen3][Gotthard2] 16
*/
void setDynamicRange(int value);
@ -313,7 +316,7 @@ class Detector {
/** [Mythen3][Gotthard2] */
Result<int> getClockPhase(int clkIndex, Positions pos = {});
/** [Mythen3][Gotthard2] */
/** [Mythen3][Gotthard2] absolute phase shift */
void setClockPhase(int clkIndex, int value, Positions pos = {});
/** [Mythen3][Gotthard2] */
@ -328,7 +331,7 @@ class Detector {
/** [Mythen3][Gotthard2] */
Result<int> getClockDivider(int clkIndex, Positions pos = {});
/** [Mythen3][Gotthard2] */
/** [Mythen3][Gotthard2] Must be greater than 1. */
void setClockDivider(int clkIndex, int value, Positions pos = {});
Result<int> getHighVoltage(Positions pos = {}) const;
@ -740,7 +743,7 @@ class Detector {
Result<std::string> getFilePath(Positions pos = {}) const;
/** If path does not exist, it will try to create it */
/** Default is "/"If path does not exist, it will try to create it */
void setFilePath(const std::string &fpath, Positions pos = {});
Result<std::string> getFileNamePrefix(Positions pos = {}) const;
@ -753,7 +756,10 @@ class Detector {
Result<int64_t> getAcquisitionIndex(Positions pos = {}) const;
/** file or Acquisition index in receiver */
/** file or Acquisition index in receiver \n
* File name: [file name prefix]_d[detector index]_f[sub file
* index]_[acquisition/file index].[raw/h5].
*/
void setAcquisitionIndex(int64_t i, Positions pos = {});
Result<bool> getFileWrite(Positions pos = {}) const;
@ -908,7 +914,7 @@ class Detector {
/** [Eiger] */
Result<bool> getBottom(Positions pos = {}) const;
/** [Eiger] for client call back (gui) purposes */
/** [Eiger] for client call back (gui) purposes to flip bottom image */
void setBottom(bool value, Positions pos = {});
/**[Eiger] Returns energies in eV where the module is trimmed */
@ -1154,7 +1160,7 @@ class Detector {
/** [Gotthard2] */
Result<int> getFilter(Positions pos = {}) const;
/** default 0 */
/** [Gotthard2] Set filter resister. Options: 0-3. Default: 0 */
void setFilter(int value, Positions pos = {});
/** [Gotthard2] */
@ -1179,7 +1185,8 @@ class Detector {
Result<int> getADCConfiguration(const int chipIndex, const int adcIndex,
Positions pos = {}) const;
/** [Gotthard2] */
/** [Gotthard2] configures one chip at a time for specific adc, chipIndex
* and adcIndex is -1 for all */
void setADCConfiguration(const int chipIndex, const int adcIndex,
const int value, Positions pos = {});
@ -1343,13 +1350,13 @@ class Detector {
/** [CTB] */
Result<int> getExternalSamplingSource(Positions pos = {}) const;
/** [CTB] Value between 0-63 */
/** [CTB] Value between 0-63 \n For advanced users only.*/
void setExternalSamplingSource(int value, Positions pos = {});
/** [CTB] */
Result<bool> getExternalSampling(Positions pos = {}) const;
/** [CTB] */
/** [CTB] For advanced users only. */
void setExternalSampling(bool value, Positions pos = {});
/** [CTB] */
@ -1510,9 +1517,10 @@ class Detector {
void resetFPGA(Positions pos = {});
/** [Jungfrau][Gotthard][CTB][Moench][Mythen3][Gotthard2]
* Advanced user Function!
* Copy detector server fname from tftp folder of hostname to detector
* Also changes respawn server, which is effective after a reboot.
* Advanced user Function! \n
* Copy detector server fname from tftp folder of hostname to detector \n
* [Jungfrau][Gotthard][CTB][Moench] Also changes respawn server, which is
* effective after a reboot.
*/
void copyDetectorServer(const std::string &fname,
const std::string &hostname, Positions pos = {});
@ -1523,13 +1531,14 @@ class Detector {
/**
* [Jungfrau][Gotthard][CTB][Moench]
* Advanced user Function!
* Advanced user Function! \n
* Updates the firmware, detector server and then reboots detector
* controller blackfin.
* sname is name of detector server binary found on tftp folder of host
* pc
* hostname is name of pc to tftp from
* fname is programming file name
* controller blackfin. \n
* [Mythen3][Gotthard2] Will still have old server starting up as the new
* server is not respawned \n
sname is name of detector server binary found on
* tftp folder of host pc hostname is name of pc to tftp from fname is
* programming file name
*/
void updateFirmwareAndServer(const std::string &sname,
const std::string &hostname,
@ -1617,11 +1626,11 @@ class Detector {
Result<int64_t> getNumberOfFramesFromStart(Positions pos = {}) const;
/** [Jungfrau][Mythen3][CTB][Moench] Get time from detector start
* [Gotthard2] only in continuous mode */
* [Gotthard2] not in burst and auto mode */
Result<ns> getActualTime(Positions pos = {}) const;
/** [Jungfrau][Mythen3][CTB][Moench] Get timestamp at a frame start
* [Gotthard2] only in continuous mode */
* [Gotthard2] not in burst and auto mode */
Result<ns> getMeasurementTime(Positions pos = {}) const;
/** get user details from shared memory (hostname, type, PID, User, Date)

View File

@ -122,7 +122,9 @@ std::string CmdProxy::Hostname(int action) {
os << cmd << ' ';
if (action == defs::HELP_ACTION) {
os << "\n\tFrees shared memory and sets hostname (or IP address) of "
"all modules concatenated by +."
"all modules concatenated by +.\n\t Virtual servers can already "
"use the port in hostname separated by ':' and ports incremented "
"by 2 to accomodate the stop server as well."
<< '\n';
} else if (action == defs::GET_ACTION) {
if (!args.empty()) {
@ -220,8 +222,8 @@ std::string CmdProxy::FirmwareVersion(int action) {
std::ostringstream os;
os << cmd << ' ';
if (action == defs::HELP_ACTION) {
os << "\n\tFimware version of detector in format [0xYYMMDD] or integer "
"for Eiger."
os << "\n\tFimware version of detector in format [0xYYMMDD] or an "
"increasing 2 digit number for Eiger."
<< '\n';
} else if (action == defs::GET_ACTION) {
if (!args.empty()) {
@ -315,9 +317,9 @@ std::string CmdProxy::DetectorSize(int action) {
os << cmd << ' ';
if (action == defs::HELP_ACTION) {
os << "[nx] [ny]\n\tDetector size, ie. Number of channels in x and y "
"dim. If 0, then hostname adds all modules in y dim. This is "
"used to calculate module coordinates included in UDP data "
"packet header."
"dim. This is used to calculate module coordinates included in "
"UDP data. \n\tBy default, it adds module in y dimension for 2d "
"detectors and in x dimension for 1d detectors packet header."
<< '\n';
} else if (action == defs::GET_ACTION) {
if (!args.empty()) {
@ -480,7 +482,8 @@ std::string CmdProxy::DynamicRange(int action) {
if (action == defs::HELP_ACTION) {
os << "[value]\n\tDynamic Range or number of bits per "
"pixel in detector.\n\t"
"[Eiger] Options: 4, 8, 16, 32\n\t"
"[Eiger] Options: 4, 8, 16, 32. If set to 32, also sets "
"clkdivider to 2, else to 0.\n\t"
"[Mythen3] Options: 8, 16, 32\n\t"
"[Jungfrau][Gotthard][Ctb][Moench][Mythen3][Gotthard2] 16"
<< '\n';
@ -838,7 +841,7 @@ std::string CmdProxy::ExternalSignal(int action) {
"[trigger_in_rising_edge|trigger_in_falling_edge|inversion_on|"
"inversion_off]\n\t where 0 is master input trigger signal, 1-3 "
"is master input gate signals, 4 is busy out signal and 5-7 is "
"master output gate signals"
"master output gate signals."
<< '\n';
} else if (action == defs::GET_ACTION) {
if (args.size() != 1) {
@ -2450,10 +2453,9 @@ std::string CmdProxy::CopyDetectorServer(int action) {
if (action == defs::HELP_ACTION) {
os << "[server_name] "
"[pc_host_name]\n\t[Jungfrau][Ctb][Moench][Mythen3][Gotthard2] "
"Copies "
"detector "
"server via tftp from pc and changes respawn server name in "
"/etc/inittab of detector."
"Copies detector server via tftp from pc. "
"\n\t[Jungfrau][Ctb][Moench]Also changes respawn server, which "
"is effective after a reboot."
<< '\n';
} else if (action == defs::GET_ACTION) {
throw sls::RuntimeError("Cannot get");
@ -2644,7 +2646,8 @@ std::string CmdProxy::ExecuteCommand(int action) {
std::ostringstream os;
os << cmd << ' ';
if (action == defs::HELP_ACTION) {
os << "[command]\n\tExecutes command on detector server." << '\n';
os << "[command]\n\tExecutes command on detector server console."
<< '\n';
} else if (action == defs::GET_ACTION) {
throw sls::RuntimeError("Cannot get.");
} else if (action == defs::PUT_ACTION) {

View File

@ -597,6 +597,7 @@ class CmdProxy {
{"detectorversion", "firmwareversion"},
{"softwareversion", "detectorserverversion"},
{"receiverversion", "rx_version"},
{"detectornumber", "serialnumber"},
{"thisversion", "clientversion"},
{"detsizechan", "detsize"},
@ -703,7 +704,7 @@ class CmdProxy {
{"firmwareversion", &CmdProxy::FirmwareVersion},
{"detectorserverversion", &CmdProxy::detectorserverversion},
{"rx_version", &CmdProxy::rx_version},
{"detectornumber", &CmdProxy::detectornumber},
{"serialnumber", &CmdProxy::serialnumber},
{"type", &CmdProxy::type},
{"nmod", &CmdProxy::nmod},
{"detsize", &CmdProxy::DetectorSize},
@ -1176,8 +1177,8 @@ class CmdProxy {
GET_COMMAND_HEX(rx_version, getReceiverVersion,
"\n\tReceiver version in format [0xYYMMDD].");
GET_COMMAND_HEX(detectornumber, getSerialNumber,
"\n\tReceiver version in format [0xYYMMDD].");
GET_COMMAND_HEX(serialnumber, getSerialNumber,
"\n\tSerial number of detector.");
GET_COMMAND(type, getDetectorType,
"\n\tReturns detector type. Can be Eiger, Jungfrau, Gotthard, "
@ -1222,8 +1223,8 @@ class CmdProxy {
INTEGER_COMMAND_NOID(
frames, getNumberOfFrames, setNumberOfFrames, StringTo<int64_t>,
"[n_frames]\n\tNumber of frames per acquisition. In "
"trigger mode, number of frames per trigger. Cannot be set in modular "
"level. In scan mode, number of frames is set to number of "
"trigger mode, number of frames per trigger. \n\tCannot be set in "
"modular level. \n\tIn scan mode, number of frames is set to number of "
"steps.\n\t[Gotthard2] Burst mode has a maximum of 2720 frames.");
INTEGER_COMMAND_NOID(triggers, getNumberOfTriggers, setNumberOfTriggers,
@ -1903,10 +1904,10 @@ class CmdProxy {
"[binary|hdf5]\n\tFile format of data file. For HDF5, package must be "
"compiled with HDF5 flags. Default is binary.");
STRING_COMMAND(
fpath, getFilePath, setFilePath,
"[path]\n\tDirectory where output data files are written in receiver. "
"If path does not exist, it will try to create it.");
STRING_COMMAND(fpath, getFilePath, setFilePath,
"[path]\n\tDirectory where output data files are written in "
"receiver. Default is '/'. \n\tIf path does not exist, it "
"will try to create it.");
STRING_COMMAND(fname, getFileNamePrefix, setFileNamePrefix,
"[name]\n\tFile name prefix for output data file. Default "
@ -2016,8 +2017,9 @@ class CmdProxy {
INTEGER_COMMAND_VEC_ID(
flippeddatax, getBottom, setBottom, StringTo<int>,
"[0, 1]\n\t[Eiger] Top or Bottom Half of Eiger module. 1 is bottom, 0 "
"is top. Used to let Receivers and Gui know to flip the bottom image "
"over the x axis. Files are not written without the flip however.");
"is top. Used to let Gui (via zmq from receiver) know to flip the "
"bottom image over the x axis. Files are not written without the flip "
"however.");
INTEGER_COMMAND_VEC_ID(
readnlines, getPartialReadout, setPartialReadout, StringTo<int>,
@ -2263,8 +2265,8 @@ class CmdProxy {
INTEGER_COMMAND_VEC_ID(
extsampling, getExternalSampling, setExternalSampling, StringTo<int>,
"[0, 1]\n\t[Ctb] Enable for external sampling signal to extsamplingsrc "
"signal for digital data. For advanced users only.");
"[0, 1]\n\t[Ctb] Enable for external sampling signal for digital data "
"to signal by extsampling src command. For advanced users only.");
INTEGER_COMMAND_VEC_ID(
extsamplingsrc, getExternalSamplingSource, setExternalSamplingSource,
@ -2361,13 +2363,13 @@ class CmdProxy {
"[(optional unit) "
"ns|us|ms|s]\n\t[Jungfrau][Mythen3][Gotthard2][Moench]["
"CTB] Time from detector start up."
"\n\t[Gotthard2] only in continuous mode.");
"\n\t[Gotthard2] not in burst and auto mode.");
TIME_GET_COMMAND(timestamp, getMeasurementTime,
"[(optional unit) "
"ns|us|ms|s]\n\t[Jungfrau][Mythen3][Gotthard2][Moench]["
"CTB] Timestamp at a frame start."
"\n\t[Gotthard2] only in continuous mode.");
"\n\t[Gotthard2] not in burst and auto mode.");
GET_COMMAND(
rx_frameindex, getRxCurrentFrameIndex,

View File

@ -101,11 +101,11 @@ TEST_CASE("detectorserverversion", "[.cmd][.new]") {
REQUIRE_THROWS(proxy.Call("detectorserverversion", {"0"}, -1, PUT));
}
TEST_CASE("detectornumber", "[.cmd][.new]") {
TEST_CASE("serialnumber", "[.cmd][.new]") {
Detector det;
CmdProxy proxy(&det);
REQUIRE_NOTHROW(proxy.Call("detectornumber", {}, -1, GET));
REQUIRE_THROWS(proxy.Call("detectornumber", {"0"}, -1, PUT));
REQUIRE_NOTHROW(proxy.Call("serialnumber", {}, -1, GET));
REQUIRE_THROWS(proxy.Call("serialnumber", {"0"}, -1, PUT));
}
TEST_CASE("type", "[.cmd][.new]") {
@ -334,10 +334,10 @@ TEST_CASE("exptime", "[.cmd][.time]") {
REQUIRE(oss.str() == "exptime 0\n");
}
{
//Get exptime of single module
std::ostringstream oss;
proxy.Call("exptime", {}, 0, GET, oss);
REQUIRE(oss.str() == "exptime 0ns\n");
// Get exptime of single module
std::ostringstream oss;
proxy.Call("exptime", {}, 0, GET, oss);
REQUIRE(oss.str() == "exptime 0ns\n");
}
det.setExptime(-1, prev_val);
}