diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt index 2af935c94..b6017d79a 100755 --- a/python/CMakeLists.txt +++ b/python/CMakeLists.txt @@ -35,8 +35,7 @@ set( PYTHON_FILES gotthard.py gotthard2.py moench.py - jsonproxy.py - slowadcproxy.py + proxy.py ctb.py jungfrau.py mythen3.py diff --git a/python/scripts/cmd_python.py b/python/scripts/cmd_python.py deleted file mode 100644 index b882dacdc..000000000 --- a/python/scripts/cmd_python.py +++ /dev/null @@ -1,100 +0,0 @@ -import subprocess -import locale -out = subprocess.run(['g', 'list'], stdout = subprocess.PIPE, encoding=locale.getpreferredencoding()) -cmd = out.stdout.splitlines() -cmd.pop(0) - -from slsdet import Detector, Eiger, Ctb - -pycmd = dir(Detector)+dir(Eiger)+dir(Ctb) - -#Add commands that we should not expect as direct commands in python -pycmd += ['vrf', 'vtr', 'vrs', 'vtgstv', 'vsvn', 'vtrim', -'vsvp', 'vth1', 'vth2', 'vth3', 'vshaper', 'vshaperneg', 'rxb_rb', -'rxb_lb', 'vref_prech', 'vref_rstore', 'vref_cds', -'vpreamp', 'vref_comp', 'vref_comp_fe vref_ds', 'vref_h_adc', -'vref_l_adc', 'iodelay', 'list', 'vref_ds', 'vis', 'vpl', -'vref_comp_fe', 'vph', 'vout_cm', 'vcp', 'vcn', 'vcmp_ll', 'vcmp_lr' - -] - - -# dacs are in general not included in the python commands and we expect to -# set them from the specialized class or using an enum -dacs = [ - 'adcvpp', - 'vicin', - 'vcassh', - 'vcal_n', - 'vcal_p' - 'vipre_out', - 'vipre_cds', - 'vdd_prot', - 'vcmp_rl', - 'vcmp_rr', - 'vcal', 'vcas', - 'vipre', - 'vin_com', - 'vin_cm', - 'vrshaper', - 'vrshaper_n', - 'vrpreamp', - 'vishaper', - 'vipre_out', - 'vcom_adc1', - 'vcom_adc2', - 'vcom_cds', - 'vdcsh', - 'v_chip', - 'vb_comp', - 'vb_comp_adc', - 'vb_comp_fe', - 'vb_cs', - 'vb_ds', - 'vb_opa_1st', - 'vb_opa_fd', - 'vb_pixbuf', - 'vb_sda', - 'vbp_colbuf', - 'vcal_p', - 'vcasc_out', - 'vcasc_sfp', - 'vcascn_pb', - 'vcascp_pb', - 'vchip_comp_adc', - 'vchip_comp_fe', - 'vchip_cs', - 'vchip_opa_1st', - 'vchip_opa_fd', - 'vchip_ref_comp_fe', - -] - -intentionally_missing = [ - 'activate', #use getActive and getRxPadDeactivatedMode syntax is not a good fit for python - 'temp_10ge', #temperatures already available from enum or specialized class - 'temp_adc', - 'temp_dcdc', - 'temp_fpga', - 'temp_fpgaext', - 'temp_fpgafl', - 'temp_fpgafr', - 'temp_slowadc', - 'temp_sodl', - 'temp_sodr', - 'trigger', #use sendSoftwareTrigger - 'update', #use updateServerAndFirmare - 'udp_validate', #use validateUdpConfiguration - 'udp_reconfigure', #use reconfigureUdpDestination - 'emin', #use rx_jsonpara -] - -pycmd += intentionally_missing -pycmd += dacs -missing = [] -for c in cmd: - if c not in pycmd: - print(c) - missing.append(c) - -print(f'Missing: {len(missing)} commands') \ No newline at end of file diff --git a/python/scripts/compare_with_commandline.py b/python/scripts/compare_with_commandline.py new file mode 100644 index 000000000..9f70004c4 --- /dev/null +++ b/python/scripts/compare_with_commandline.py @@ -0,0 +1,132 @@ +import subprocess +import locale +out = subprocess.run(['g', 'list'], stdout = subprocess.PIPE, encoding=locale.getpreferredencoding()) +cmd = out.stdout.splitlines() +cmd.pop(0) + +from slsdet import Detector + +pycmd = dir(Detector) + + +# dacs are in general not included in the python commands and we expect to +# set them from the specialized class or using an enum +dacs = [ + 'adcvpp', + 'iodelay', + 'list', + 'rxb_lb', + 'rxb_rb', + 'v_chip', + 'vb_comp', + 'vb_comp_adc', + 'vb_comp_fe', + 'vb_cs', + 'vb_ds', + 'vb_opa_1st', + 'vb_opa_fd', + 'vb_pixbuf', + 'vb_sda', + 'vbp_colbuf', + 'vcal', + 'vcal_n', + 'vcal_p', + 'vipre_out', + 'vcas', + 'vcasc_out', + 'vcasc_sfp', + 'vcascn_pb', + 'vcascp_pb', + 'vcassh', + 'vchip_comp_adc', + 'vchip_comp_fe', + 'vchip_cs', + 'vchip_opa_1st', + 'vchip_opa_fd', + 'vchip_ref_comp_fe', + 'vcmp_ll', + 'vcmp_lr', + 'vcmp_rl', + 'vcmp_rr', + 'vcn', + 'vcom_adc1', + 'vcom_adc2', + 'vcom_cds', + 'vcp', + 'vdcsh', + 'vdd_prot', + 'vicin', + 'vin_cm', + 'vin_com', + 'vipre', + 'vipre_cds', + 'vipre_out', + 'vishaper', + 'vout_cm', + 'vref_cds', + 'vref_comp', + 'vref_comp_fe', + 'vref_ds', + 'vref_h_adc', + 'vref_l_adc', + 'vref_prech', + 'vref_rstore', + 'vrpreamp', + 'vrshaper', + 'vrshaper_n', + 'vsvn', + 'vsvp', + 'vtgstv', + 'vth1', + 'vth2', + 'vth3', + 'vtrim' +] + +intentionally_missing = [ + 'activate', #use getActive and getRxPadDeactivatedMode syntax is not a good fit for python + 'temp_10ge', #temperatures already available from enum or specialized class + 'temp_adc', + 'temp_dcdc', + 'temp_fpga', + 'temp_fpgaext', + 'temp_fpgafl', + 'temp_fpgafr', + 'temp_slowadc', + 'temp_sodl', + 'temp_sodr', + 'trigger', #use sendSoftwareTrigger + 'update', #use updateServerAndFirmare + 'udp_validate', #use validateUdpConfiguration + 'udp_reconfigure', #use reconfigureUdpDestination + 'pulse', # use pulseChip pulsePixel pulsePixelNmove + 'pulsechip', + 'pulsenmove', +] + +pycmd += intentionally_missing +pycmd += dacs +missing = [] +for c in cmd: + if c not in pycmd: + print(c) + missing.append(c) + +print(f'\nMissing: {len(missing)} commands') +print(f'Excluded: {len(dacs)} dacs') +print(f'Excluded: {len(intentionally_missing)} other commands') + + + +not_in_cmd = [] +for c in pycmd: + if c.islower() and not c.startswith('_'): + if c not in cmd: + not_in_cmd.append(c) +print(f'\nCommands in Python and NOT in command line: {len(not_in_cmd)}') +for c in not_in_cmd: + print(c) + + + +# print(',\n'.join([f'\'{d}\'' for d in sorted(dacs)])) diff --git a/python/scripts/generate_functions.py b/python/scripts/generate_functions.py index 095a57a70..5a955e63b 100644 --- a/python/scripts/generate_functions.py +++ b/python/scripts/generate_functions.py @@ -60,6 +60,23 @@ def get_arguments(node): args = f", {args}" return args +def get_arguments_with_default(node): + args = [] + for arg in node.get_arguments(): + tokens = [t.spelling for t in arg.get_tokens()] + print(tokens) + if '=' in tokens: + if arg.type.spelling == "sls::Positions": #TODO! automate + args.append("py::arg() = Positions{}") + else: + args.append('py::arg()' + ''.join(tokens[tokens.index('='):])) + else: + args.append('py::arg()') + args = ", ".join(args) + if args: + args = f", {args}" + return args + def get_fdec(node): args = [a.type.spelling for a in node.get_arguments()] @@ -86,7 +103,8 @@ def visit(node): and child.access_specifier == cindex.AccessSpecifier.PUBLIC ): m.append(child) - args = get_arguments(child) + # args = get_arguments(child) + args = get_arguments_with_default(child) fs = get_fdec(child) lines.append( f'.def("{child.spelling}",{fs} &Detector::{child.spelling}{args})' diff --git a/python/slsdet/detector.py b/python/slsdet/detector.py index 4f52abacc..4f1d63c18 100755 --- a/python/slsdet/detector.py +++ b/python/slsdet/detector.py @@ -11,8 +11,7 @@ detectorType = slsDetectorDefs.detectorType from .utils import element_if_equal, all_equal, get_set_bits, list_to_bitmask from .utils import Geometry, to_geo, element, reduce_time, is_iterable from . import utils as ut -from .jsonproxy import JsonProxy -from .slowadcproxy import SlowAdcProxy +from .proxy import JsonProxy, SlowAdcProxy from .registers import Register, Adc_register import datetime as dt @@ -141,6 +140,15 @@ class Detector(CppDetectorApi): raise ValueError("hostname needs to be string or list of strings") + @property + @element + def port(self): + return self.getControlPort() + + @port.setter + def port(self, value): + ut.set_using_dict(self.setControlPort, value) + @property @element def stopport(self): @@ -186,6 +194,10 @@ class Detector(CppDetectorApi): def dr(self, dr): self.setDynamicRange(dr) + @property + def drlist(self): + return self.getDynamicRangeList() + @property def module_geometry(self): return to_geo(self.getModuleGeometry()) @@ -196,7 +208,7 @@ class Detector(CppDetectorApi): return element_if_equal(ms) @property - def detector_size(self): + def detsize(self): return to_geo(self.getDetectorSize()) @property @@ -235,6 +247,25 @@ class Detector(CppDetectorApi): def frames(self, n_frames): self.setNumberOfFrames(n_frames) + @property + @element + def framesl(self): + return self.getNumberOfFramesLeft() + + @property + @element + def nframes(self): + return self.getNumberOfFramesFromStart() + + @property + @element + def powerchip(self): + return self.getPowerChip() + + @powerchip.setter + def powerchip(self, value): + ut.set_using_dict(self.setPowerChip, value) + @property def triggers(self): return element_if_equal(self.getNumberOfTriggers()) @@ -573,13 +604,14 @@ class Detector(CppDetectorApi): self.setFileFormat(format) @property + @element def findex(self): """File or Acquisition index in receiver.""" - return element_if_equal(self.getAcquisitionIndex()) + return self.getAcquisitionIndex() @findex.setter def findex(self, index): - self.setAcquisitionIndex(index) + ut.set_using_dict(self.setAcquisitionIndex, index) @property def fname(self): @@ -664,6 +696,7 @@ class Detector(CppDetectorApi): # ZMQ Streaming Parameters (Receiver<->Client) @property + @element def rx_zmqstream(self): """ Enable/ disable data streaming from receiver via zmq (eg. to GUI or to another process for further processing). \n @@ -671,11 +704,11 @@ class Detector(CppDetectorApi): Switching to Gui automatically enables data streaming in receiver. \n Switching back to command line acquire will require disabling data streaming in receiver for fast applications. """ - return element_if_equal(self.getRxZmqDataStream()) + return self.getRxZmqDataStream() @rx_zmqstream.setter - def rx_zmqdatastream(self, enable): - self.setRxZmqDataStream(enable) + def rx_zmqstream(self, enable): + ut.set_using_dict(self.setRxZmqDataStream, enable) @property def rx_zmqfreq(self): @@ -861,38 +894,6 @@ class Detector(CppDetectorApi): def udp_dstport2(self, port): self.setDestinationUDPPort2(port) - @property - def src_udpmac(self): - return element_if_equal(self.getSourceUDPMAC()) - - @src_udpmac.setter - def src_udpmac(self, mac): - self.setSourceUDPMAC(MacAddr(mac)) - - @property - def src_udpip2(self): - return element_if_equal(self.getSourceUDPIP()) - - @src_udpip2.setter - def src_udpip2(self, ip): - self.setSourceUDPIP(IpAddr(ip)) - - @property - def src_udpip(self): - return element_if_equal(self.getSourceUDPIP()) - - @src_udpip.setter - def src_udpip(self, ip): - self.setSourceUDPIP(IpAddr(ip)) - - @property - def src_udpmac2(self): - return element_if_equal(self.getSourceUDPMAC2()) - - @src_udpmac2.setter - def src_udpmac2(self, mac): - self.setSourceUDPMAC2(MacAddr(mac)) - @property def highvoltage(self): """High voltage to the sensor in Voltage. @@ -1189,19 +1190,17 @@ class Detector(CppDetectorApi): return JsonProxy(self) - - @rx_jsonpara.setter - def rx_jsonpara(self, args): - for key, value in args.items(): - self.setAdditionalJsonParameter(key, str(value)) - @property @element def rx_jsonaddheader(self): return self.getAdditionalJsonHeader() + @rx_jsonaddheader.setter + def rx_jsonaddheader(self, args): + ut.set_using_dict(self.setAdditionalJsonHeader, args) + @property - def frameindex(self): + def rx_frameindex(self): return self.getRxCurrentFrameIndex() @property @@ -1252,7 +1251,7 @@ class Detector(CppDetectorApi): """ - <<>> + <<<-----------------------Eiger specific----------------------->>> """ @@ -1290,6 +1289,15 @@ class Detector(CppDetectorApi): def subexptime(self, t): ut.set_time_using_dict(self.setSubExptime, t) + @property + @element + def readnlines(self): + return self.getPartialReadout() + + @readnlines.setter + def readnlines(self, value): + ut.set_using_dict(self.setPartialReadout, value) + @property def subdeadtime(self): @@ -2263,3 +2271,13 @@ class Detector(CppDetectorApi): + """ + + <<<-----------------------Gotthard specific----------------------->>> + + """ + + @property + def exptimel(self): + t = self.getExptimeLeft() + return reduce_time(t) diff --git a/python/slsdet/jsonproxy.py b/python/slsdet/proxy.py similarity index 58% rename from python/slsdet/jsonproxy.py rename to python/slsdet/proxy.py index a85adf630..9467bb288 100644 --- a/python/slsdet/jsonproxy.py +++ b/python/slsdet/proxy.py @@ -1,4 +1,5 @@ from .utils import element_if_equal +from .enums import dacIndex class JsonProxy: """ @@ -28,3 +29,25 @@ class JsonProxy: return '\n'.join([f'{key}: {value}' for key, value in r.items()]) + +class SlowAdcProxy: + """ + Proxy class to allow for more intuitive reading the slow ADCs + """ + def __init__(self, det): + self.det = det + + def __getitem__(self, key): + dac_index = dacIndex(int(dacIndex.SLOW_ADC0)+key) + return element_if_equal(self.det.getSlowADC(dac_index)) + + def __repr__(self): + rstr = '' + for i in range(7): + r = element_if_equal(self.__getitem__(i)) + if isinstance(r, list): + rstr += ' '.join(f'{item} mV' for item in r) + else: + rstr += f'{i}: {r} mV\n' + + return rstr.strip('\n') \ No newline at end of file diff --git a/python/slsdet/slowadcproxy.py b/python/slsdet/slowadcproxy.py deleted file mode 100644 index 291f526a8..000000000 --- a/python/slsdet/slowadcproxy.py +++ /dev/null @@ -1,25 +0,0 @@ -from .utils import element_if_equal -from .enums import dacIndex -class SlowAdcProxy: - """ - Proxy class to allow for more intuitive reading the slow ADCs - """ - def __init__(self, det): - self.det = det - - def __getitem__(self, key): - dac_index = dacIndex(int(dacIndex.SLOW_ADC0)+key) - return element_if_equal(self.det.getSlowADC(dac_index)) - - def __repr__(self): - rstr = '' - for i in range(7): - r = element_if_equal(self.__getitem__(i)) - if isinstance(r, list): - rstr += ' '.join(f'{item} mV' for item in r) - else: - rstr += f'{i}: {r} mV\n' - - return rstr.strip('\n') - - diff --git a/python/slsdet/utils.py b/python/slsdet/utils.py index 3474cda0e..687063bda 100755 --- a/python/slsdet/utils.py +++ b/python/slsdet/utils.py @@ -111,14 +111,14 @@ def make_string_path(path): def set_using_dict(func, args): - if isinstance(args, dict): + if isinstance(args, dict) and all(isinstance(k, int) for k in args.keys()): for key, value in args.items(): func(value, [key]) else: func(args) def set_time_using_dict(func, args): - if isinstance(args, dict): + if isinstance(args, dict) and all(isinstance(k, int) for k in args.keys()): for key, value in args.items(): if isinstance(value, int): value = float(value) diff --git a/python/src/detector.cpp b/python/src/detector.cpp index d3e61c998..f5d0cbf72 100644 --- a/python/src/detector.cpp +++ b/python/src/detector.cpp @@ -322,11 +322,11 @@ void init_det(py::module &m) { (Result(Detector::*)(defs::dacIndex, bool, sls::Positions) const) & Detector::getDAC, - py::arg(), py::arg(), py::arg() = Positions{}) + py::arg(), py::arg() = false, py::arg() = Positions{}) .def("setDAC", (void (Detector::*)(defs::dacIndex, int, bool, sls::Positions)) & Detector::setDAC, - py::arg(), py::arg(), py::arg(), py::arg() = Positions{}) + py::arg(), py::arg(), py::arg() = false, py::arg() = Positions{}) .def("getOnChipDAC", (Result(Detector::*)(defs::dacIndex, int, sls::Positions) const) & @@ -488,14 +488,14 @@ void init_det(py::module &m) { py::arg() = Positions{}) .def("setDestinationUDPPort", (void (Detector::*)(int, int)) & Detector::setDestinationUDPPort, - py::arg(), py::arg()) + py::arg(), py::arg() = -1) .def("getDestinationUDPPort2", (Result(Detector::*)(sls::Positions) const) & Detector::getDestinationUDPPort2, py::arg() = Positions{}) .def("setDestinationUDPPort2", (void (Detector::*)(int, int)) & Detector::setDestinationUDPPort2, - py::arg(), py::arg()) + py::arg(), py::arg() = -1) .def("reconfigureUDPDestination", (void (Detector::*)(sls::Positions)) & Detector::reconfigureUDPDestination, @@ -568,7 +568,7 @@ void init_det(py::module &m) { Detector::getRxPort, py::arg() = Positions{}) .def("setRxPort", (void (Detector::*)(int, int)) & Detector::setRxPort, - py::arg(), py::arg()) + py::arg(), py::arg() = -1) .def("getRxFifoDepth", (Result(Detector::*)(sls::Positions) const) & Detector::getRxFifoDepth, @@ -730,7 +730,7 @@ void init_det(py::module &m) { py::arg() = Positions{}) .def("setRxZmqPort", (void (Detector::*)(int, int)) & Detector::setRxZmqPort, py::arg(), - py::arg()) + py::arg() = -1) .def("getRxZmqIP", (Result(Detector::*)(sls::Positions) const) & Detector::getRxZmqIP, @@ -745,7 +745,7 @@ void init_det(py::module &m) { py::arg() = Positions{}) .def("setClientZmqPort", (void (Detector::*)(int, int)) & Detector::setClientZmqPort, - py::arg(), py::arg()) + py::arg(), py::arg() = -1) .def("getClientZmqIp", (Result(Detector::*)(sls::Positions) const) & Detector::getClientZmqIp, @@ -778,7 +778,8 @@ void init_det(py::module &m) { (void (Detector::*)(int, defs::detectorSettings, bool, sls::Positions)) & Detector::setThresholdEnergy, - py::arg(), py::arg(), py::arg(), py::arg() = Positions{}) + py::arg(), py::arg() = defs::STANDARD, py::arg() = true, + py::arg() = Positions{}) .def("getSettingsPath", (Result(Detector::*)(sls::Positions) const) & Detector::getSettingsPath, diff --git a/slsDetectorSoftware/include/Detector.h b/slsDetectorSoftware/include/Detector.h index 217e5dcd2..ddea67c0d 100644 --- a/slsDetectorSoftware/include/Detector.h +++ b/slsDetectorSoftware/include/Detector.h @@ -367,9 +367,9 @@ class Detector { /** gets list of dac enums for this detector */ std::vector getDacList() const; - Result getDAC(defs::dacIndex index, bool mV, Positions pos = {}) const; + Result getDAC(defs::dacIndex index, bool mV = false, Positions pos = {}) const; - void setDAC(defs::dacIndex index, int value, bool mV, Positions pos = {}); + void setDAC(defs::dacIndex index, int value, bool mV = false, Positions pos = {}); /* [Gotthard2] */ Result getOnChipDAC(defs::dacIndex index, int chipIndex, diff --git a/slsDetectorSoftware/src/CmdProxy.h b/slsDetectorSoftware/src/CmdProxy.h index f19d06ba6..917b2fbbc 100644 --- a/slsDetectorSoftware/src/CmdProxy.h +++ b/slsDetectorSoftware/src/CmdProxy.h @@ -650,6 +650,7 @@ class CmdProxy { {"rx_version", &CmdProxy::rx_version}, {"detectornumber", &CmdProxy::detectornumber}, {"type", &CmdProxy::type}, + {"nmod", &CmdProxy::nmod}, {"detsize", &CmdProxy::DetectorSize}, {"settingslist", &CmdProxy::settingslist}, {"settings", &CmdProxy::settings}, @@ -1126,6 +1127,8 @@ class CmdProxy { GET_COMMAND(type, getDetectorType, "\n\tSerial number or MAC of detector (hex)."); + GET_COMMAND_NOID(nmod, size, "\n\tNumber of modules in shared memory."); + GET_COMMAND_NOID(settingslist, getSettingsList, "\n\tList of settings implemented for this detector.");