diff --git a/python/CMakeLists.txt b/python/CMakeLists.txt index f37b4966b..3a8b49058 100755 --- a/python/CMakeLists.txt +++ b/python/CMakeLists.txt @@ -2,7 +2,8 @@ pybind11_add_module(_sls_detector src/main.cpp src/enums.cpp - src/experimental.cpp + src/detector.cpp + src/network.cpp ) target_link_libraries(_sls_detector PUBLIC diff --git a/python/scripts/generate_functions.py b/python/scripts/generate_functions.py new file mode 100644 index 000000000..391dfa426 --- /dev/null +++ b/python/scripts/generate_functions.py @@ -0,0 +1,84 @@ +""" +This file is used to auto generate Python bindings for the +sls::Detector class. The tool needs the libclang bindings +to be installed. + +When the Detector API is updated this file should be run +manually +""" +from clang import cindex +import subprocess +import argparse + + +from parse import system_include_paths + +default_build_path = "/home/l_frojdh/sls/build/" +fpath = "../../slsDetectorSoftware/src/Detector.cpp" + + +parser = argparse.ArgumentParser() +parser.add_argument("-p", "--build_path", help="Path to the build database", type = str, default=default_build_path) +cargs = parser.parse_args() + +db = cindex.CompilationDatabase.fromDirectory(cargs.build_path) +index = cindex.Index.create() +args = db.getCompileCommands(fpath) +args = list(iter(args).__next__().arguments)[0:-1] +args = args + "-x c++ --std=c++11".split() +syspath = system_include_paths('clang++') +incargs = ["-I" + inc for inc in syspath] +args = args + incargs + + +tu = index.parse(fpath, args=args) + + +m = [] +ag = [] + +lines = [] + + +def get_arguments(node): + args = [a.type.spelling for a in node.get_arguments()] + args = [ + "py::arg() = Positions{}" if item == "sls::Positions" else "py::arg()" + for item in args + ] + args = ', '.join(args) + if args: + args = f', {args}' + return args + + +def visit(node): + if node.kind == cindex.CursorKind.CLASS_DECL: + if node.displayname == "Detector": + for child in node.get_children(): + if ( + child.kind == cindex.CursorKind.CXX_METHOD + and child.access_specifier == cindex.AccessSpecifier.PUBLIC + ): + m.append(child) + args = get_arguments(child) + lines.append(f'.def(\"{child.spelling}\", &Detector::{child.spelling}{args})') + for child in node.get_children(): + visit(child) + + +visit(tu.cursor) + + +with open('../src/detector_in.cpp') as f: + data = f.read() +s = ''.join(lines) +s += ';' +text = data.replace('[[FUNCTIONS]]', s) +warning = '/* WARINING This file is auto generated any edits might be overwritten without warning */\n\n' +with open('../src/detector.cpp', 'w') as f: + f.write(warning) + f.write(text) + +# run clang format on the output +subprocess.run(['clang-format', '../src/detector.cpp', '-i']) \ No newline at end of file diff --git a/python/scripts/parse.py b/python/scripts/parse.py index a186d52c8..c8b44ec8c 100644 --- a/python/scripts/parse.py +++ b/python/scripts/parse.py @@ -1,4 +1,9 @@ import re +import subprocess +from subprocess import PIPE +import os + + def remove_comments(text): def replacer(match): s = match.group(0) @@ -10,4 +15,42 @@ def remove_comments(text): r'//.*?$|/\*.*?\*/|\'(?:\\.|[^\\\'])*\'|"(?:\\.|[^\\"])*"', re.DOTALL | re.MULTILINE ) - return re.sub(pattern, replacer, text) \ No newline at end of file + return re.sub(pattern, replacer, text) + + + + +#based on ccsyspath: https://github.com/AndrewWalker/ccsyspath + +def compiler_preprocessor_verbose(compiler, extraflags): + """Capture the compiler preprocessor stage in verbose mode + """ + lines = [] + with open(os.devnull, 'r', encoding='utf-8') as devnull: + cmd = [compiler, '-E'] + cmd += extraflags + cmd += ['-', '-v'] + p = subprocess.Popen(cmd, stdin=devnull, stdout=PIPE, stderr=PIPE) + p.wait() + lines = p.stderr.read() + lines = lines.splitlines() + return lines + +def system_include_paths(compiler, cpp=True): + extraflags = [] + if cpp: + extraflags = b'-x c++'.split() + lines = compiler_preprocessor_verbose(compiler, extraflags) + lines = [ line.strip() for line in lines ] + + start = lines.index(b'#include <...> search starts here:') + end = lines.index(b'End of search list.') + + lines = lines[start+1:end] + paths = [] + for line in lines: + line = line.replace(b'(framework directory)', b'') + line = line.strip() + paths.append(line) + paths = [p.decode('utf-8') for p in paths] + return paths \ No newline at end of file diff --git a/python/setup.py b/python/setup.py index 264cb946d..e09b4b59f 100755 --- a/python/setup.py +++ b/python/setup.py @@ -38,7 +38,8 @@ ext_modules = [ '_sls_detector', ['src/main.cpp', 'src/enums.cpp', - 'src/experimental.cpp'], + 'src/detector.cpp', + 'src/network.cpp'], include_dirs=[ # Path to pybind11 headers get_pybind_include(), diff --git a/python/sls_detector/__init__.py b/python/sls_detector/__init__.py index b5addeed2..af70e9224 100755 --- a/python/sls_detector/__init__.py +++ b/python/sls_detector/__init__.py @@ -15,3 +15,6 @@ timingMode = _sls_detector.slsDetectorDefs.timingMode dacIndex = _sls_detector.slsDetectorDefs.dacIndex detectorType = _sls_detector.slsDetectorDefs.detectorType detectorSettings = _sls_detector.slsDetectorDefs.detectorSettings + +IpAddr = _sls_detector.IpAddr +MacAddr = _sls_detector.MacAddr diff --git a/python/src/experimental.cpp b/python/src/detector.cpp similarity index 63% rename from python/src/experimental.cpp rename to python/src/detector.cpp index b04ea7c85..05136dfb9 100644 --- a/python/src/experimental.cpp +++ b/python/src/detector.cpp @@ -1,3 +1,6 @@ +/* WARINING This file is auto generated any edits might be overwritten without + * warning */ + #include #include #include @@ -9,55 +12,60 @@ #include "sls_detector_defs.h" #include "typecaster.h" namespace py = pybind11; -void init_experimental(py::module &m) { +void init_det(py::module &m) { using sls::Detector; using sls::Positions; - using defs = slsDetectorDefs; py::class_ CppDetectorApi(m, "CppDetectorApi"); CppDetectorApi .def(py::init()) - // Configuration - .def("freeSharedMemory", (void (Detector::*)()) &Detector::freeSharedMemory) - .def("loadConfig", &Detector::loadConfig) - .def("loadParameters", &Detector::loadParameters) - .def("setHostname", &Detector::setHostname) + .def("freeSharedMemory", &Detector::freeSharedMemory) + .def("loadConfig", &Detector::loadConfig, py::arg()) + .def("loadParameters", &Detector::loadParameters, py::arg()) .def("getHostname", &Detector::getHostname, py::arg() = Positions{}) + .def("setHostname", &Detector::setHostname, py::arg()) + .def("setVirtualDetectorServers", &Detector::setVirtualDetectorServers, + py::arg(), py::arg()) .def("getShmId", &Detector::getShmId) + .def("getPackageVersion", &Detector::getPackageVersion) + .def("getClientVersion", &Detector::getClientVersion) .def("getFirmwareVersion", &Detector::getFirmwareVersion, py::arg() = Positions{}) .def("getDetectorServerVersion", &Detector::getDetectorServerVersion, py::arg() = Positions{}) .def("getSerialNumber", &Detector::getSerialNumber, py::arg() = Positions{}) - .def("getClientVersion", &Detector::getClientVersion) .def("getReceiverVersion", &Detector::getReceiverVersion, py::arg() = Positions{}) .def("getDetectorType", &Detector::getDetectorType, py::arg() = Positions{}) .def("size", &Detector::size) + .def("empty", &Detector::empty) .def("getModuleGeometry", &Detector::getModuleGeometry) .def("getModuleSize", &Detector::getModuleSize, py::arg() = Positions{}) .def("getDetectorSize", &Detector::getDetectorSize) - .def("setDetectorSize", &Detector::setDetectorSize) + .def("setDetectorSize", &Detector::setDetectorSize, py::arg()) .def("getSettings", &Detector::getSettings, py::arg() = Positions{}) .def("setSettings", &Detector::setSettings, py::arg(), py::arg() = Positions{}) - - // TODO! Python funcs for callbacks? - - // Acquisition Parameters - .def("getNumberOfFrames", &Detector::getNumberOfFrames) - .def("setNumberOfFrames", &Detector::setNumberOfFrames) - .def("getNumberOfTriggers", &Detector::getNumberOfTriggers) - .def("setNumberOfTriggers", &Detector::setNumberOfTriggers) + .def("registerAcquisitionFinishedCallback", + &Detector::registerAcquisitionFinishedCallback, py::arg(), + py::arg()) + .def("registerDataCallback", &Detector::registerDataCallback, py::arg(), + py::arg()) + .def("getNumberOfFrames", &Detector::getNumberOfFrames, + py::arg() = Positions{}) + .def("setNumberOfFrames", &Detector::setNumberOfFrames, py::arg()) + .def("getNumberOfTriggers", &Detector::getNumberOfTriggers, + py::arg() = Positions{}) + .def("setNumberOfTriggers", &Detector::setNumberOfTriggers, py::arg()) + .def("getExptime", &Detector::getExptime, py::arg() = Positions{}) .def("setExptime", &Detector::setExptime, py::arg(), py::arg() = Positions{}) - .def("getExptime", &Detector::getExptime, py::arg() = Positions{}) + .def("getPeriod", &Detector::getPeriod, py::arg() = Positions{}) .def("setPeriod", &Detector::setPeriod, py::arg(), py::arg() = Positions{}) - .def("getPeriod", &Detector::getPeriod, py::arg() = Positions{}) .def("getDelayAfterTrigger", &Detector::getDelayAfterTrigger, py::arg() = Positions{}) .def("setDelayAfterTrigger", &Detector::setDelayAfterTrigger, py::arg(), @@ -68,196 +76,124 @@ void init_experimental(py::module &m) { py::arg() = Positions{}) .def("getDelayAfterTriggerLeft", &Detector::getDelayAfterTriggerLeft, py::arg() = Positions{}) + .def("getPeriodLeft", &Detector::getPeriodLeft, py::arg() = Positions{}) .def("getSpeed", &Detector::getSpeed, py::arg() = Positions{}) .def("setSpeed", &Detector::setSpeed, py::arg(), py::arg() = Positions{}) .def("getADCPhase", &Detector::getADCPhase, py::arg() = Positions{}) - .def("setADCPhase", &Detector::setADCPhase, py::arg(), py::arg() = Positions{}) + .def("getMaxADCPhaseShift", &Detector::getMaxADCPhaseShift, + py::arg() = Positions{}) .def("getADCPhaseInDegrees", &Detector::getADCPhaseInDegrees, py::arg() = Positions{}) .def("setADCPhaseInDegrees", &Detector::setADCPhaseInDegrees, py::arg(), py::arg() = Positions{}) + .def("getClockFrequency", &Detector::getClockFrequency, py::arg(), + py::arg() = Positions{}) + .def("setClockFrequency", &Detector::setClockFrequency, py::arg(), + py::arg(), py::arg() = Positions{}) + .def("getClockPhase", &Detector::getClockPhase, py::arg(), + py::arg() = Positions{}) + .def("setClockPhase", &Detector::setClockPhase, py::arg(), py::arg(), + py::arg() = Positions{}) + .def("getMaxClockPhaseShift", &Detector::getMaxClockPhaseShift, + py::arg(), py::arg() = Positions{}) + .def("getClockPhaseinDegrees", &Detector::getClockPhaseinDegrees, + py::arg(), py::arg() = Positions{}) + .def("setClockPhaseinDegrees", &Detector::setClockPhaseinDegrees, + py::arg(), py::arg(), py::arg() = Positions{}) + .def("getClockDivider", &Detector::getClockDivider, py::arg(), + py::arg() = Positions{}) + .def("setClockDivider", &Detector::setClockDivider, py::arg(), + py::arg(), py::arg() = Positions{}) .def("getHighVoltage", &Detector::getHighVoltage, py::arg() = Positions{}) .def("setHighVoltage", &Detector::setHighVoltage, py::arg(), py::arg() = Positions{}) - .def("getTemperature", &Detector::getTemperature, py::arg(), py::arg() = Positions{}) - - .def("getDAC", &Detector::getDAC, py::arg(), py::arg() = false, + .def("getDAC", &Detector::getDAC, py::arg(), py::arg(), py::arg() = Positions{}) .def("setDAC", &Detector::setDAC, py::arg(), py::arg(), py::arg(), py::arg() = Positions{}) - + .def("getOnChipDAC", &Detector::getOnChipDAC, py::arg(), py::arg(), + py::arg() = Positions{}) + .def("setOnChipDAC", &Detector::setOnChipDAC, py::arg(), py::arg(), + py::arg(), py::arg() = Positions{}) .def("getTimingMode", &Detector::getTimingMode, py::arg() = Positions{}) - .def("setTimingMode", &Detector::setTimingMode, py::arg(), py::arg() = Positions{}) - - // ACQUISITION .def("acquire", &Detector::acquire) - .def("startDetector", &Detector::startDetector) - .def("stopDetector", &Detector::stopDetector) + .def("clearAcquiringFlag", &Detector::clearAcquiringFlag) .def("startReceiver", &Detector::startReceiver) .def("stopReceiver", &Detector::stopReceiver) - .def("clearAcquiringFlag", &Detector::clearAcquiringFlag) + .def("startDetector", &Detector::startDetector) + .def("stopDetector", &Detector::stopDetector) .def("getDetectorStatus", &Detector::getDetectorStatus, py::arg() = Positions{}) .def("getReceiverStatus", &Detector::getReceiverStatus, py::arg() = Positions{}) - .def("getFramesCaught", &Detector::getFramesCaught, py::arg() = Positions{}) - + .def("getNumMissingPackets", &Detector::getNumMissingPackets, + py::arg() = Positions{}) .def("getStartingFrameNumber", &Detector::getStartingFrameNumber, py::arg() = Positions{}) .def("setStartingFrameNumber", &Detector::setStartingFrameNumber, py::arg(), py::arg() = Positions{}) - .def("sendSoftwareTrigger", &Detector::sendSoftwareTrigger, py::arg() = Positions{}) - - // Network Configuration (Detector<->Receiver) .def("getNumberofUDPInterfaces", &Detector::getNumberofUDPInterfaces, py::arg() = Positions{}) - .def("setNumberofUDPInterfaces", &Detector::setNumberofUDPInterfaces, py::arg(), py::arg() = Positions{}) .def("getSelectedUDPInterface", &Detector::getSelectedUDPInterface, py::arg() = Positions{}) - .def("selectUDPInterface", &Detector::selectUDPInterface, py::arg(), py::arg() = Positions{}) - - // Using lambda to allow for conversion from IpAddr - .def("getSourceUDPIP", - [](const Detector &d, Positions pos) { - std::vector res; - for (const auto &s : d.getSourceUDPIP(pos)) - res.push_back(s.str()); - return res; - }, + .def("getSourceUDPIP", &Detector::getSourceUDPIP, py::arg() = Positions{}) - - .def("setSourceUDPIP", - [](Detector &d, std::string ip, Positions pos) { - d.setSourceUDPIP(sls::IpAddr(ip), pos); - }, - py::arg(), py::arg() = Positions{}) - .def("getSourceUDPIP2", - [](const Detector &d, Positions pos) { - std::vector res; - for (const auto &s : d.getSourceUDPIP2(pos)) - res.push_back(s.str()); - return res; - }, + .def("setSourceUDPIP", &Detector::setSourceUDPIP, py::arg(), py::arg() = Positions{}) - .def("setSourceUDPIP2", - [](Detector &d, std::string ip, Positions pos) { - d.setSourceUDPIP2(sls::IpAddr(ip), pos); - }, - py::arg(), py::arg() = Positions{}) - .def("getSourceUDPMAC", - [](const Detector &d, Positions pos) { - std::vector res; - for (const auto &s : d.getSourceUDPMAC(pos)) - res.push_back(s.str()); - return res; - }, + .def("getSourceUDPIP2", &Detector::getSourceUDPIP2, py::arg() = Positions{}) - .def("setSourceUDPMAC", - [](Detector &d, std::string mac, Positions pos) { - d.setSourceUDPMAC(sls::MacAddr(mac), pos); - }, - py::arg(), py::arg() = Positions{}) - - .def("getSourceUDPMAC2", - [](const Detector &d, Positions pos) { - std::vector res; - for (const auto &s : d.getSourceUDPMAC2(pos)) - res.push_back(s.str()); - return res; - }, + .def("setSourceUDPIP2", &Detector::setSourceUDPIP2, py::arg(), py::arg() = Positions{}) - .def("setSourceUDPMAC2", - [](Detector &d, std::string mac, Positions pos) { - d.setSourceUDPMAC2(sls::MacAddr(mac), pos); - }, - py::arg(), py::arg() = Positions{}) - - .def("getDestinationUDPIP", - [](const Detector &d, Positions pos) { - std::vector res; - for (const auto &s : d.getDestinationUDPIP(pos)) - res.push_back(s.str()); - return res; - }, + .def("getSourceUDPMAC", &Detector::getSourceUDPMAC, py::arg() = Positions{}) - .def("setDestinationUDPIP", - [](Detector &d, std::string ip, Positions pos) { - d.setDestinationUDPIP(sls::IpAddr(ip), pos); - }, - py::arg(), py::arg() = Positions{}) - - .def("getDestinationUDPIP2", - [](const Detector &d, Positions pos) { - std::vector res; - for (const auto &s : d.getDestinationUDPIP2(pos)) - res.push_back(s.str()); - return res; - }, + .def("setSourceUDPMAC", &Detector::setSourceUDPMAC, py::arg(), py::arg() = Positions{}) - .def("setDestinationUDPIP2", - [](Detector &d, std::string ip, Positions pos) { - d.setDestinationUDPIP2(sls::IpAddr(ip), pos); - }, - py::arg(), py::arg() = Positions{}) - - .def("getDestinationUDPMAC", - [](const Detector &d, Positions pos) { - std::vector res; - for (const auto &s : d.getDestinationUDPMAC(pos)) - res.push_back(s.str()); - return res; - }, + .def("getSourceUDPMAC2", &Detector::getSourceUDPMAC2, py::arg() = Positions{}) - - .def("setDestinationUDPMAC", - [](Detector &d, std::string mac, Positions pos) { - d.setDestinationUDPMAC(sls::MacAddr(mac), pos); - }, - py::arg(), py::arg() = Positions{}) - - .def("getDestinationUDPMAC2", - [](const Detector &d, Positions pos) { - std::vector res; - for (const auto &s : d.getDestinationUDPMAC2(pos)) - res.push_back(s.str()); - return res; - }, + .def("setSourceUDPMAC2", &Detector::setSourceUDPMAC2, py::arg(), py::arg() = Positions{}) - - .def("setDestinationUDPMAC2", - [](Detector &d, std::string mac, Positions pos) { - d.setDestinationUDPMAC2(sls::MacAddr(mac), pos); - }, + .def("getDestinationUDPIP", &Detector::getDestinationUDPIP, + py::arg() = Positions{}) + .def("setDestinationUDPIP", &Detector::setDestinationUDPIP, py::arg(), + py::arg() = Positions{}) + .def("getDestinationUDPIP2", &Detector::getDestinationUDPIP2, + py::arg() = Positions{}) + .def("setDestinationUDPIP2", &Detector::setDestinationUDPIP2, py::arg(), + py::arg() = Positions{}) + .def("getDestinationUDPMAC", &Detector::getDestinationUDPMAC, + py::arg() = Positions{}) + .def("setDestinationUDPMAC", &Detector::setDestinationUDPMAC, py::arg(), + py::arg() = Positions{}) + .def("getDestinationUDPMAC2", &Detector::getDestinationUDPMAC2, + py::arg() = Positions{}) + .def("setDestinationUDPMAC2", &Detector::setDestinationUDPMAC2, py::arg(), py::arg() = Positions{}) - .def("getDestinationUDPPort", &Detector::getDestinationUDPPort, py::arg() = Positions{}) .def("setDestinationUDPPort", &Detector::setDestinationUDPPort, - py::arg(), py::arg() = Positions{}) + py::arg(), py::arg()) .def("getDestinationUDPPort2", &Detector::getDestinationUDPPort2, py::arg() = Positions{}) .def("setDestinationUDPPort2", &Detector::setDestinationUDPPort2, - py::arg(), py::arg() = Positions{}) - + py::arg(), py::arg()) .def("printRxConfiguration", &Detector::printRxConfiguration, py::arg() = Positions{}) - .def("getTenGiga", &Detector::getTenGiga, py::arg() = Positions{}) .def("setTenGiga", &Detector::setTenGiga, py::arg(), py::arg() = Positions{}) @@ -269,7 +205,6 @@ void init_experimental(py::module &m) { py::arg() = Positions{}) .def("setTransmissionDelayFrame", &Detector::setTransmissionDelayFrame, py::arg(), py::arg() = Positions{}) - .def("getTransmissionDelayLeft", &Detector::getTransmissionDelayLeft, py::arg() = Positions{}) .def("setTransmissionDelayLeft", &Detector::setTransmissionDelayLeft, @@ -278,21 +213,13 @@ void init_experimental(py::module &m) { py::arg() = Positions{}) .def("setTransmissionDelayRight", &Detector::setTransmissionDelayRight, py::arg(), py::arg() = Positions{}) - - /************************************************** - * * - * RECEIVER CONFIG * - * * - * ************************************************/ - .def("getUseReceiverFlag", &Detector::getUseReceiverFlag, py::arg() = Positions{}) .def("getRxHostname", &Detector::getRxHostname, py::arg() = Positions{}) .def("setRxHostname", &Detector::setRxHostname, py::arg(), py::arg() = Positions{}) .def("getRxPort", &Detector::getRxPort, py::arg() = Positions{}) - .def("setRxPort", &Detector::setRxPort, py::arg(), - py::arg() = Positions{}) + .def("setRxPort", &Detector::setRxPort, py::arg(), py::arg()) .def("getRxFifoDepth", &Detector::getRxFifoDepth, py::arg() = Positions{}) .def("setRxFifoDepth", &Detector::setRxFifoDepth, py::arg(), @@ -320,12 +247,6 @@ void init_experimental(py::module &m) { py::arg() = Positions{}) .def("getRxLastClientIP", &Detector::getRxLastClientIP, py::arg() = Positions{}) - - /************************************************** - * * - * FILE * - * * - * ************************************************/ .def("getFileFormat", &Detector::getFileFormat, py::arg() = Positions{}) .def("setFileFormat", &Detector::setFileFormat, py::arg(), py::arg() = Positions{}) @@ -336,36 +257,25 @@ void init_experimental(py::module &m) { py::arg() = Positions{}) .def("setFileNamePrefix", &Detector::setFileNamePrefix, py::arg(), py::arg() = Positions{}) - .def("getFilePath", &Detector::getFilePath) - .def("setFilePath", &Detector::setFilePath, py::arg(), - py::arg() = Positions{}) - .def("getAcquisitionIndex", &Detector::getAcquisitionIndex, py::arg() = Positions{}) .def("setAcquisitionIndex", &Detector::setAcquisitionIndex, py::arg(), py::arg() = Positions{}) - .def("setFileWrite", &Detector::setFileWrite, py::arg(), - py::arg() = Positions{}) .def("getFileWrite", &Detector::getFileWrite, py::arg() = Positions{}) - .def("setFileOverWrite", &Detector::setFileOverWrite, py::arg(), - py::arg() = Positions{}) - .def("getFileOverWrite", &Detector::getFileOverWrite, - py::arg() = Positions{}) - .def("setMasterFileWrite", &Detector::setMasterFileWrite, py::arg(), + .def("setFileWrite", &Detector::setFileWrite, py::arg(), py::arg() = Positions{}) .def("getMasterFileWrite", &Detector::getMasterFileWrite, py::arg() = Positions{}) - .def("setFramesPerFile", &Detector::setFramesPerFile, py::arg(), + .def("setMasterFileWrite", &Detector::setMasterFileWrite, py::arg(), + py::arg() = Positions{}) + .def("getFileOverWrite", &Detector::getFileOverWrite, + py::arg() = Positions{}) + .def("setFileOverWrite", &Detector::setFileOverWrite, py::arg(), py::arg() = Positions{}) .def("getFramesPerFile", &Detector::getFramesPerFile, py::arg() = Positions{}) - - /************************************************** - * * - * ZMQ Streaming Parameters (Receiver<->Client)* - * * - * ************************************************/ - + .def("setFramesPerFile", &Detector::setFramesPerFile, py::arg(), + py::arg() = Positions{}) .def("getRxZmqDataStream", &Detector::getRxZmqDataStream, py::arg() = Positions{}) .def("setRxZmqDataStream", &Detector::setRxZmqDataStream, py::arg(), @@ -378,29 +288,21 @@ void init_experimental(py::module &m) { .def("setRxZmqTimer", &Detector::setRxZmqTimer, py::arg(), py::arg() = Positions{}) .def("getRxZmqPort", &Detector::getRxZmqPort, py::arg() = Positions{}) - .def("setRxZmqPort", &Detector::setRxZmqPort, py::arg(), - py::arg() = Positions{}) + .def("setRxZmqPort", &Detector::setRxZmqPort, py::arg(), py::arg()) .def("getRxZmqIP", &Detector::getRxZmqIP, py::arg() = Positions{}) .def("setRxZmqIP", &Detector::setRxZmqIP, py::arg(), py::arg() = Positions{}) .def("getClientZmqPort", &Detector::getClientZmqPort, py::arg() = Positions{}) .def("setClientZmqPort", &Detector::setClientZmqPort, py::arg(), - py::arg() = -1) + py::arg()) .def("getClientZmqIp", &Detector::getClientZmqIp, py::arg() = Positions{}) .def("setClientZmqIp", &Detector::setClientZmqIp, py::arg(), py::arg() = Positions{}) - - /************************************************** - * * - * Eiger Specific * - * * - * ************************************************/ - .def("getDynamicRange", &Detector::getDynamicRange, py::arg() = Positions{}) - .def("setDynamicRange", &Detector::setDynamicRange) + .def("setDynamicRange", &Detector::setDynamicRange, py::arg()) .def("getSubExptime", &Detector::getSubExptime, py::arg() = Positions{}) .def("setSubExptime", &Detector::setSubExptime, py::arg(), py::arg() = Positions{}) @@ -408,12 +310,10 @@ void init_experimental(py::module &m) { py::arg() = Positions{}) .def("setSubDeadTime", &Detector::setSubDeadTime, py::arg(), py::arg() = Positions{}) - .def("getThresholdEnergy", &Detector::getThresholdEnergy, py::arg() = Positions{}) .def("setThresholdEnergy", &Detector::setThresholdEnergy, py::arg(), - py::arg() = defs::STANDARD, py::arg() = true, - py::arg() = Positions{}) + py::arg(), py::arg(), py::arg() = Positions{}) .def("getSettingsPath", &Detector::getSettingsPath, py::arg() = Positions{}) .def("setSettingsPath", &Detector::setSettingsPath, py::arg(), @@ -422,7 +322,7 @@ void init_experimental(py::module &m) { py::arg() = Positions{}) .def("getRxAddGapPixels", &Detector::getRxAddGapPixels, py::arg() = Positions{}) - .def("setRxAddGapPixels", &Detector::setRxAddGapPixels) + .def("setRxAddGapPixels", &Detector::setRxAddGapPixels, py::arg()) .def("getParallelMode", &Detector::getParallelMode, py::arg() = Positions{}) .def("setParallelMode", &Detector::setParallelMode, py::arg(), @@ -448,10 +348,10 @@ void init_experimental(py::module &m) { py::arg() = Positions{}) .def("getRateCorrection", &Detector::getRateCorrection, py::arg() = Positions{}) - .def("setRateCorrection", &Detector::setRateCorrection, py::arg(), - py::arg() = Positions{}) .def("setDefaultRateCorrection", &Detector::setDefaultRateCorrection, py::arg() = Positions{}) + .def("setRateCorrection", &Detector::setRateCorrection, py::arg(), + py::arg() = Positions{}) .def("getPartialReadout", &Detector::getPartialReadout, py::arg() = Positions{}) .def("setPartialReadout", &Detector::setPartialReadout, py::arg(), @@ -460,7 +360,6 @@ void init_experimental(py::module &m) { py::arg() = Positions{}) .def("setInterruptSubframe", &Detector::setInterruptSubframe, py::arg(), py::arg() = Positions{}) - .def("getMeasuredPeriod", &Detector::getMeasuredPeriod, py::arg() = Positions{}) .def("getMeasuredSubFramePeriod", &Detector::getMeasuredSubFramePeriod, @@ -476,7 +375,6 @@ void init_experimental(py::module &m) { py::arg() = Positions{}) .def("setPartialReset", &Detector::setPartialReset, py::arg(), py::arg() = Positions{}) - .def("pulsePixel", &Detector::pulsePixel, py::arg(), py::arg(), py::arg() = Positions{}) .def("pulsePixelNMove", &Detector::pulsePixelNMove, py::arg(), @@ -484,13 +382,7 @@ void init_experimental(py::module &m) { .def("pulseChip", &Detector::pulseChip, py::arg(), py::arg() = Positions{}) .def("getQuad", &Detector::getQuad, py::arg() = Positions{}) - .def("setQuad", &Detector::setQuad) - - /************************************************** - * * - * Jungfrau Specific * - * * - * ************************************************/ + .def("setQuad", &Detector::setQuad, py::arg()) .def("getThresholdTemperature", &Detector::getThresholdTemperature, py::arg() = Positions{}) .def("setThresholdTemperature", &Detector::setThresholdTemperature, @@ -503,7 +395,6 @@ void init_experimental(py::module &m) { py::arg() = Positions{}) .def("resetTemperatureEvent", &Detector::resetTemperatureEvent, py::arg() = Positions{}) - .def("getPowerChip", &Detector::getPowerChip, py::arg() = Positions{}) .def("setPowerChip", &Detector::setPowerChip, py::arg(), py::arg() = Positions{}) @@ -511,70 +402,45 @@ void init_experimental(py::module &m) { py::arg() = Positions{}) .def("setAutoCompDisable", &Detector::setAutoCompDisable, py::arg(), py::arg() = Positions{}) - .def("getNumberOfAdditionalStorageCells", - &Detector::getNumberOfAdditionalStorageCells) + &Detector::getNumberOfAdditionalStorageCells, + py::arg() = Positions{}) .def("setNumberOfAdditionalStorageCells", - &Detector::setNumberOfAdditionalStorageCells) + &Detector::setNumberOfAdditionalStorageCells, py::arg()) .def("getStorageCellStart", &Detector::getStorageCellStart, py::arg() = Positions{}) .def("setStoragecellStart", &Detector::setStoragecellStart, py::arg(), py::arg() = Positions{}) - + .def("getStorageCellDelay", &Detector::getStorageCellDelay, + py::arg() = Positions{}) .def("setStorageCellDelay", &Detector::setStorageCellDelay, py::arg(), py::arg() = Positions{}) - - // Bits and registers - .def("setBit", &Detector::setBit, py::arg(), py::arg(), + .def("getROI", &Detector::getROI, py::arg() = Positions{}) + .def("setROI", &Detector::setROI, py::arg(), py::arg()) + .def("clearROI", &Detector::clearROI, py::arg() = Positions{}) + .def("getExptimeLeft", &Detector::getExptimeLeft, py::arg() = Positions{}) - .def("clearBit", &Detector::clearBit, py::arg(), py::arg(), + .def("getExternalSignalFlags", &Detector::getExternalSignalFlags, py::arg() = Positions{}) - .def("readRegister", &Detector::readRegister, py::arg(), - py::arg() = Positions{}) - - .def("writeRegister", &Detector::writeRegister, py::arg(), py::arg(), - py::arg() = Positions{}) - - .def("getStartingFrameNumber", &Detector::getStartingFrameNumber, - py::arg() = Positions{}) - .def("setStartingFrameNumber", &Detector::setStartingFrameNumber, + .def("setExternalSignalFlags", &Detector::setExternalSignalFlags, py::arg(), py::arg() = Positions{}) - - /************************************************** - * * - * Insignificant * - * * - * ************************************************/ - - .def("getControlPort", &Detector::getControlPort, + .def("getImageTestMode", &Detector::getImageTestMode, py::arg() = Positions{}) - .def("setControlPort", &Detector::setControlPort, py::arg(), + .def("setImageTestMode", &Detector::setImageTestMode, py::arg(), py::arg() = Positions{}) - .def("getStopPort", &Detector::getStopPort, py::arg() = Positions{}) - .def("setStopPort", &Detector::setStopPort, py::arg(), + .def("getInjectChannel", &Detector::getInjectChannel, py::arg() = Positions{}) - .def("getDetectorLock", &Detector::getDetectorLock, + .def("setInjectChannel", &Detector::setInjectChannel, py::arg(), + py::arg(), py::arg() = Positions{}) + .def("getVetoPhoton", &Detector::getVetoPhoton, py::arg(), py::arg() = Positions{}) - .def("setDetectorLock", &Detector::setDetectorLock, py::arg(), + .def("setVetoPhoton", &Detector::setVetoPhoton, py::arg(), py::arg(), + py::arg(), py::arg(), py::arg() = Positions{}) + .def("setVetoReference", &Detector::setVetoReference, py::arg(), + py::arg(), py::arg() = Positions{}) + .def("setBurstMode", &Detector::setBurstMode, py::arg(), py::arg() = Positions{}) - .def("getLastClientIP", &Detector::getLastClientIP, - py::arg() = Positions{}) - .def("executeCommand", &Detector::executeCommand, py::arg(), - py::arg() = Positions{}) - .def("getNumberOfFramesFromStart", - &Detector::getNumberOfFramesFromStart, py::arg() = Positions{}) - .def("getActualTime", &Detector::getActualTime, py::arg() = Positions{}) - .def("getMeasurementTime", &Detector::getMeasurementTime, - py::arg() = Positions{}) - .def("getUserDetails", &Detector::getUserDetails) - .def("getRxCurrentFrameIndex", &Detector::getRxCurrentFrameIndex, - py::arg() = Positions{}) - - /************************************************** - * * - * CTB Specific * - * * - * ************************************************/ + .def("getBurstMode", &Detector::getBurstMode, py::arg() = Positions{}) .def("getNumberOfAnalogSamples", &Detector::getNumberOfAnalogSamples, py::arg() = Positions{}) .def("setNumberOfAnalogSamples", &Detector::setNumberOfAnalogSamples, @@ -606,11 +472,161 @@ void init_experimental(py::module &m) { .def("setRUNClock", &Detector::setRUNClock, py::arg(), py::arg() = Positions{}) .def("getSYNCClock", &Detector::getSYNCClock, py::arg() = Positions{}) - - // Time - - .def("setSubExptime", &Detector::setSubExptime, py::arg(), + .def("getADCPipeline", &Detector::getADCPipeline, py::arg() = Positions{}) - .def("getSubExptime", &Detector::getSubExptime, + .def("setADCPipeline", &Detector::setADCPipeline, py::arg(), + py::arg() = Positions{}) + .def("getDBITPipeline", &Detector::getDBITPipeline, + py::arg() = Positions{}) + .def("setDBITPipeline", &Detector::setDBITPipeline, py::arg(), + py::arg() = Positions{}) + .def("getVoltage", &Detector::getVoltage, py::arg(), + py::arg() = Positions{}) + .def("setVoltage", &Detector::setVoltage, py::arg(), py::arg(), + py::arg() = Positions{}) + .def("getMeasuredVoltage", &Detector::getMeasuredVoltage, py::arg(), + py::arg() = Positions{}) + .def("getMeasuredCurrent", &Detector::getMeasuredCurrent, py::arg(), + py::arg() = Positions{}) + .def("getSlowADC", &Detector::getSlowADC, py::arg(), + py::arg() = Positions{}) + .def("getADCEnableMask", &Detector::getADCEnableMask, + py::arg() = Positions{}) + .def("setADCEnableMask", &Detector::setADCEnableMask, py::arg(), + py::arg() = Positions{}) + .def("getTenGigaADCEnableMask", &Detector::getTenGigaADCEnableMask, + py::arg() = Positions{}) + .def("setTenGigaADCEnableMask", &Detector::setTenGigaADCEnableMask, + py::arg(), py::arg() = Positions{}) + .def("getADCInvert", &Detector::getADCInvert, py::arg() = Positions{}) + .def("setADCInvert", &Detector::setADCInvert, py::arg(), + py::arg() = Positions{}) + .def("getExternalSamplingSource", &Detector::getExternalSamplingSource, + py::arg() = Positions{}) + .def("setExternalSamplingSource", &Detector::setExternalSamplingSource, + py::arg(), py::arg() = Positions{}) + .def("getExternalSampling", &Detector::getExternalSampling, + py::arg() = Positions{}) + .def("setExternalSampling", &Detector::setExternalSampling, py::arg(), + py::arg() = Positions{}) + .def("getRxDbitList", &Detector::getRxDbitList, py::arg() = Positions{}) + .def("setRxDbitList", &Detector::setRxDbitList, py::arg(), + py::arg() = Positions{}) + .def("getRxDbitOffset", &Detector::getRxDbitOffset, + py::arg() = Positions{}) + .def("setRxDbitOffset", &Detector::setRxDbitOffset, py::arg(), + py::arg() = Positions{}) + .def("setDigitalIODelay", &Detector::setDigitalIODelay, py::arg(), + py::arg(), py::arg() = Positions{}) + .def("getLEDEnable", &Detector::getLEDEnable, py::arg() = Positions{}) + .def("setLEDEnable", &Detector::setLEDEnable, py::arg(), + py::arg() = Positions{}) + .def("setPattern", &Detector::setPattern, py::arg(), + py::arg() = Positions{}) + .def("savePattern", &Detector::savePattern, py::arg()) + .def("getPatternIOControl", &Detector::getPatternIOControl, + py::arg() = Positions{}) + .def("setPatternIOControl", &Detector::setPatternIOControl, py::arg(), + py::arg() = Positions{}) + .def("getPatternClockControl", &Detector::getPatternClockControl, + py::arg() = Positions{}) + .def("setPatternClockControl", &Detector::setPatternClockControl, + py::arg(), py::arg() = Positions{}) + .def("getPatternWord", &Detector::getPatternWord, py::arg(), + py::arg() = Positions{}) + .def("setPatternWord", &Detector::setPatternWord, py::arg(), py::arg(), + py::arg() = Positions{}) + .def("getPatternLoopAddresses", &Detector::getPatternLoopAddresses, + py::arg(), py::arg() = Positions{}) + .def("setPatternLoopAddresses", &Detector::setPatternLoopAddresses, + py::arg(), py::arg(), py::arg(), py::arg() = Positions{}) + .def("getPatternLoopCycles", &Detector::getPatternLoopCycles, py::arg(), + py::arg() = Positions{}) + .def("setPatternLoopCycles", &Detector::setPatternLoopCycles, py::arg(), + py::arg(), py::arg() = Positions{}) + .def("getPatternWaitAddr", &Detector::getPatternWaitAddr, py::arg(), + py::arg() = Positions{}) + .def("setPatternWaitAddr", &Detector::setPatternWaitAddr, py::arg(), + py::arg(), py::arg() = Positions{}) + .def("getPatternWaitTime", &Detector::getPatternWaitTime, py::arg(), + py::arg() = Positions{}) + .def("setPatternWaitTime", &Detector::setPatternWaitTime, py::arg(), + py::arg(), py::arg() = Positions{}) + .def("getPatternMask", &Detector::getPatternMask, + py::arg() = Positions{}) + .def("setPatternMask", &Detector::setPatternMask, py::arg(), + py::arg() = Positions{}) + .def("getPatternBitMask", &Detector::getPatternBitMask, + py::arg() = Positions{}) + .def("setPatternBitMask", &Detector::setPatternBitMask, py::arg(), + py::arg() = Positions{}) + .def("getAdditionalJsonHeader", &Detector::getAdditionalJsonHeader, + py::arg() = Positions{}) + .def("setAdditionalJsonHeader", &Detector::setAdditionalJsonHeader, + py::arg(), py::arg() = Positions{}) + .def("getAdditionalJsonParameter", + &Detector::getAdditionalJsonParameter, py::arg(), + py::arg() = Positions{}) + .def("setAdditionalJsonParameter", + &Detector::setAdditionalJsonParameter, py::arg(), py::arg(), + py::arg() = Positions{}) + .def("getDetectorMinMaxEnergyThreshold", + &Detector::getDetectorMinMaxEnergyThreshold, py::arg(), + py::arg() = Positions{}) + .def("setDetectorMinMaxEnergyThreshold", + &Detector::setDetectorMinMaxEnergyThreshold, py::arg(), py::arg(), + py::arg() = Positions{}) + .def("getFrameMode", &Detector::getFrameMode, py::arg() = Positions{}) + .def("setFrameMode", &Detector::setFrameMode, py::arg(), + py::arg() = Positions{}) + .def("getDetectorMode", &Detector::getDetectorMode, + py::arg() = Positions{}) + .def("setDetectorMode", &Detector::setDetectorMode, py::arg(), + py::arg() = Positions{}) + .def("programFPGA", &Detector::programFPGA, py::arg(), + py::arg() = Positions{}) + .def("resetFPGA", &Detector::resetFPGA, py::arg() = Positions{}) + .def("copyDetectorServer", &Detector::copyDetectorServer, py::arg(), + py::arg(), py::arg() = Positions{}) + .def("rebootController", &Detector::rebootController, + py::arg() = Positions{}) + .def("updateFirmwareAndServer", &Detector::updateFirmwareAndServer, + py::arg(), py::arg(), py::arg(), py::arg() = Positions{}) + .def("readRegister", &Detector::readRegister, py::arg(), + py::arg() = Positions{}) + .def("writeRegister", &Detector::writeRegister, py::arg(), py::arg(), + py::arg() = Positions{}) + .def("setBit", &Detector::setBit, py::arg(), py::arg(), + py::arg() = Positions{}) + .def("clearBit", &Detector::clearBit, py::arg(), py::arg(), + py::arg() = Positions{}) + .def("executeFirmwareTest", &Detector::executeFirmwareTest, + py::arg() = Positions{}) + .def("executeBusTest", &Detector::executeBusTest, + py::arg() = Positions{}) + .def("writeAdcRegister", &Detector::writeAdcRegister, py::arg(), + py::arg(), py::arg() = Positions{}) + .def("getControlPort", &Detector::getControlPort, + py::arg() = Positions{}) + .def("setControlPort", &Detector::setControlPort, py::arg(), + py::arg() = Positions{}) + .def("getStopPort", &Detector::getStopPort, py::arg() = Positions{}) + .def("setStopPort", &Detector::setStopPort, py::arg(), + py::arg() = Positions{}) + .def("getDetectorLock", &Detector::getDetectorLock, + py::arg() = Positions{}) + .def("setDetectorLock", &Detector::setDetectorLock, py::arg(), + py::arg() = Positions{}) + .def("getLastClientIP", &Detector::getLastClientIP, + py::arg() = Positions{}) + .def("executeCommand", &Detector::executeCommand, py::arg(), + py::arg() = Positions{}) + .def("getNumberOfFramesFromStart", + &Detector::getNumberOfFramesFromStart, py::arg() = Positions{}) + .def("getActualTime", &Detector::getActualTime, py::arg() = Positions{}) + .def("getMeasurementTime", &Detector::getMeasurementTime, + py::arg() = Positions{}) + .def("getUserDetails", &Detector::getUserDetails) + .def("getRxCurrentFrameIndex", &Detector::getRxCurrentFrameIndex, py::arg() = Positions{}); } diff --git a/python/src/detector_in.cpp b/python/src/detector_in.cpp new file mode 100644 index 000000000..38ec13a1b --- /dev/null +++ b/python/src/detector_in.cpp @@ -0,0 +1,21 @@ +#include +#include +#include +#include + +#include "Detector.h" +#include "ToString.h" +#include "network_utils.h" +#include "sls_detector_defs.h" +#include "typecaster.h" +namespace py = pybind11; +void init_det(py::module &m) { + using sls::Detector; + using sls::Positions; + + py::class_ CppDetectorApi(m, "CppDetectorApi"); + CppDetectorApi + .def(py::init()) + + [[FUNCTIONS]] +} diff --git a/python/src/main.cpp b/python/src/main.cpp index bf2cace69..2d3c300d6 100755 --- a/python/src/main.cpp +++ b/python/src/main.cpp @@ -17,6 +17,8 @@ using ds = std::chrono::duration; namespace py = pybind11; void init_enums(py::module &); void init_experimental(py::module &); +void init_det(py::module &); +void init_network(py::module &); PYBIND11_MODULE(_sls_detector, m) { m.doc() = R"pbdoc( C/C++ API @@ -29,7 +31,9 @@ PYBIND11_MODULE(_sls_detector, m) { )pbdoc"; init_enums(m); - init_experimental(m); + init_det(m); + init_network(m); + // init_experimental(m); py::module io = m.def_submodule("io", "Submodule for io"); diff --git a/python/src/network.cpp b/python/src/network.cpp new file mode 100644 index 000000000..000e84e16 --- /dev/null +++ b/python/src/network.cpp @@ -0,0 +1,39 @@ +/* +This file contains Python bindings for the IpAddr and MacAddr +classes. +*/ + + +#include +#include +#include +#include + +#include "network_utils.h" +namespace py = pybind11; +using sls::IpAddr; +using sls::MacAddr; +void init_network(py::module &m) { + + py::class_ IpAddr(m, "IpAddr"); + IpAddr.def(py::init()) + .def(py::init()) + .def(py::init()) + .def("hex", &IpAddr::hex) + .def("uint32", &IpAddr::uint32) + .def(py::self == py::self) + .def("__repr__", &IpAddr::str) + .def("str", &IpAddr::str); + + + py::class_ MacAddr(m, "MacAddr"); + MacAddr.def(py::init()) + .def(py::init()) + .def(py::init()) + .def("hex", &MacAddr::hex) + .def(py::self == py::self) + .def("uint64", &MacAddr::uint64) + .def("__repr__", &MacAddr::str) + .def("str", &MacAddr::str); + +} diff --git a/slsDetectorSoftware/tests/test-CmdProxy-eiger.cpp b/slsDetectorSoftware/tests/test-CmdProxy-eiger.cpp index 1418e5c83..893d7d6db 100644 --- a/slsDetectorSoftware/tests/test-CmdProxy-eiger.cpp +++ b/slsDetectorSoftware/tests/test-CmdProxy-eiger.cpp @@ -13,7 +13,7 @@ using sls::Detector; using test::GET; using test::PUT; -TEST_CASE("Eiger transmission delay") { +TEST_CASE("Eiger transmission delay", "[.cmd]") { Detector det; CmdProxy proxy(&det); auto det_type = det.getDetectorType().squash(); diff --git a/slsDetectorSoftware/tests/test-CmdProxy.cpp b/slsDetectorSoftware/tests/test-CmdProxy.cpp index b5b28cc4d..e1504c10e 100644 --- a/slsDetectorSoftware/tests/test-CmdProxy.cpp +++ b/slsDetectorSoftware/tests/test-CmdProxy.cpp @@ -3014,7 +3014,7 @@ TEST_CASE("zmqip", "[.cmd]") { } } -TEST_CASE("zmqport") { +TEST_CASE("zmqport", "[.cmd]") { Detector det; CmdProxy proxy(&det); diff --git a/slsSupportLib/include/network_utils.h b/slsSupportLib/include/network_utils.h index 12bc4a125..df411468d 100755 --- a/slsSupportLib/include/network_utils.h +++ b/slsSupportLib/include/network_utils.h @@ -38,6 +38,7 @@ class MacAddr { std::string to_hex(const char delimiter = 0) const; public: + constexpr MacAddr() noexcept{} constexpr MacAddr(uint64_t mac) noexcept : addr_{mac} {} MacAddr(std::string mac); MacAddr(const char *address);