diff --git a/python/slsdet/detector.py b/python/slsdet/detector.py index 46e4c9f12..0c8775e9a 100755 --- a/python/slsdet/detector.py +++ b/python/slsdet/detector.py @@ -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) """ diff --git a/slsDetectorServers/slsDetectorServer/src/slsDetectorServer_funcs.c b/slsDetectorServers/slsDetectorServer/src/slsDetectorServer_funcs.c index 817fdccf5..fba922b86 100644 --- a/slsDetectorServers/slsDetectorServer/src/slsDetectorServer_funcs.c +++ b/slsDetectorServers/slsDetectorServer/src/slsDetectorServer_funcs.c @@ -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 diff --git a/slsDetectorSoftware/include/Detector.h b/slsDetectorSoftware/include/Detector.h index 220111138..82d208407 100644 --- a/slsDetectorSoftware/include/Detector.h +++ b/slsDetectorSoftware/include/Detector.h @@ -58,7 +58,7 @@ class Detector { Result 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 &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 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 getNumberOfTriggers(Positions pos = {}) const; @@ -228,8 +231,8 @@ class Detector { Result 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 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 getClockDivider(int clkIndex, Positions pos = {}); - /** [Mythen3][Gotthard2] */ + /** [Mythen3][Gotthard2] Must be greater than 1. */ void setClockDivider(int clkIndex, int value, Positions pos = {}); Result getHighVoltage(Positions pos = {}) const; @@ -740,7 +743,7 @@ class Detector { Result 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 getFileNamePrefix(Positions pos = {}) const; @@ -753,7 +756,10 @@ class Detector { Result 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 getFileWrite(Positions pos = {}) const; @@ -908,7 +914,7 @@ class Detector { /** [Eiger] */ Result 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 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 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 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 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 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 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 getMeasurementTime(Positions pos = {}) const; /** get user details from shared memory (hostname, type, PID, User, Date) diff --git a/slsDetectorSoftware/src/CmdProxy.cpp b/slsDetectorSoftware/src/CmdProxy.cpp index 7cc7fa58d..f3b379f1b 100644 --- a/slsDetectorSoftware/src/CmdProxy.cpp +++ b/slsDetectorSoftware/src/CmdProxy.cpp @@ -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) { diff --git a/slsDetectorSoftware/src/CmdProxy.h b/slsDetectorSoftware/src/CmdProxy.h index c987dcd8e..e83fcc910 100644 --- a/slsDetectorSoftware/src/CmdProxy.h +++ b/slsDetectorSoftware/src/CmdProxy.h @@ -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, "[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, "[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, @@ -2263,8 +2265,8 @@ class CmdProxy { INTEGER_COMMAND_VEC_ID( extsampling, getExternalSampling, setExternalSampling, StringTo, - "[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, diff --git a/slsDetectorSoftware/tests/test-CmdProxy.cpp b/slsDetectorSoftware/tests/test-CmdProxy.cpp index a169cf5d5..ff6fc3854 100644 --- a/slsDetectorSoftware/tests/test-CmdProxy.cpp +++ b/slsDetectorSoftware/tests/test-CmdProxy.cpp @@ -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); }