mirror of
https://github.com/slsdetectorgroup/slsDetectorPackage.git
synced 2025-06-05 01:20:41 +02:00
9.0.0.rc (#1058)
* dev: update 2d gain plot color map (if no x and ymin/max changes or window resizing): setFixedWidth was updating for window resize, updated virtual servers for g2 and jungfrau to keep changing gain and data for every frame. the data value (#819) * Dev/jf/fix pedestal (#821) * jf pedestal fix: touch enable bit last * dev: jf sync: stopping master gives idle (#824) * jf sync mode master could return idle when stopped and so not all modules return the same value and must check for 'stopped or idle', Also must throw if any of the module gives an error * added contains_only to sls::Result (#827) * added variadic template for checking if a result contains only specified values * fix for gcc4.8 * renamed to Result::contains_only * updated condition in Detector.cpp * stop on only the positions --------- Co-authored-by: Erik Fröjdh <erik.frojdh@gmail.com> * dev jf: change status reg bits (#829) * jf: rewrite of status reg bits, waiting state includes both wati for trigger and start frame, blocking trigger only waits if its not in waiting for trigger and run busy enabled, error state connected in firmware * dev jf: reconfigure chip when touching electron collection mode bit (#831) * jf: if bit 14 in reg 0x5d (electron mode collection bit) is changed, configure chip if v1.1 and powered on. so touch writeregister (setbit/clearbit also calls write register in the end). replace when electroncollectionmode command introduced * eiger required fw version to 32: fix for blocking trigger in quad (#834) * fix warning for prev_val (variable size array) in tests (#838) * Dev: : gui acq finished callback for different status (#850) * fix acquisition finished status to have different status for different modules, but does not have to be error. for eg. jf sync fw (2.4.1 gives idle for master and stopped for slaves when stopping acquiistion) * handling inconsistent fnums to be -1 in gui, so when one sets 0 (change of value) will also give an exception (#854) * Dev: fix py virtual test (#846) * draft to fix virtual test when it fails * catching errors in tests and removing sigchild ignore so servers (process in background) executing commands will not fail (pclose no child processes, if sigchld is ignored) fixed * uncommented python loading config * somehow killal slsReciever in second detector test fails even though no receiver running * fixing script for virtual simlator test:fixed issue with check if process running, fixed moench tests * formatting * tests for jf (#835) * execute command inside server fixed (from fix simulator tests and exec command PR) (#857) * dev: fix server logic in checking detector idle (#861) * fix buggy logic in checking detector idle and an argument check * Dev: trigger signal issues handled at acquire (#864) * if blocking and handling sync, only master gets blocking acq, slaves get non blocking as they are first and so dont get status or error caught when slaves dont get trigger (due to not connected etc) and acq returns with slaves still in waiting status. so check status of all in blocking acq * for all dets with sync, ensure atleast one master when starting acq * docs updated about sync * minor fix for test_simulator * updating docs * fixed doc * added python 3.12 to the conda build variants * documentation and examples * formatting * forward declare zmq_msg_t and moved include (#869) * forward declare zmq_msg_t and moved include * removed zmq from pkg list * removed zmq as dependency for slsdet (#870) * dev: moench: min exptime (#865) * moench: remove min clock cycles for setting exptime (had been ported from jf) * commands code generation (#871) * commands code generation (#803) * commands code generation for only frames command * fix cmake file and add Caller files * working exptime, fully extended commands file and its variants * start adding template commands * add INT_CMD_VEC_ID template * add list command, generate multiple bins, format code * reach 208 commands using the cpp macros * add tests for command parser * start adding tests for commands parser * fix typo to use commands.yaml * add more tests for command_parser * add all template functions (up to 218 commands) * finish template functions and add more CmdProxy.cpp functions (250+) * 257 commands * 300 commands the rest are very special commands * add special commands without generation * separate special functions from generated c++ file * implementing one command for put and get (buggy) * add infer action in a separate file * generate header for special commands from yaml * allow only 0 or 1 for bool inputs * group all commands in gen_commands.py * add help to gen_commands.py * add autocomplete bash script * autocompletion: add support for module levels and help * remove debugging line * add autocompletion, help to commands, change int [0,1] to bool * copy tests for Caller.cpp. Tests pass * update with the new developer branch changes * fix errors after merging (there is problems with tests) * fixed port/stopport in yaml (intput typo), added '_caller' to the test dac and test on chip dac command in global test for cmdcaller * undo previous test simulator debug change * add documentation for the generated code * reducing the comment to be replaced in length so formatting does not split into 2 lines * removed formatting specific style of C++11 in gen_commands.py to keep with the top level clang format of the project * regeneratign code for commands * automation generated * Redirect deprecated commands (#872) * working implementation, need to fix dac * fixed deprecation redirect for dac command * Detector specific autocomplete (#873) * working implementation, need to fix dac * fixed deprecation redirect for dac command * detector specific completion for dac * added autocomplete using detector specific * fixed error when autocompleting partial words * Generate commands/fix commands (#875) * fix vm_a, im_a etc have deg Celsius suffix, also help missing or changed in some places * dac: require det id for all, arg0 to be printed at output, help for onchip dac and dac, onchipdac: spacing * getscan detid and blocking trigger help * udp_Dstlist det_id fixed, but rx_id invalid * cmdApp in line with cmdLineApp (missing version, receiver_id, not creating det object in help action * added set_command to differentiate between check_det_id and require_det_id (mixed up), args: -1 needs to check for at least one argument * reordering * reordering and checked till integer_command_hex * fixed a lot more commands * fix caller tests for eiger * changes to tests after Bechir left * changing .cmd to .cmdcall for the caller commands * fixed tests for caller, still warning for setexptime about cast input * autocomplete ran * add moench test * regenerating autocomplete and commands * fixing other things from merge conflicts (renaming slsDetectorDefs to defs in commands.yaml) * formatting * added code injection to help (#876) * updated 3 commands to have get output that can be put into put (#877) * updated some commands to have get output that can be put into put * fix tests for clkdiv * adding help to free (#878) * removing old commands and renaming them, (also making it work for parameters command as it was still calling cmdproxy) (#879) * More helpful error messages for unsupported actions (#880) * removing old commands and renaming them, (also making it work for parameters command as it was still calling cmdproxy) * Added specific help for unsupported actions * fixed a vetofile get special exception message. more specific warning for special exception message instead of no function warning * added condition checking true in exceptions for special message --------- Co-authored-by: Bechir Brahem <bachbrahem@gmail.com> Co-authored-by: Erik Frojdh <erik.frojdh@gmail.com> Co-authored-by: Dhanya Thattil <dhanya.thattil@psi.ch> * Generate commands/fix det command rename (#881) * made a link to bash autocompletion script in main folder, and replaced all references to 'det' command with 'sls_detector' * Generate commands/fix detp detg command rename (#882) * replacing detp with sls_Detector_put and detg with sls_detector_get * sls_detector_not implemented, but extended message to ask user to use sls_detector_get or sls_detector_put * autocompletion also for sls_detector or det * Xilinx ctb (#884) * updated registers, arm64 * compiler set to aarch64 for xilinx server * updated RegisterDefs.h * merge into generate branch and resolving conflicts and adding the xilinx changes to callerspecial and commands.yaml * compiles and can print firmware version (using a different csp0 address) * fixing other servers (gotthard, jungfrau, moench, mythen3) that it returns in case of mapping failure, xilinxctb: added that it checks type, prints proper fw version, checks kernel date, added armprocessor define to use in common places, added specifiers to supress overflow and truncation warnings * added detector ip and mac adddress to the printout * fixed tests and recompiled servers * Xilinx client tests (#887) * implemented testbus, testfpga, set/get #frames, triggers, allowed that and for connection to client, also allowed, getnumchannels, configuremac, getrunstatus, setdetectorposition with dummy values * allowing tests for xilinx * binaries in * Dev/xilinx defaults and pattern (#888) * implemented testbus, testfpga, set/get #frames, triggers, allowed that and for connection to client, also allowed, getnumchannels, configuremac, getrunstatus, setdetectorposition with dummy values * connected kernelversion, hardwareversion, versions, framesl, triggersl, dr, timingmode, pattern (except patioctrl) thats there for altera ctb * replaced set/get64Bit to set/getU64bit in all loadpattern.c for (ctb and m3 also) * minor * updated commands generation * formatting * moench default speed set to after init readout configuration (half speed) (#886) * Fixed path when building as submodule * Moench v8 (#892) * new rct structure for moench03 * new moench data structure for offline processing * meonch raw data and zmq process files updated to 7.0.3 version * implemented config file for Zmq file * raw data and zmq work with config file, but only with one file/interface * zmq config change * added config examples for zmq and rawdata * pmod for 7.0.3 and 8.0.0 from previous releases * updated pmod 8.0.1 for rh7 and rh8 * m3 fix to get kernel version properly on nios without an incorrect error msg (#898) * moench: changed max shifts of adc clk from 240 to 200 (#900) * Protect from getenv("HOME") returning nullptr (#907) (#908) * Protect from getenv("HOME") returning nullptr (e.g., in case running in systemd) * Write proper warning in Module.cpp Co-authored-by: Filip Leonarski <filip.leonarski@psi.ch> * Dev/xilinx acq (#901) * period and exptime(patternwaittime level 0) * added new regsieterdefs and updated api version and fixedpattern reg * autogenerate commands * formatting * minor * wip resetflow, readout mode, transceiver mask, transceiver enable * acquisition, but streaming done bit and busy (exposing + read chip to fifo) not known yet from fw * programming fpga and device tree done * most configuration done, need to connect configuretransceiver to client * stuck at resetting transciever timed out * minor * fixed virtual, added chip busyto fifo, streaming busy, set/getnext framenumber * configuretransceiver from client, added help in client * make formatt and command generation * tests for xilinx ctb works * command generation * dacs added and tested, power not done * power added * added temp_fpga * binaries in * ctrlreg is 0 to enable chip=fixed, high dac val = min val= fixed, power regulators in weird order=fixed, device tree could be loaded with dacs before adcs=fixed * start works * virtual server sends * receiver works * tests * python function and enum generation, commands generatorn and autocomplete, formatting, tests * tests fail at start(transceiver not aligned) * tests passed * all binaries compiled * eiger binary in * added --nomodule cehck for xilinx * updated binaries * formatting * moench server: changed default values of adcphase for full speed from 300 to 150 and dac vipre_cds from 800 to 1280 (#922) * client bug fix: m3 multi module bad channel file throws bad allocation when modules skipped, needed to add vectors in 2d vector of bad channel list (#920) Co-authored-by: Erik Fröjdh <erik.frojdh@gmail.com> * developer: blocking acquire stop with slave temporarily in waiting (#926) * client: stopping a blocking acquire of multi modules checks status to catch slaves that might still be in waiting. Problem is (gotthard2 25um at least) slave is in waiting only temporarily before going go idle/stopped. So a 50ms sleep is necessary ot not throw an unnecessary error * client: when stopping blocking acquire, wait up to 1s in 50ms increments for slave to stop waiting temporarily * fix to rapidjson for build with gcc 14 (#929) * Dev: m3 clkdiv0 20 (#924) * m3: clk 0 changed from 10 to 20 (100MHz to 50MHz) * g2: startup clk div back to 10 as in firmware but setting in software startup to 20 * m3: minor print error if clk divider > max * G2: reconfigure chip (#927) * changed common.c readADCFromFile to make it more general and move temperature calculation for Eiger out of this function and inside whereever it is called. * g2 and m2: gethighvoltage was just a variable set in server, it is now moved to a get inside DAC5671 implementation (but not reading a measured value, instead what is set from a file), high voltage variable used inside DAC5671 for virtual servers * g2: switching off hv (ifrom non zero to zero value) will wait for 10s; powering on chip reconfigures chip; powering off chip unconfigures chip; powering off chip also includes check if hv = 0, if not throw exception; chip configuration checked before acquring; at start up: hv switched off and chip powered on, so does not wait 10s to switch off hv; * included test to check powering off chip when hv is on should throw an exception * g2: check if chip configured before acquiring * nios: read hv value set from file and virtual still goes into DAC5671 for conversions to and fro dac to V, change common readadc to readparameter to generalize, make sethighvoltage into a get and set to catch errors in get as well, g2: if not at startup, remmeber hv value before setting it and after check if value was being switched off (from a non zero value) and wait 10s if it was (10s wait only for switching off from non zero and not at startup) * developer: moench empty data callback (#936) * moench (feature to wait for post processing to be done in new sls_detector_acquire_zmq executable) READOUT_ACTION_ZMQ added to action enums sls_detector_acquire_zmq added to executables empty data call back so that client listens to last dummy zmq packet from moench post processor processor: remove NEWZMQ ifdefs and remove connect for zmq publisher socket * fix to compile * cmds generated and parsed * dev: client: status for blocking acquire stop with slave temporarily in waiting (#944) * acq finish call back gets status squashed with default error but before that need to wait for gotthard slaves to catch up from waiting to stopped * bug fixes related to file saving (#931) (#946) * fix the file path resetting issue of GUI in the case where different modules have different fpath setting. * fix stack-buffer-overflow issue when using HDF5 HDF5DataFile::parameterDataTypes have 64bit type (i.e. STD_U64LE), the size of fill_value should be at least 8 bytes. * change the type of fill_value to uint64_t Co-authored-by: Z.H. Li <zhenghenge@gmail.com> * updated documentation from martin (#948) * Dev/xilinx ctb test (#942) * voltage regulators only looks at dac and not at ctrl_reg * xilinx: change dac max to 2048, setting dac ist not inverse conversion from dac to voltage anymore, but setting power is inverse, also there is max and min to power, a different min for vio and this is checked at funcs interface, not printign or converting to mv in dac for power regulators (as its conversion max and min are different) * Use links for dacs/adc and adapt power rglt thresholds * Remove wait for transceiver reset * adc and dac device not used anymore and hence removed * udp restucturing: arm has to be multiple of 16 and no byteswap in udp_gen, option to compile locally in arm architecture, memsize of the second udp memory has to be limited --------- Co-authored-by: Martin Brückner <martin.brueckner@psi.ch> * formatting * dev: jungfrau HW 1.0: adc output clock phase to 120 (#952) * jungfrau: change adc output clock phase from 180 to 120 for v1.0 boards for reliable readout of adc #2 * versioning * formatting * rx: moved creating fpath (if it doesnt exist) from setting file path to at the start of acquisition when creating file. This is done here so that it does not fail if fwrite is disabled anyway. Also fixed it in documentation. Changed in documentation that the default for fwrite is disabled (#957) * added keepalive zmq socket option (after 60s of idle time, 10 probes every sec. Mainly because an issue at Max IV (#956) * Moench mess from developer (#953) * new moench data structure for offline processing * Dev/zmq stream all ipv6 adn remove rx_zmqip (#958) * enable ipv6 in zmq socket * removed rx_zmqip API and field in gui, changed client updaterxrzip to updateclientzmqip to have the rx_hostname ip if 0. * updated command line for rx_zmqip to give a warning. * Replaced 'depreciated' to 'deprecated' everywhere * switching from * to 0.0.0.0 works for rebinding zmq sockets * fixed help in command line for rx_zmqip * to 0.0.0.0 and removed cmd in python * remove publisher zmq socket ip also for moench post processing * fixed tests * publisher zmq ip macros to be reused * fixed a warning about narrowing conversion from size_t to int (#963) * fixed stop server not starting up with setup variables (#949) * m3: fixed stop server not starting up with setup variables * all servers except eiger fixed for virtual stop server to start up with setupDetector function called * virtual tests work * eiger: versions print neednt be in stop server * jungfrau: stop server (not virtual) also needs to read config file * ensuring master is setup for virtual and real servers * Dev/pyctbgui merge (#960) * added empty c extension * added rotation to the decoding * added color map, options and findex * minor * move checks to before acquisition * added pixel map based decoder * cleanup * no thread creation for single thread processing * added rotation and test to compare * allow high and low water mark for zmq (also buffer size) for fast readouts * removed roatation during decoding * added Transpose to image and invert Y False to invert it * retains the zoomed state after the first image of gui, catch and display exception if no detector connected * moved start frame to dockable widget, removed extra frame number label, moved current measurement also to dockable widget, hide frame plot entirely when showing patternviewer * first image dependin on which plot * remember settings of main window size and position, dockewidget if docked, its size and posisiotn as well, then update it next time the gui is opened * change in comment * using c decoder for moench 04 and matterhorn * catch exception from invalid image from decoder * clean up * update row and col when choosing image type, neeeded to show values * fix for previous PR * disable resetting colormap values keep the range selected for every new acquisition * fix typos + tested on virtual matterhorn * minor print * refactored Slow ADCs Tab * refactored DAC tab * refactored power supplies * refactored signals tab * refactored transceiver tab * fix typo * fix typo2 * remove commented code * delete commented code * delete commented code * delete commented signals code * remove commented code for transceiver tab * refactor adc tab * refactor Pattern Tab * Refactor transceivers tab (PR#5) (#118) * refactored transceiver tab * remove commented code for transceiver tab --------- Co-authored-by: Erik Frojdh <erik.frojdh@gmail.com> * refactor adc tab (PR#6) (#119) * refactor adc tab * refactored Plot and Acquisition Tabs * fix the regression issue * restructure project files * applying singleton and renaming tabs to services * working install using pip * applies singleton to tab classes and remove CI erros * added pyzmq and pillow * remove the singleton implementation and keep changes * fix merge errors in mainWindow * moved misplaced init file * rename service to tab * reorganize imports * iterate over tabs * reorder tabs * add slowadc to the list * saving changes (buggy) power supply ui not showing in the gui * split power supply tab * fixed tests * add hardcoded values to defines file * fix error * separate power supply * fix errors for powerSuppliesTab * split dacs * split slow adcs * split signals tab * added tests for bit_utils * add slowAdc class to defines * split transceiver ui file * split adc.ui * split pattern ui file * split plot and acquisition ui file * added basic test for parsing bit names * removed redundant code in read_alias_file * fix dacs ui position * testing for correct exception * cmd and args at split * group radio buttons * fix comments from PR#1 * show legend * added python version and dev requirements to setup.py * fix dac issue * moved _decoder into pkg * added inplace build * removed clear * fixed dependencies * make tests run without slsdet * updated name of action * define colcount * fixed loading of alias file * add yapf and ruff * apply formatting * fix E and F rules * add more ruff rules * change variable name * squashing gh debugging commits and add pre-commit * update label values to mv units * add hook for yapf * reconfigure yapf precommit hook * add format and check_format to makefile * change gh actions * update readme * added check_format * WIP * added linting in github action * updated readme] * add more control for color choice * remove useless file * fix un-updated line after refactoring Defines BIT0_31_MASK is not found in Defines.signals * visually improve the interface * fix last commit * add only selected plots for legend * add hide legend button * change hide legend to show legend checkbox show legend is checked by default * add support for saving in numpy * solve conversations * fix acq index offset * fix browse button in pattern error * fix other browse button errors * finish tests and add usage.md * remove buffer * add file,numpy-like interface and tests * remove useless .npy files * subscriptible npz files * remove useless files * remove repetetive tests * save changes * add mode r+, add with support,remove logging * remove offset of acqIndex between raw and numpy saving * fix only saving last frame * save signals of multiple devices * add comments and move condition for clearer code * fix bug when vieweing pattern file * iterate over enabled and plotted plots * add padestal substraction to transceiver and analog data * init pedestal frames to detector.frames * restore old exception * add pedestal substraction for digital signals * remove frames spinbox from plotTab * remove comments and use str instead of Path * avoid saving all frames * correct exception and log error's trace * add gui tests * add waveform test * add pedestal test * refactor by using fixtures * add tests for moench analog and pattern * add pytest-qt to dependencies * add save and load gui parameters * remove nohup file * fix old bug IndexError * save plot type * a * handle canceling load, loading matterhorn pedestal for moench * remove comparing .png files for pattern test * save plot type * red error on status bar when shape mismatch for loaded pedestal * fix makefile and docstrings * fix PRs conversation * move code into different function * fix wrong function names for power supply * removed old ctbgui * removed unnecessary files --------- Co-authored-by: Erik Frojdh <erik.frojdh@gmail.com> Co-authored-by: Braham Bechir <braham_b@pc11979.psi.ch> Co-authored-by: Bechir <bechir.braham@psi.ch> Co-authored-by: Bechir <bechir.brahem420@gmail.com> * Dev/xilinx mat update (#959) * put back code to obtain adc and dac device indexafter loading device tree and then create folder iio_device_links and create symbolic links there according to device indices found. ln -sf operation not permitted, so folder has to be deleted and created everytime. Also refactored definitions to have all the xilinx name or detector specific stuff out of programbyArm.c * uncommented waittransceiverreset at startup (should work now) and return of powering off chip at startup (error for transceiver alignment reset) * updated registerdefs from firmware * minor prints and updating names from registerdefs * waittransceiverreset has been fixed in firmware and removing warnign for that, transceiver alignment check for powering off chip is not done in fw (giving a warning and returning ok for now) * fixing ipchecksum (not done), removed startperiphery, allowing readout command to be allowed for xilinx when acquiring * dont build doc for Tobi Schluter from libzmq, which uses iso-8859-1 and the umlaut cause compilation to fail on some machines (#973) * 8.0.2 psi modules * missed the rx_zmqip implementations in detector.h and python bindings (#975) * rx_zmqip has been removed. Remove it also for pyctbgui (#979) * format * Dev/rx callbacks (#966) * changed rxr callback signatures to all include structs * removed datamodify call back as size can be changed in the original data call back now * bringing some parameters (set functions) to dataProcessor class for its callback (namely udpport, quad, fliprows, totalframes, jsonheader), resulting in also removing totalframes from 2 other function signatures * updated MultiReceiverApp to reflect the new callback signatures * Dev/reg bit change no validate (#970) - do not validate write reg, setbit and clearbit by default anymore - --validate will force validation on the bitmask or entire reg - remove return value for write reg (across server to client, but thankfully not in the Detector class) - extend validation into writereg, setbit and clearbit for Eiger (always special) - need to check python (TODO) - missed the rx_zmqip implementations in detector.h and python bindings * sleep implemented for command line, mainly for config files for firmware developers (#982) * change gain mode help from dynamicgain to dynamic (#988) * fixing python version. allowing versions to execute even if no detector connected or in shared memory (#990) * Jf: Electron collection mode (#983) * electron collection mode for jungfrau. also removing the config chip when using register command * collectionMode: HOLE/ELECTRON (enum) * Dev/m3 readout speed (#985) * added readoutspeed command to m3 (fullspeed - 10, half speed - 20, quarter speed - 40), removed reaodut pll, moved up system pll clock indices, leaving pll index in common altera code, default speed is half speed, allow only system_c0 to be set, the others can be obtained, same for clkphase, maxclkphaseshift, clkfreq. added to readoutspeedlist commands, updated help and updated tests * updated readoutspeedlist command * jf: timing info decoder (#987) * timing_info_decoder command with options swissfel (default) and shine. added to python, command line generation, autocomplete, tostring, tests. * updated jungfrau timing info decoder mask (#991) * minor. removed warning print at startup for empty eth udp to listen to (#992) * removed 'Caller/CALLER' from test names as there is only one command line now (#993) * formatting * Dev/g2 stop frame number (#980) * get/set next frame number in G2 (firmware only has set, no get) * firmware has issues: each stop keeps 2 frame header in fifo and the resetting frame number happens after that * removed the option to set burstmode to burst external or continuwous internal * needs to be revisited before 9.0.0 * formatting * fix the command help in the command help generator for Gotthard2 about nextframenumber (#994) * first draft at fixing nextframenumber properly with firmware (#995) * fixing nextframenumber properly with firmware * updated firmware to have getnextframenumber and fixed setnextframenumber to reset also the header fifo when stopping * fix tests for gotthard2 * Dev/g2 fix next frame number (#996) * binaries in * formatting * release notes * release notes * updating firmware dates * release notes * package release version and renaming server names * updated client versioning * updated moench fw release version * 900/proper free (#1002) * first draft of fixing the free function available within the class * removed class member function freeSharedmemory for both Detector and Module; made the free function freeSharedmemory accessible to python interface; setHostname if there is already a module in shm will recreate the Detector object while freeing shm completely and keeping detsize and intitialchecks (previous commit), sethostname called from DetectorClass in virtual command to have one point of entry (previous commit), testing Module class frees shared memory using free function * Detector class: added copy and move constructor and assignmentoperators due to explicit destructor (DetectorImpl fwd declared), DetectorImpl class: included ZmqSocket to remove destructor (should not be virtual in any case), Module class: removed explciit destructor to allow compiler generated constructor and operators * formatting * updated client version date * minor fix for readme autocomplete * setting detsize after hostname should throw also for single module for consistency (#999) * 900/autocomplete documentation (#1003) * fixed the gendoc to reflect the new parser, updated documentation to include info about autocomplete in the command line part, error in createing docs * fixed list deprecated, fixed command help (to show properly on a html, fixed other help warnings * minor indents * 900/g2 chip configure at startup (#1008) * g2: chip reconfigure variable not set when powering on at startup because readconfig is the one configuring the chip the first time to default chip settings * cleaning up code * 900/rm volatile (#1006) * Removing volatile and replacing with atomic to ensure atomicity * compiling header include issue * 900/jf firmware rollback (#1010) * jf: rolling back firmware required to v1.5 and 2.5, updated release notes, fixed a bug when updating server (when server name same as link name:throws with no message, pedestal mode check changed for the time being for loops to be 0xFF size * compensating for jf fw bug for pedestalmode where loops should be 16 bit, but is 8 bit in fw. to be fixed in next version * formatting * fixed python test simulator to kill previous servers * gui: hide 'complete image' and just show 'missing packets' when there are missing packets in that image form the receiver (#1013) * release notes update (#1015) * 900/detach pthreads not joining (#1017) * detach the pthreads that are not joining else memory leak * release notes * removed the clean up comment, also refactored the pthread join/detach for ctb 1g * 900/server malloc check (#1020) * usleep in communication to actually relay the err message of memory allocation to the client (weird but test for now), function in server to handle memory allcoation issues (updates mess, ret and sendsit to the client and returns prior from function implementatin, setting fnum in client for the speicific functions that send to detector each argument separtely, they need to remember the fnum else they throw with the incorrect fnum * server: every malloc must check if it succeeded, rearranging so that the free is clear as well (only in funcs so far) * formatting * fixed malloc checks in other places other than funcs.c * bug fix return from previous commit * pointer bug from previous commit * formatting * binaries in * 900/document json ctb file format (#1027) * docs receiver formats rewrite * added documentation for all the receiver files, updated release notes, udpated help in commands help for timing, fixed by throwing exception for aa dividy by 0 error caused by not freeing memory (detsize) when switching between 1d and 2d detectors, removed unnecessary 'recevier up' printout, fixed dbit list 64 bit mask error in master json file (was not 64 bit before), fixed bug in reading gotthard1 data (needs to be tested) * generating commands help and formatting, also fix help for trimen command line * added ctb frame format documentation, added some links to some commands, added documentation about adding expat-devel in installation for rhel8 gui, fixed some indentation issues that screwed up command line help documentation * added ctb frame format documentation * updated documentation about zeromq-devel for <8.0.0 versions * fixed typo in python for vb_pixbuf Jungfrau dac (#1030) * fixed cli documentation (#1037) * 900: legal gain values in jungfrau simulator (#1043) * legal gain values in jungfrau simulator * typo * release notes * 900/jungfrau temp control default enable (#1041) * jungfrau: enabling temp control by default at server startup * 900: fixed invalid arguments to slsmultireceiver (#1039) * wasnt showing error message for invalid arguments to slsmultireceiver * allow 0 arguments to act like an slsReceiver with start tcp port 1954 and just 1 receiver * 9.0.0: version from file to cmake and python (#1024) - renamed conda-recipe folder - added a check to see if build and install folder exists in build.sh (conda recipe) - created VERSION file that has '0.0.0'for developer but can be updated using update_version.py that takes in a version. The script checks for semantic versioning and updates VERSION file - VERSION file also copied along with py files to slsdet in python cmakelist and build_pylib.sh (for conda), also copied in root folder for installations (for no coding purpose) - init.py and setup.py reads this file to get the version (a bit differently to find the VERSION file) - VERSION file read into cmake to get the version and also added to compile definition. So RELEASE removed from versionAPI.h (using SLS_DET_VERSION compile definiton instead) and also removed updateRelease script. - conda getting project version from environment variable SLS_DET_VERSION that is set in build_pylib.sh prior. - added 3.13 python to conda build - anything related to ctb removed from release notes as users will always use developer - sets 9.0.0 to VERSION file by running update_version.py without an argument * formatting * finalized binaries * updated m3 fw version (#1046) * release notes * fix cmake (cannot find VERSION file) when using package as subfolder as cmake_source_dir is not same anymore, add troubleshooting doc for m3 regarding loose control board for waiting status in auto timing mode, fix m3 tests to test register write (previously was read only) (#1047) * 900: bumped pybind11 version and added setuptools on host (#1050) * bumped pybind11 version and added setuptools on host * updated pybind11 tarball to 2.13 and in cmakefile to get 2.13 frpm github, also updated documentation about pybind 2.13 * update release notes, doc * updating readme --------- Co-authored-by: Erik Fröjdh <erik.frojdh@gmail.com> * 900 cmake_source_dir (#1053) * when package used as subdirectory (cmake-subfolder-example) it fails when python is used because the cmake_source_dir is now the one above package. * changed cmake_current_list_dir to cmake_current_source_dir * removing the unnecessary VERSION file installed in the root directory (from PR #1020) * 900: pybind 2.13.6 and python 3.8 (#1054) * changed pybind 2.13.0 to 2.13.6, kept conda at min 2.13.0 * changed min python version from 3.6 to 3.8 * 900/docs (#1056) * minimum python is 3.8, so >= * removed ctb frame documentation. should be in internal wiki * updated release notes * updated releate date --------- Co-authored-by: Erik Fröjdh <erik.frojdh@gmail.com> Co-authored-by: froejdh_e <erik.frojdh@psi.ch> Co-authored-by: anberga <34126852+anberga@users.noreply.github.com> Co-authored-by: Filip Leonarski <filip.leonarski@psi.ch> Co-authored-by: Z.H. Li <zhenghenge@gmail.com> Co-authored-by: Martin Brückner <martin.brueckner@psi.ch> Co-authored-by: Braham Bechir <braham_b@pc11979.psi.ch> Co-authored-by: Bechir <bechir.braham@psi.ch> Co-authored-by: Bechir <bechir.brahem420@gmail.com>
This commit is contained in:
parent
4880f87791
commit
0aeb7e4417
2
.github/workflows/cmake.yml
vendored
2
.github/workflows/cmake.yml
vendored
@ -17,7 +17,7 @@ jobs:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: awalsh128/cache-apt-pkgs-action@latest
|
||||
with:
|
||||
packages: libzmq3-dev libhdf5-dev qtbase5-dev qt5-qmake libqt5svg5-dev
|
||||
packages: libhdf5-dev qtbase5-dev qt5-qmake libqt5svg5-dev
|
||||
version: 1.0
|
||||
|
||||
- name: Configure CMake
|
||||
|
1
CMakeFiles/cmake.check_cache
Normal file
1
CMakeFiles/cmake.check_cache
Normal file
@ -0,0 +1 @@
|
||||
# This file is generated by cmake for dependency checking of the CMakeCache.txt file
|
@ -2,7 +2,15 @@
|
||||
# Copyright (C) 2021 Contributors to the SLS Detector Package
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
project(slsDetectorPackage)
|
||||
set(PROJECT_VERSION 8.0.2)
|
||||
|
||||
# Read VERSION file into project version
|
||||
set(VERSION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/VERSION")
|
||||
file(READ "${VERSION_FILE}" VERSION_CONTENT)
|
||||
string(STRIP "${VERSION_CONTENT}" PROJECT_VERSION_STRING)
|
||||
set(PROJECT_VERSION ${PROJECT_VERSION_STRING})
|
||||
|
||||
# Pass it to the compiler
|
||||
add_compile_definitions(SLS_DET_VERSION="${PROJECT_VERSION}")
|
||||
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG")
|
||||
|
||||
@ -148,7 +156,6 @@ set(SLS_INTERNAL_QWT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/libs/qwt-6.1.5)
|
||||
set(ClangFormat_EXCLUDE_PATTERNS "build/"
|
||||
"libs/"
|
||||
"slsDetectorCalibration/"
|
||||
"ctbGui/"
|
||||
"manual/"
|
||||
"python/"
|
||||
"sample/"
|
||||
@ -232,6 +239,8 @@ if (NOT TARGET slsProjectCSettings)
|
||||
-Wredundant-decls
|
||||
-Wdouble-promotion
|
||||
-Werror=return-type
|
||||
-Wno-format-overflow
|
||||
-Wno-format-truncation
|
||||
)
|
||||
sls_disable_c_warning("-Wstringop-truncation")
|
||||
endif()
|
||||
@ -244,6 +253,7 @@ if(SLS_USE_SANITIZER)
|
||||
# target_link_libraries(slsProjectOptions INTERFACE -fsanitize=thread)
|
||||
endif()
|
||||
|
||||
|
||||
if(SLS_TUNE_LOCAL)
|
||||
target_compile_options(slsProjectOptions INTERFACE -mtune=native -march=native)
|
||||
endif()
|
||||
@ -294,19 +304,20 @@ if (SLS_USE_INTEGRATION_TESTS)
|
||||
endif (SLS_USE_INTEGRATION_TESTS)
|
||||
|
||||
if (SLS_USE_PYTHON)
|
||||
find_package (Python 3.6 COMPONENTS Interpreter Development)
|
||||
find_package (Python 3.8 COMPONENTS Interpreter Development)
|
||||
if(SLS_FETCH_PYBIND11_FROM_GITHUB)
|
||||
FetchContent_Declare(
|
||||
pybind11
|
||||
GIT_REPOSITORY https://github.com/pybind/pybind11
|
||||
GIT_TAG v2.11.0
|
||||
GIT_TAG v2.13.6
|
||||
)
|
||||
|
||||
else()
|
||||
# https://github.com/pybind/pybind11/releases
|
||||
FetchContent_Declare(
|
||||
pybind11
|
||||
URL ${CMAKE_SOURCE_DIR}/libs/pybind11/v2.11.0.tar.gz
|
||||
URL_HASH MD5=90c4946e87c64d8d8fc0ae4edf35d780
|
||||
URL ${CMAKE_CURRENT_SOURCE_DIR}/libs/pybind11/v2.13.6.tar.gz
|
||||
URL_HASH MD5=a04dead9c83edae6d84e2e343da7feeb
|
||||
)
|
||||
endif()
|
||||
FetchContent_MakeAvailable(pybind11)
|
||||
@ -315,7 +326,7 @@ if (SLS_USE_PYTHON)
|
||||
endif(SLS_USE_PYTHON)
|
||||
|
||||
if (SLS_USE_CTBGUI)
|
||||
add_subdirectory(ctbGui)
|
||||
add_subdirectory(pyctbgui)
|
||||
endif(SLS_USE_CTBGUI)
|
||||
|
||||
configure_file( .clang-tidy
|
||||
@ -344,4 +355,4 @@ if(SLS_MASTER_PROJECT)
|
||||
set(CMAKE_INSTALL_DIR "share/cmake/${PROJECT_NAME}")
|
||||
set(PROJECT_LIBRARIES slsSupportShared slsDetectorShared slsReceiverShared)
|
||||
include(cmake/package_config.cmake)
|
||||
endif()
|
||||
endif()
|
124
README.md
124
README.md
@ -2,7 +2,11 @@
|
||||
Before building from source make sure that you have the [software wiki](https://slsdetectorgroup.github.io/devdoc/dependencies.html) installed. If installing using conda, conda will manage the dependencies. Avoid also installing packages with pip.
|
||||
|
||||
## Documentaion
|
||||
Detailed documentation can be found in the [software wiki](https://slsdetectorgroup.github.io/devdoc/index.html) and on the [official site](https://www.psi.ch/en/detectors/software).
|
||||
Detailed documentation including installation can be found in the [software wiki](https://slsdetectorgroup.github.io/devdoc/index.html).
|
||||
|
||||
Different releases can be found on the [official site](https://www.psi.ch/en/lxn/software-releases).
|
||||
|
||||
Firmware compatiblity can be found in [firmware page](https://github.com/slsdetectorgroup/slsDetectorFirmware)
|
||||
|
||||
## Installation
|
||||
|
||||
@ -42,33 +46,20 @@ conda search slsdet
|
||||
conda search slsdetgui
|
||||
```
|
||||
|
||||
### 2. Build from source
|
||||
## 2. Build from source
|
||||
|
||||
##### 2.1 Download Source Code from github
|
||||
### 2.1 Download Source Code from github
|
||||
```
|
||||
git clone https://github.com/slsdetectorgroup/slsDetectorPackage.git --branch 7.0.0
|
||||
```
|
||||
|
||||
**Pybind for Python**<br>
|
||||
* **v7.0.0+**:
|
||||
pybind11 packaged into 'libs/pybind'. No longer a submodule. No need for "recursive" or "submodule update".
|
||||
|
||||
* **Older versions**:
|
||||
pybind11 is a submodule. Must be cloned using "recursive" and updated when switching between versions using the following commands.
|
||||
|
||||
```
|
||||
# clone using recursive to get pybind11 submodule
|
||||
git clone --recursive https://github.com/slsdetectorgroup/slsDetectorPackage.git
|
||||
|
||||
# update submodule when switching between releases
|
||||
cd slsDetectorPackage
|
||||
git submodule update --init
|
||||
```
|
||||
|
||||
##### 2.2 Build from source
|
||||
> **Note:** For v6.x.x of slsDetectorPackage and older, refer [pybind11 notes on cloning](#Pybind-and-Zeromq).
|
||||
|
||||
|
||||
###### Build using CMake
|
||||
### 2.2 Build from source
|
||||
|
||||
|
||||
### Build using CMake
|
||||
|
||||
```
|
||||
# outside slsDetecorPackage folder
|
||||
@ -94,26 +85,28 @@ Instead of the cmake command, one can use ccmake to get a list of options to con
|
||||
ccmake ..
|
||||
|
||||
# choose the options
|
||||
# first press [c] - configure
|
||||
# first press [c] - configure (unil you see [g])
|
||||
# then press [g] - generate
|
||||
```
|
||||
|
||||
|Example cmake options|Comment|
|
||||
|---|---|
|
||||
| -DSLS_USE_PYTHON=ON | Python |
|
||||
| -DPython_FIND_VIRTUALENV=ONLY | Python from only the conda environment |
|
||||
| -DZeroMQ_HINT=/usr/lib64 | Use system zmq instead |
|
||||
| -DPython_FIND_VIRTUALENV=ONLY | Python from only the conda env |
|
||||
| -DSLS_USE_GUI=ON | GUI |
|
||||
| -DSLS_USE_HDF5=ON | HDF5 |
|
||||
| -DSLS_USE_SIMULATOR=ON | Simulator |
|
||||
|
||||
> **Note:** For v7.x.x of slsDetectorPackage and older, refer [zeromq notes for cmake option to hint library location](#Pybind-and-Zeromq).
|
||||
|
||||
###### Build using in-built cmk.sh script
|
||||
### Build using in-built cmk.sh script
|
||||
|
||||
```
|
||||
The binaries are generated in slsDetectorPackage/build/bin directory.
|
||||
|
||||
Usage: ./cmk.sh [-b] [-c] [-d <HDF5 directory>] [e] [g] [-h] [i] [-j <Number of threads>]
|
||||
[-k <CMake command>] [-l <Install directory>] [m] [n] [-p] [-q <Zmq hint directory>]
|
||||
[r] [s] [t] [u] [z]
|
||||
Usage: $0 [-b] [-c] [-d <HDF5 directory>] [-e] [-g] [-h] [-i]
|
||||
[-j <Number of threads>] [-k <CMake command>] [-l <Install directory>]
|
||||
[-m] [-n] [-p] [-r] [-s] [-t] [-u] [-z]
|
||||
-[no option]: only make
|
||||
-b: Builds/Rebuilds CMake files normal mode
|
||||
-c: Clean
|
||||
@ -128,14 +121,13 @@ Usage: ./cmk.sh [-b] [-c] [-d <HDF5 directory>] [e] [g] [-h] [i] [-j <Number of
|
||||
-m: Manuals
|
||||
-n: Manuals without compiling doxygen (only rst)
|
||||
-p: Builds/Rebuilds Python API
|
||||
-q: Zmq hint directory
|
||||
-r: Build/Rebuilds only receiver
|
||||
-s: Simulator
|
||||
-t: Build/Rebuilds only text client
|
||||
-u: Chip Test Gui
|
||||
-z: Moench zmq processor
|
||||
|
||||
|
||||
|
||||
# display all options
|
||||
./cmk.sh -?
|
||||
|
||||
@ -145,11 +137,14 @@ Usage: ./cmk.sh [-b] [-c] [-d <HDF5 directory>] [e] [g] [-h] [i] [-j <Number of
|
||||
# new build, python and compile in parallel:
|
||||
./cmk.sh -cbpj5
|
||||
|
||||
#To use the system zmq (/usr/lib64) instead
|
||||
./cmk.sh -cbj5 -q /usr/lib64
|
||||
#For rebuilding only certain sections
|
||||
./cmk.sh -tg #only text client and gui
|
||||
./cmk.sh -r #only receiver
|
||||
```
|
||||
|
||||
###### Build on old distributions
|
||||
> **Note:** For v7.x.x of slsDetectorPackage and older, refer [zeromq notes for cmk script option to hint library location](#Pybind-and-Zeromq).
|
||||
|
||||
### Build on old distributions
|
||||
|
||||
If your linux distribution doesn't come with a C++11 compiler (gcc>4.8) then
|
||||
it's possible to install a newer gcc using conda and build the slsDetectorPackage
|
||||
@ -166,7 +161,10 @@ cmake ../slsDetectorPackage -DCMAKE_PREFIX_PATH=$CONDA_PREFIX
|
||||
make -j12
|
||||
```
|
||||
|
||||
###### Build slsDetectorGui (Qt5)
|
||||
> **Note:** For v7.x.x of slsDetectorPackage and older, refer [zeromq notes for dependencies for conda](#Pybind-and-Zeromq).
|
||||
|
||||
|
||||
### Build slsDetectorGui (Qt5)
|
||||
|
||||
1. Using pre-built binary on conda
|
||||
```
|
||||
@ -180,7 +178,14 @@ yum install qt5-qtbase-devel.x86_64
|
||||
yum install qt5-qtsvg-devel.x86_64
|
||||
```
|
||||
|
||||
3. Using conda
|
||||
3. Using system installation on RHEL8
|
||||
```
|
||||
yum install qt5-qtbase-devel.x86_64
|
||||
yum install qt5-qtsvg-devel.x86_64
|
||||
yum install expat-devel.x86_64
|
||||
```
|
||||
|
||||
4. Using conda
|
||||
```
|
||||
#Add channels for dependencies and our library
|
||||
conda config --add channels conda-forge
|
||||
@ -208,13 +213,15 @@ cd slsDetectorPackage
|
||||
./cmk.sh -cbgj9
|
||||
```
|
||||
|
||||
###### Build documentation from package
|
||||
> **Note:** For v7.x.x of slsDetectorPackage and older, refer [zeromq notes for dependencies for conda](#Pybind-and-Zeromq).
|
||||
|
||||
### Build documentation from package
|
||||
The documentation for the slsDetectorPackage is build using a combination
|
||||
of Doxygen, Sphinx and Breathe. The easiest way to install the dependencies
|
||||
is to use conda
|
||||
|
||||
```
|
||||
conda create -n myenv python sphinx_rtd_theme breathe
|
||||
conda create -n myenv python=3.12 sphinx sphinx_rtd_theme breathe doxygen numpy
|
||||
```
|
||||
|
||||
```
|
||||
@ -228,6 +235,47 @@ make rst # rst only, saves time in case the API did not change
|
||||
```
|
||||
|
||||
|
||||
|
||||
## Pybind and Zeromq
|
||||
|
||||
### Pybind11 for Python
|
||||
**v8.0.0+**:
|
||||
pybind11 is built
|
||||
* by default from tar file in repo (libs/pybind/v2.1x.0.tar.gz)
|
||||
* or use advanced option SLS_FETCH_PYBIND11_FROM_GITHUB [link].
|
||||
* v9.0.0+: pybind11 (v2.13.6)
|
||||
* v8.x.x : pybind11 (v2.11.0)
|
||||
|
||||
**v7.x.x**:
|
||||
pybind11 packaged into ‘libs/pybind’. No longer a submodule. No need for “recursive” or “submodule update”.
|
||||
|
||||
**Older versions**:
|
||||
pybind11 is a submodule. Must be cloned using “recursive” and updated when switching between versions using the following commands.
|
||||
|
||||
```
|
||||
# Note: Only for v6.x.x versions and older
|
||||
|
||||
# clone using recursive to get pybind11 submodule
|
||||
git clone --recursive https://github.com/slsdetectorgroup/slsDetectorPackage.git
|
||||
|
||||
# update submodule when switching between releases
|
||||
cd slsDetectorPackage
|
||||
git submodule update --init
|
||||
```
|
||||
|
||||
### Zeromq
|
||||
**v8.0.0+**:
|
||||
zeromq (v4.3.4) is built
|
||||
* by default from tar file in repo (libs/libzmq/libzmq-4.3.4.tar.gz)
|
||||
* or use advanced option SLS_FETCH_ZMQ_FROM_GITHUB [link].
|
||||
|
||||
**v7.x.x and older**:
|
||||
zeromq-devel must be installed and one can hint its location using
|
||||
* cmake option:’-DZeroMQ_HINT=/usr/lib64’ or
|
||||
* option ‘-q’ in cmk.sh script: : ./cmk.sh -cbj5 -q /usr/lib64
|
||||
* ‘zeromq’ dependency added when installing using conda
|
||||
|
||||
|
||||
## Support
|
||||
dhanya.thattil@psi.ch
|
||||
erik.frojdh@psi.ch
|
||||
erik.frojdh@psi.ch
|
347
RELEASE.txt
347
RELEASE.txt
@ -1,123 +1,284 @@
|
||||
SLS Detector Package Bug Fix Release 8.0.2 released on 18.09.2024
|
||||
=================================================================
|
||||
SLS Detector Package Major Release 9.0.0 released on 25.11.2024
|
||||
===============================================================
|
||||
|
||||
This document describes the differences between v8.0.2 and v8.0.1
|
||||
This document describes the differences between v9.0.0 and v8.0.2
|
||||
|
||||
|
||||
|
||||
CONTENTS
|
||||
--------
|
||||
1 Resolved Issues
|
||||
2 On-board Detector Server Compatibility
|
||||
3 Firmware Requirements
|
||||
4 Kernel Requirements
|
||||
5 Download, Documentation & Support
|
||||
1 Compilation Changes
|
||||
2 New or Changed Features
|
||||
2.1 Breaking API
|
||||
2.2 Resolved or Changed Features
|
||||
2.3 New Features
|
||||
3 On-board Detector Server Compatibility
|
||||
4 Firmware Requirements
|
||||
5 Kernel Requirements
|
||||
6 Download, Documentation & Support
|
||||
|
||||
|
||||
|
||||
|
||||
1 Resolved Issues
|
||||
=================
|
||||
2 Compilation Changes
|
||||
=====================
|
||||
|
||||
|
||||
Compilation
|
||||
-----------
|
||||
* Python version
|
||||
Minimum python version is changed from 3.6 to 3.8
|
||||
|
||||
|
||||
* Rapidjson compilation with gcc 14
|
||||
Fixed a compile issue with gcc 14. Same fix in later commits to rapidjson.
|
||||
* Pybind11 version
|
||||
In-built version and the one picked up from github
|
||||
updated from v2.11.0 to v2.13.6
|
||||
|
||||
|
||||
Client
|
||||
------
|
||||
* Python lib versioning
|
||||
slsdet.__version__ now returns the package release version.
|
||||
|
||||
|
||||
* getenv("HOME") returning nullptr
|
||||
When this happens, especially for systemd, it segfaults. Protection
|
||||
provided by using empty string in this case.
|
||||
* Python version in conda build
|
||||
Added python 3.13 also to conda build
|
||||
|
||||
|
||||
* [Mythen3] Bad channel list for multi module
|
||||
Exception thrown when loading multi module bad channel file skipping
|
||||
modules in between. Fixed.
|
||||
|
||||
2 New, Changed or Resolved Features
|
||||
=====================================
|
||||
|
||||
|
||||
* [Gotthard2] Stopping a blocking acquisition
|
||||
A check added in v8.0.0 to catch slaves that might be in waiting forever
|
||||
also catches Gotthard2 25um slaves that might only be in waiting
|
||||
temporarily. This is fixed with a 50ms sleep before checking again
|
||||
(upto 1s).
|
||||
|
||||
|
||||
* [Moench] Acquire finished processing call back
|
||||
New executable 'sls_detector_acquire_zmq' added to listen to all zmq
|
||||
packets from post processor or external process to signal end of post
|
||||
processing. Post processor refactoring of zmq socket creation added.
|
||||
|
||||
|
||||
Gui / Callback
|
||||
--------------
|
||||
|
||||
|
||||
* [Gotthard2] Stopping a blocking acquisition
|
||||
From the previous issue, call back for acquisition finished status gives
|
||||
error for inconsistent states. Again, a check every 50ms upto 1s is
|
||||
added to let go the temporarily waiting slave.
|
||||
|
||||
|
||||
* Different file paths
|
||||
Fixes file path resetting when different modules have different fpath set.
|
||||
2.1 Breaking API
|
||||
==================
|
||||
|
||||
|
||||
Receiver
|
||||
--------
|
||||
|
||||
|
||||
* HDF5 fill value
|
||||
Fix the fill value to accomodate all datatypes.
|
||||
* Receiver callbacks
|
||||
Brought much more metadata to receiver callbacks to construct the image.
|
||||
Update MultiReceiverApp to reflect this change.
|
||||
|
||||
|
||||
Firmware
|
||||
|
||||
* File path
|
||||
At start of acquisition or at rx_start command, the file path is only
|
||||
then verified if it exists and created if it does not.
|
||||
|
||||
|
||||
Client
|
||||
------
|
||||
|
||||
|
||||
* Removed receiver/publisher ZMQ IP
|
||||
Command line: rx_zmqip gives a warning and does nothing
|
||||
Python : rx_zmqip removed
|
||||
C++ API: get/setRxZmqIP removed
|
||||
|
||||
Publisher zmq IP set to '0.0.0.0' or to listen on all interfaces.
|
||||
The publisher will determine which interface to stream out from based on
|
||||
the network route to the subscriber IP. Hence, receiver zmq IP is not
|
||||
required.
|
||||
|
||||
|
||||
* Write register, Set or Clear bit
|
||||
Validation for this advanced feature has been removed by default.
|
||||
One can force validation by using --validate in the command line or by
|
||||
setting the validate option in the API.
|
||||
|
||||
|
||||
ZMQ
|
||||
---
|
||||
|
||||
|
||||
* Publisher socket constructor does not take an IP anymore.
|
||||
The details are above under 'Removed receiver/publisher ZMQ IP'.
|
||||
|
||||
|
||||
GUI/ Client Callback
|
||||
--------------------
|
||||
|
||||
|
||||
* completeImage member in detectorData attribute now returns false only
|
||||
if any the sub images (from different udp ports) have completeImage
|
||||
set to false in the JSON header. This is set if therea are any missing
|
||||
packets for that udp port on slsReceiver/slsMultiReceiver.
|
||||
|
||||
The different subimages are anyway not synchronized. This errs when
|
||||
there are different missing images across multiple UDP ports.
|
||||
|
||||
The Gui does not show "complete image" in the status bar anymore.
|
||||
If any of the udp ports have missing packets for that current disaplayed
|
||||
image, then the "missing packets" will show in red in the status bar.
|
||||
|
||||
|
||||
Detector Server
|
||||
---------------
|
||||
|
||||
|
||||
* [Mythen3] Only run clock can be set
|
||||
Clock 0 is now the run clock and the only one that can be set.
|
||||
The others are be read only.
|
||||
This affects the following commands:
|
||||
Command line or python API: clkdiv, clkfreq, clkphase, maxclkphaseshift
|
||||
C++ API: get/setClockDivider, getClockFrequency, get/setClockPhase,
|
||||
getMaxClockPhaseShift
|
||||
|
||||
|
||||
* [Jungfrau] Temperature Control
|
||||
Temperature control is enabled by default at on-board detector server
|
||||
startup.
|
||||
As before, the default temperature threshold is 65°C and crossing this
|
||||
value will set a temperature event.
|
||||
|
||||
|
||||
|
||||
2.2 Resolved or Changed Features
|
||||
================================
|
||||
|
||||
|
||||
Compilation
|
||||
-----------
|
||||
|
||||
|
||||
* cmake_source_dir
|
||||
Fixed compilation error when using python and adding the slsDetectorPackage
|
||||
as a subfolder due to cmake source directory changing.
|
||||
|
||||
|
||||
Client
|
||||
------
|
||||
|
||||
|
||||
* Command line Code Generation
|
||||
The command line parsing code is now generated from a yaml file. This is
|
||||
transparent to the user.
|
||||
|
||||
|
||||
* Clearer error message about freeing shared memory.
|
||||
|
||||
|
||||
Detector Server
|
||||
---------------
|
||||
|
||||
|
||||
* [Gotthard2] Chip reconfiguration
|
||||
|
||||
- Powering off/on the chip will now switch off chip configuration
|
||||
property/ configure the chip every time.
|
||||
|
||||
- Switching off high voltage from a non zero value will now wait
|
||||
10s to return for safety reasons.
|
||||
|
||||
- Powering off the chip requires high voltage to have been
|
||||
switched off prior.
|
||||
|
||||
- Acquisition requires chip to have been configured prior.
|
||||
|
||||
|
||||
* [Gotthard2] Burst mode options restricted
|
||||
Burst mode external and continuous mode internal are not allowed to be set
|
||||
anymore as they are anyway not implemented.
|
||||
|
||||
|
||||
Receiver
|
||||
--------
|
||||
|
||||
|
||||
* [Moench] Overflow with exptime of 0
|
||||
Fixed overflow when subtracting 1 clock cycle from exptime.
|
||||
* [Gotthard I] fixed header stripping fixing segfault.
|
||||
|
||||
|
||||
On-board Detector Server
|
||||
------------------------
|
||||
* Error or help message for invalid arguments to slsMultiReceiver.
|
||||
|
||||
|
||||
* [Moench] Few changes in Server:
|
||||
- Max shifts of adc clock changed from 240 to 200.
|
||||
|
||||
- Fixed overflow when subtracting 2 clock cycles from exptime of 0ms.
|
||||
|
||||
- Default readout speed to half speed from quarter.
|
||||
|
||||
- Change default ADC phase to 150 for full readout speed.
|
||||
|
||||
- Change default vipre_cds dac from 800 to 1280.
|
||||
Simulator
|
||||
---------
|
||||
|
||||
|
||||
* [Mythen3] Change Clk divider from 10 (100MHz) to 20 (50MHz) at startup.
|
||||
* Refactored stop server to have better start up.
|
||||
|
||||
|
||||
* [Jungfrau] Fix for HW v1.0 boards for unreliable ADC 2
|
||||
Issues sometimes seen on some HW v 1.0 boards are fixed with phase
|
||||
relationship of 120 degrees. HW v2.0 boards are not affected.
|
||||
* Fixed possible memory leak when taking non blocking acquisitions.
|
||||
|
||||
|
||||
* [Jungfrau] Valid gain values in data sent out. Previously, 2 was also sent out.
|
||||
|
||||
|
||||
ZMQ
|
||||
---
|
||||
|
||||
|
||||
* Publiser socket constructor
|
||||
|
||||
- enables keep alive socket options to send heartbeat messages to prevent
|
||||
discarded TCP flows if there is no packet for a longer period.
|
||||
|
||||
- enables IPv6 interfaces
|
||||
|
||||
* Prints specific error for ENOENT (endpoint does not exist)
|
||||
|
||||
|
||||
|
||||
2.3 New Features
|
||||
================
|
||||
|
||||
|
||||
Client
|
||||
------
|
||||
|
||||
|
||||
* Auto completion
|
||||
bash_autocomplete.sh or zsh_autocomplete.sh must be sourced from the
|
||||
main package folder to enable auto completion of commands and arguments
|
||||
for the command line on that shell.
|
||||
|
||||
|
||||
* sls_detector
|
||||
New executable that can be used instead of 'sls_detector_get' and
|
||||
'sls_detector_put' for most commands. It will infer from the number of
|
||||
arguments, which executable (sls_detector_put or sls_detector_get) to use.
|
||||
For the rare commands that cannot be inferred from the number of arguments,
|
||||
it will complain accordingly.
|
||||
|
||||
|
||||
* [Jungfrau] Timing Info Decoder (Advanced configuration)
|
||||
Command line or python API: timing_info_decoder
|
||||
C++ API: get/setTimingInfoDecoder. Options: SWISSFEL (Default), SHINE
|
||||
|
||||
|
||||
* [Jungfrau] Collection Mode (Advanced configuration)
|
||||
Command line or python API: collectionmode
|
||||
C++ API: get/setCollectionMode. Options: ELECTRON, HOLE (Default)
|
||||
If chip v1.1, also configures the chip afterwards.
|
||||
|
||||
|
||||
* [Gotthard2] Next frame number
|
||||
'Stop' in G2 25um is not synchronous and hence might trigger an extra set
|
||||
of frames in the slave module, resulting in the next acquiistion starting
|
||||
with inconsistent frame numbers between master and slave. Solved by
|
||||
setting next frame number to the larger value (max + 1) after a stop command.
|
||||
Requires a firmware update.
|
||||
|
||||
Documentation
|
||||
-------------
|
||||
Command line or python API: nextframenumber
|
||||
C++ API: get/setNextFrameNumber
|
||||
Can set/get the starting frame number for the next acquistion.
|
||||
|
||||
|
||||
* Updated troubleshooting documentaion to check links and disable firewall
|
||||
* [Mythen3] Readout speed
|
||||
Command line, python API: readoutspeed. Options: full_speed (10MHz),
|
||||
half_speed (20MHz, default), quarter_speed (40MHz)
|
||||
C++ API: get/setReadoutSpeed
|
||||
Also affect:
|
||||
Command line, python API: readoutspeedlist
|
||||
C++ API: getReadoutSpeedList
|
||||
|
||||
|
||||
* Excluded non UTF-8 encoded libzmq documents due to machine dependent
|
||||
compilation issues.
|
||||
* Sleep
|
||||
Command line, python/ C++ API: sleep
|
||||
Client sleeps for required time. Advanced command mainly for firmware
|
||||
developers to use in config files.
|
||||
|
||||
|
||||
* Xilinx Chip Test Board added
|
||||
|
||||
|
||||
|
||||
@ -125,20 +286,24 @@ This document describes the differences between v8.0.2 and v8.0.1
|
||||
==========================================
|
||||
|
||||
|
||||
Eiger 8.0.0
|
||||
Jungfrau 8.0.2
|
||||
Mythen3 8.0.2
|
||||
Gotthard2 8.0.0
|
||||
Gotthard 8.0.0
|
||||
Moench 8.0.2
|
||||
Ctb 8.0.0
|
||||
|
||||
Eiger 9.0.0
|
||||
Jungfrau 9.0.0
|
||||
Mythen3 9.0.0
|
||||
Gotthard2 9.0.0
|
||||
Gotthard 9.0.0
|
||||
Moench 9.0.0
|
||||
|
||||
|
||||
On-board Detector Server Upgrade
|
||||
--------------------------------
|
||||
|
||||
From v6.1.0 (without tftp):
|
||||
Using command 'updatedetectorserver'
|
||||
update only on-board detector server
|
||||
Using command 'updatedetectorserver'
|
||||
|
||||
|
||||
udpate both on-board detector server and firmware simultaneously
|
||||
Using command 'update'
|
||||
|
||||
Instructions available at
|
||||
https://slsdetectorgroup.github.io/devdoc/serverupgrade.html
|
||||
@ -155,18 +320,15 @@ This document describes the differences between v8.0.2 and v8.0.1
|
||||
Jungfrau 20.09.2023 (v1.5, HW v1.0) (updated in 8.0.0)
|
||||
21.09.2023 (v2.5, HW v2.0) (updated in 8.0.0)
|
||||
|
||||
Mythen3 24.01.2023 (v1.4) (updated in 7.0.0)
|
||||
Mythen3 13.11.2024 (v2.0) (updated in 9.0.0)
|
||||
|
||||
Gotthard2 23.11.2022 (v0.3) (updated in 7.0.0)
|
||||
Gotthard2 03.10.2024 (v1.0) (updated in 9.0.0)
|
||||
|
||||
Moench 26.10.2023 (v2.0) (updated in 8.0.2)
|
||||
|
||||
Gotthard 08.02.2018 (50um and 25um Master)
|
||||
09.02.2018 (25 um Slave)
|
||||
|
||||
Moench 26.10.2023 (v0.3.2) (updated in 8.0.2,
|
||||
under development)
|
||||
|
||||
Ctb 28.08.2023 (v1.2) (updated in 8.0.0)
|
||||
|
||||
|
||||
Detector Upgrade
|
||||
----------------
|
||||
@ -178,16 +340,15 @@ This document describes the differences between v8.0.2 and v8.0.1
|
||||
Mythen3 via command <.rbf>
|
||||
Gotthard2 via command <.rbf>
|
||||
Moench via command <.pof>
|
||||
Ctb via command <.pof>
|
||||
|
||||
Gotthard cannot be upgraded remotely
|
||||
|
||||
Except Eiger,
|
||||
upgrade
|
||||
using command 'programfpga' or
|
||||
Using command 'programfpga' or
|
||||
|
||||
udpate both server and firmware simultaneously
|
||||
using command 'update'
|
||||
udpate both on-board detector server and firmware simultaneously
|
||||
Using command 'update'
|
||||
|
||||
|
||||
Instructions available at
|
||||
|
1
bash_autocomplete.sh
Symbolic link
1
bash_autocomplete.sh
Symbolic link
@ -0,0 +1 @@
|
||||
slsDetectorSoftware/generator/autocomplete/bash_autocomplete.sh
|
@ -1,6 +0,0 @@
|
||||
# SPDX-License-Identifier: LGPL-3.0-or-other
|
||||
# Copyright (C) 2021 Contributors to the SLS Detector Package
|
||||
|
||||
echo "|<-------- starting python build"
|
||||
cd python
|
||||
${PYTHON} setup.py install
|
@ -1,8 +1,12 @@
|
||||
# SPDX-License-Identifier: LGPL-3.0-or-other
|
||||
# Copyright (C) 2021 Contributors to the SLS Detector Package
|
||||
|
||||
mkdir build
|
||||
mkdir install
|
||||
if [ ! -d "build" ]; then
|
||||
mkdir build
|
||||
fi
|
||||
if [ ! -d "install" ]; then
|
||||
mkdir install
|
||||
fi
|
||||
cd build
|
||||
cmake .. \
|
||||
-DCMAKE_PREFIX_PATH=$CONDA_PREFIX \
|
14
conda-recipe/build_pylib.sh
Executable file
14
conda-recipe/build_pylib.sh
Executable file
@ -0,0 +1,14 @@
|
||||
# SPDX-License-Identifier: LGPL-3.0-or-other
|
||||
# Copyright (C) 2021 Contributors to the SLS Detector Package
|
||||
|
||||
echo "|<-------- starting python build"
|
||||
|
||||
cd python
|
||||
|
||||
# copy VERSION into slsdet for installation
|
||||
cp ../VERSION slsdet/VERSION
|
||||
|
||||
# to be used to get project version in meta.yaml
|
||||
export SLS_DET_VERSION=$(cat python/slsdet/VERSION)
|
||||
|
||||
${PYTHON} setup.py install
|
@ -4,4 +4,5 @@ python:
|
||||
- 3.10
|
||||
- 3.11
|
||||
- 3.12
|
||||
|
||||
- 3.13
|
||||
|
@ -1,15 +1,19 @@
|
||||
|
||||
{% set version = environ.get('SLS_DET_VERSION', '0.0.0') %}
|
||||
|
||||
|
||||
package:
|
||||
name: sls_detector_software
|
||||
version: {{ environ.get('GIT_DESCRIBE_TAG', '') }}
|
||||
version: "{{ version }}"
|
||||
|
||||
|
||||
source:
|
||||
- path: ..
|
||||
path: ..
|
||||
|
||||
build:
|
||||
number: 0
|
||||
binary_relocation: True
|
||||
rpaths:
|
||||
rpaths:
|
||||
- lib/
|
||||
|
||||
requirements:
|
||||
@ -61,13 +65,11 @@ outputs:
|
||||
- libstdcxx-ng
|
||||
- libgcc-ng
|
||||
|
||||
|
||||
run:
|
||||
- libstdcxx-ng
|
||||
- libgcc-ng
|
||||
|
||||
- name: slsdet
|
||||
|
||||
script: build_pylib.sh
|
||||
|
||||
requirements:
|
||||
@ -77,12 +79,13 @@ outputs:
|
||||
- {{compiler('cxx')}}
|
||||
- {{ pin_subpackage('slsdetlib', exact=True) }}
|
||||
- setuptools
|
||||
- pybind11=2.11
|
||||
- pybind11=2.13
|
||||
|
||||
host:
|
||||
- python
|
||||
- {{ pin_subpackage('slsdetlib', exact=True) }}
|
||||
- pybind11=2.11
|
||||
- setuptools
|
||||
- pybind11=2.13
|
||||
|
||||
|
||||
run:
|
||||
@ -92,11 +95,11 @@ outputs:
|
||||
- numpy
|
||||
- {{ pin_subpackage('slsdetlib', exact=True) }}
|
||||
|
||||
|
||||
test:
|
||||
imports:
|
||||
- slsdet
|
||||
|
||||
|
||||
- name: slsdetgui
|
||||
script: copy_gui.sh
|
||||
requirements:
|
@ -1,90 +0,0 @@
|
||||
# SPDX-License-Identifier: LGPL-3.0-or-other
|
||||
# Copyright (C) 2021 Contributors to the SLS Detector Package
|
||||
|
||||
|
||||
find_package(ROOT CONFIG REQUIRED COMPONENTS Core Gui)
|
||||
find_package(TIFF REQUIRED)
|
||||
|
||||
target_include_directories(ROOT::Core INTERFACE "${ROOT_INCLUDE_DIRS}")
|
||||
add_library(ROOT::Flags_CXX IMPORTED INTERFACE)
|
||||
separate_arguments(ROOT_CXX_FLAGS)
|
||||
target_compile_options(ROOT::Flags_CXX INTERFACE ${ROOT_CXX_FLAGS})
|
||||
separate_arguments(ROOT_DEFINITIONS)
|
||||
target_compile_definitions(ROOT::Flags_CXX INTERFACE ${ROOT_DEFINITIONS})
|
||||
|
||||
# This fixes a bug in the linker flags
|
||||
string(REPLACE "-L " "-L" ROOT_EXE_LINKER_FLAGS "${ROOT_EXE_LINKER_FLAGS}")
|
||||
separate_arguments(ROOT_EXE_LINKER_FLAGS)
|
||||
|
||||
# Stuck into using old property method due to separate -L and -l arguments
|
||||
# (A full path to -l is better!)
|
||||
set_property(TARGET ROOT::Flags_CXX PROPERTY
|
||||
INTERFACE_LINK_LIBRARIES ${ROOT_EXE_LINKER_FLAGS})
|
||||
set_property(TARGET ROOT::Core PROPERTY
|
||||
INTERFACE_INCLUDE_DIRECTORIES "${ROOT_INCLUDE_DIRS}")
|
||||
|
||||
|
||||
add_executable(ctbGui
|
||||
ctbGui.cpp
|
||||
ctbMain.cpp
|
||||
ctbDacs.cpp
|
||||
ctbPowers.cpp
|
||||
ctbSlowAdcs.cpp
|
||||
ctbSignals.cpp
|
||||
ctbAdcs.cpp
|
||||
ctbPattern.cpp
|
||||
ctbAcquisition.cpp
|
||||
${CMAKE_SOURCE_DIR}/slsDetectorCalibration/tiffio/src/tiffIO.cpp
|
||||
)
|
||||
|
||||
|
||||
#TODO! Replace with target
|
||||
target_include_directories(ctbGui PRIVATE
|
||||
${CMAKE_SOURCE_DIR}/slsDetectorCalibration/dataStructures
|
||||
${CMAKE_SOURCE_DIR}/slsDetectorCalibration/interpolations
|
||||
${CMAKE_SOURCE_DIR}/slsDetectorCalibration/
|
||||
${CMAKE_SOURCE_DIR}/slsDetectorCalibration/tiffio/include/
|
||||
)
|
||||
|
||||
# Headders needed for ROOT dictionary generation
|
||||
set( HEADERS
|
||||
ctbDefs.h
|
||||
ctbMain.h
|
||||
ctbDacs.h
|
||||
ctbPattern.h
|
||||
ctbSignals.h
|
||||
ctbAdcs.h
|
||||
ctbAcquisition.h
|
||||
ctbPowers.h
|
||||
ctbSlowAdcs.h
|
||||
)
|
||||
|
||||
#set(ROOT_INCLUDE_PATH ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
|
||||
# ROOT dictionary generation
|
||||
root_generate_dictionary(ctbDict ${HEADERS} LINKDEF ctbLinkDef.h)
|
||||
add_library(ctbRootLib SHARED ctbDict.cxx)
|
||||
target_include_directories(ctbRootLib PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
target_link_libraries(ctbRootLib PUBLIC
|
||||
ROOT::Core
|
||||
slsDetectorShared
|
||||
${ROOT_LIBRARIES}
|
||||
${ROOT_EXE_LINKER_FLAGS}
|
||||
)
|
||||
|
||||
set_target_properties(
|
||||
ctbRootLib PROPERTIES
|
||||
LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin
|
||||
)
|
||||
|
||||
target_link_libraries(ctbGui PUBLIC
|
||||
slsDetectorShared
|
||||
ctbRootLib
|
||||
${TIFF_LIBRARIES}
|
||||
)
|
||||
|
||||
set_target_properties(ctbGui PROPERTIES
|
||||
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin
|
||||
|
||||
)
|
||||
|
@ -1,46 +0,0 @@
|
||||
# SPDX-License-Identifier: LGPL-3.0-or-other
|
||||
# Copyright (C) 2021 Contributors to the SLS Detector Package
|
||||
|
||||
|
||||
INCS=ctbMain.h ctbDacs.h ctbPattern.h ctbSignals.h ctbAdcs.h ctbAcquisition.h ctbPowers.h ctbSlowAdcs.h
|
||||
SRC= $(INCS:.h=.cpp) ctbDict.cpp
|
||||
LINKDEF=ctbLinkDef.h
|
||||
ZMQLIB=../slsReceiverSoftware/include
|
||||
LIBRARYCBF=$(CBFLIBDIR)/lib/*.o
|
||||
|
||||
INCDIR=-I../slsReceiverSoftware/include/ -I../slsDetectorSoftware/include/ -I../slsSupportLib/include/ -I../slsDetectorCalibration -I../slsDetectorCalibration/dataStructures -I$(CBFLIBDIR)/include -I../slsDetectorCalibration/interpolations
|
||||
LDFLAG=-L../build/bin -lSlsDetector -lSlsSupport -L/usr/lib64/ -lpthread -lm -lstdc++ -lzmq -pthread -lrt -ltiff -L$(ZMQLIB) -L$(CBFLIBDIR)/lib/ -std=c++11
|
||||
#
|
||||
MAIN=ctbGui.cpp
|
||||
|
||||
DESTDIR?=../build/bin
|
||||
|
||||
|
||||
OBJS = $(SRC:.cpp=.o) $(MAIN:.cpp=.o)
|
||||
|
||||
all: $(DESTDIR)/ctbGui
|
||||
|
||||
|
||||
doc:
|
||||
cd manual && make DESTDIR=$(DESTDIR)
|
||||
|
||||
htmldoc:
|
||||
cd manual && make html DESTDIR=$(DESTDIR)
|
||||
|
||||
ctbDict.cpp: $(INCS) $(LINKDEF)
|
||||
rootcint -f ctbDict.cpp -c $(INCS) $(LINKDEF)
|
||||
|
||||
%.o : %.cpp
|
||||
echo $@
|
||||
g++ -DMYROOT `root-config --cflags --glibs` -lMinuit -DCTB $(LDFLAG) -o $@ -c $< $(INCDIR)
|
||||
#$(CXX) -o $@ -c $< $(INCLUDES) $(DFLAGS) -fPIC $(EPICSFLAGS) -lpthread #$(FLAGS)
|
||||
|
||||
|
||||
|
||||
$(DESTDIR)/ctbGui: $(OBJS) $(LINKDEF)
|
||||
g++ -DMYROOT `root-config --cflags --glibs` -lMinuit -DCTB $(LDFLAG) -o ctbGui $(INCDIR) $(OBJS) ../slsDetectorCalibration/tiffIO.cpp
|
||||
mv ctbGui $(DESTDIR)
|
||||
|
||||
clean:
|
||||
rm -f $(DESTDIR)/ctbGui *.o ctbDict.* $(OBJS)
|
||||
|
@ -1,48 +0,0 @@
|
||||
# SPDX-License-Identifier: LGPL-3.0-or-other
|
||||
# Copyright (C) 2021 Contributors to the SLS Detector Package
|
||||
|
||||
|
||||
INCS=ctbMain.h ctbDacs.h ctbPattern.h ctbSignals.h ctbAdcs.h ctbAcquisition.h ctbPowers.h ctbSlowAdcs.h
|
||||
SRC= $(INCS:.h=.cpp) ctbDict.cpp
|
||||
LINKDEF=ctbLinkDef.h
|
||||
#ctbActions.h
|
||||
ZMQLIB=../slsReceiverSoftware/include
|
||||
LIBRARYCBF=$(CBFLIBDIR)/lib/*.o
|
||||
|
||||
INCDIR=-I../slsReceiverSoftware/include/ -I../slsDetectorSoftware/include/ -I../slsSupportLib/include/ -I../slsDetectorCalibration -I../slsDetectorCalibration/dataStructures -I$(CBFLIBDIR)/include -I../slsDetectorCalibration/interpolations
|
||||
|
||||
LDFLAG=-L../build/bin -lSlsDetector -lSlsSupport -L/usr/lib64/ -lpthread -lm -lstdc++ -lzmq -pthread -lrt -ltiff -L$(ZMQLIB) -L$(CBFLIBDIR)/lib/ -std=c++11
|
||||
#
|
||||
MAIN=ctbGui.cpp
|
||||
|
||||
DESTDIR?=../build/bin
|
||||
|
||||
|
||||
OBJS = $(SRC:.cpp=.o) $(MAIN:.cpp=.o)
|
||||
|
||||
all: $(DESTDIR)/ctbGui
|
||||
|
||||
|
||||
doc:
|
||||
cd manual && make DESTDIR=$(DESTDIR)
|
||||
|
||||
htmldoc:
|
||||
cd manual && make html DESTDIR=$(DESTDIR)
|
||||
|
||||
ctbDict.cpp: $(INCS) $(LINKDEF)
|
||||
rootcling -f ctbDict.cpp -c $(INCS) $(LINKDEF)
|
||||
|
||||
%.o : %.cpp
|
||||
echo $@
|
||||
g++ -DMYROOT `source root-config --cflags --glibs` -lMinuit -DCTB $(LDFLAG) -o $@ -c $< $(INCDIR)
|
||||
#$(CXX) -o $@ -c $< $(INCLUDES) $(DFLAGS) -fPIC $(EPICSFLAGS) -lpthread #$(FLAGS)
|
||||
|
||||
|
||||
|
||||
$(DESTDIR)/ctbGui: $(OBJS) $(LINKDEF)
|
||||
g++ -DMYROOT `source root-config --cflags --glibs` -lMinuit -DCTB $(LDFLAG) -o ctbGui $(INCDIR) $(OBJS) ../slsDetectorCalibration/tiffIO.cpp
|
||||
mv ctbGui $(DESTDIR)
|
||||
|
||||
clean:
|
||||
rm -f $(DESTDIR)/ctbGui *.o ctbDict.* $(OBJS)
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,248 +0,0 @@
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-other
|
||||
// Copyright (C) 2021 Contributors to the SLS Detector Package
|
||||
#ifndef CTBACQUISITION_H
|
||||
#define CTBACQUISITION_H
|
||||
#include <TGFrame.h>
|
||||
|
||||
#include "ctbAdcs.h"
|
||||
#include "ctbSignals.h"
|
||||
#include "ctbPattern.h"
|
||||
class TGTextEntry;
|
||||
class TGLabel;
|
||||
class TGNumberEntry;
|
||||
class TGCheckButton;
|
||||
class TThread;
|
||||
class TGraph;
|
||||
class TMultiGraph;
|
||||
class THStack;
|
||||
class TGButtonGroup;
|
||||
class TGRadioButton;
|
||||
class TGComboBox;
|
||||
class TTimer;
|
||||
class TCanvas;
|
||||
class TH2F;
|
||||
class TH1F;
|
||||
class TGLabel;
|
||||
class TGTextButton;
|
||||
|
||||
namespace sls
|
||||
{
|
||||
class Detector;
|
||||
class detectorData;
|
||||
};
|
||||
|
||||
template <class dataType> class slsDetectorData;
|
||||
|
||||
class singlePhotonDetector;
|
||||
//class singlePhotonDetector;
|
||||
class commonModeSubtraction;
|
||||
|
||||
#include <string>
|
||||
#include <stdint.h>
|
||||
using namespace std;
|
||||
|
||||
class ctbAcquisition : public TGGroupFrame {
|
||||
|
||||
|
||||
enum {DESERIALIZER, MOENCH04, MOENCH02, MOENCH03, IMAGE32B, IMAGE16B, ADCSAR2, MYTHEN301, MYTHEN302};
|
||||
|
||||
|
||||
private:
|
||||
TGTextEntry *eOutdir;
|
||||
TGTextEntry *eFname;
|
||||
TGNumberEntry *eFindex;
|
||||
TGCheckButton *cFileSave;
|
||||
|
||||
|
||||
TGNumberEntry *eSerOff;
|
||||
TGNumberEntry *eDynRange;
|
||||
TGNumberEntry *eNumCount;
|
||||
|
||||
|
||||
TGNumberEntry *ePixX;
|
||||
TGNumberEntry *ePixY;
|
||||
|
||||
TGNumberEntry *eFitADC;
|
||||
TGNumberEntry *eBitPlot;
|
||||
TGNumberEntry *eMinRaw;
|
||||
TGNumberEntry *eMaxRaw;
|
||||
TGNumberEntry *eMinPedSub;
|
||||
TGNumberEntry *eMaxPedSub;
|
||||
TGCheckButton *cMinMaxRaw;
|
||||
TGCheckButton *cMinMaxPedSub;
|
||||
|
||||
|
||||
|
||||
|
||||
TGNumberEntry *eMeasurements;
|
||||
|
||||
|
||||
|
||||
TGTextButton *bStatus;
|
||||
// TGTextButton
|
||||
TGCheckButton *cCompile;
|
||||
TGTextButton *cLoad;
|
||||
// TGCheckButton *cRun;
|
||||
|
||||
TThread *acqThread;
|
||||
|
||||
|
||||
THStack *adcStack;
|
||||
THStack *bitStack;
|
||||
THStack *countsStack;
|
||||
|
||||
|
||||
TH1F *adcHisto[NADCS];
|
||||
TH1F *countsHisto[NADCS];
|
||||
|
||||
TH1F *bitHisto[NSIGNALS];
|
||||
float bitOffset[NSIGNALS];
|
||||
|
||||
// int enableFlag[NADCS+4];
|
||||
int roMode;
|
||||
|
||||
int dBitOffset;
|
||||
|
||||
|
||||
|
||||
TH1F *adcFit;
|
||||
TH1F *bitPlot;
|
||||
TH1F *countsFit;
|
||||
|
||||
|
||||
|
||||
TH2F *h2DMapAn; // for 2D detectors
|
||||
TH2F *h2DMapDig; // for 2D detectors
|
||||
TH1F *h1DMap; //for 1D detectors
|
||||
|
||||
// TH2F *h2Scan; // for 2D detectors
|
||||
// TMultiGraph *mgAdcs;
|
||||
// TH1I *plotAdc[NADCS];
|
||||
|
||||
|
||||
sls::Detector* myDet;
|
||||
|
||||
int plotFlag[NADCS];
|
||||
int bitPlotFlag[NSIGNALS];
|
||||
|
||||
int ip;
|
||||
// int nChannels;
|
||||
// int chanEnable;
|
||||
//int nADCs;
|
||||
|
||||
std::vector <int> dbitlist;
|
||||
std::vector <int> adclist;
|
||||
|
||||
TGButtonGroup *bgPlot;// = new TGVButtonGroup(main_frame);
|
||||
TGRadioButton *rbPlotOff;
|
||||
TGRadioButton *rbWaveform;
|
||||
TGRadioButton *rbDistribution;
|
||||
TGRadioButton *rb2D;
|
||||
// TGRadioButton *rbScan;
|
||||
TGComboBox *cbDetType;
|
||||
TGCheckButton *cbGetPedestal;
|
||||
TGCheckButton *cbSubtractPedestal;
|
||||
TGCheckButton *cbCommonMode;
|
||||
TGTextButton *bResetPedestal;
|
||||
|
||||
TGLabel *lClickX;
|
||||
TGLabel *lClickY;
|
||||
TGLabel *lClickValue;
|
||||
|
||||
|
||||
TCanvas *myCanvas;
|
||||
TTimer *plotTimer;
|
||||
|
||||
char patternFile[10000];
|
||||
char patternCompiler[10000];
|
||||
|
||||
int globalPlot;
|
||||
int adcPlot;
|
||||
int dbitPlot;
|
||||
int tenG;
|
||||
|
||||
int nAnalogSamples, nDigitalSamples;
|
||||
// int iScanStep;
|
||||
|
||||
slsDetectorData<uint16_t> *dataStructure;
|
||||
singlePhotonDetector *photonFinder;
|
||||
//singlePhotonDetector *photonFinder;
|
||||
commonModeSubtraction *commonMode;
|
||||
int cmSub;
|
||||
|
||||
int stop;
|
||||
|
||||
uint64_t dBitMask;
|
||||
|
||||
int deserializer;
|
||||
|
||||
public:
|
||||
ctbAcquisition(TGVerticalFrame*, sls::Detector*);
|
||||
void setOutdir();
|
||||
void setFname();
|
||||
void setMeasurements();
|
||||
void setFsave(Bool_t);
|
||||
void changePlot(Int_t);
|
||||
void changeDetector(Int_t);
|
||||
void changePlot();
|
||||
void changeDetector();
|
||||
void setFindex();
|
||||
void Draw();
|
||||
void setCanvas(TCanvas*);
|
||||
|
||||
void toggleAcquisition();
|
||||
void loadPattern();
|
||||
static void* ThreadHandle(void *arg);
|
||||
void update();
|
||||
void acquisitionFinished();
|
||||
// string getParameters();
|
||||
|
||||
void setGraph (int i ,int en, Pixel_t col);
|
||||
void setBitGraph (int i ,int en, Pixel_t col);
|
||||
void startAcquisition();
|
||||
static void progressCallback(double,void*);
|
||||
static void dataCallback(sls::detectorData*, long unsigned int, unsigned int, void*);
|
||||
int StopFlag;
|
||||
|
||||
int plotData(sls::detectorData*, int);
|
||||
|
||||
void setPatternFile(const char* t);
|
||||
|
||||
void setPatternCompiler(const char* t);
|
||||
|
||||
void setAnalogSamples(int);
|
||||
void setDigitalSamples(int);
|
||||
|
||||
void setADCEnable(Int_t);
|
||||
void setDbitEnable(Int_t);
|
||||
void setReadoutMode(int);
|
||||
void updateChans();
|
||||
|
||||
void resetPedestal();
|
||||
|
||||
void ToggleCommonMode(Bool_t);
|
||||
void TogglePedSub(Bool_t);
|
||||
void ChangeHistoLimitsPedSub(Long_t );
|
||||
void ChangeHistoLimitsRaw(Long_t);
|
||||
void ChangeHistoLimitsPedSub( );
|
||||
void ChangeHistoLimitsRaw();
|
||||
void ChangeHistoLimitsPedSub(Bool_t );
|
||||
void ChangeHistoLimitsRaw(Bool_t);
|
||||
|
||||
|
||||
void ChangeSerialOffset();
|
||||
void ChangeSerialOffset(Long_t);
|
||||
void ChangeNumberOfChannels();
|
||||
void ChangeNumberOfChannels(Long_t);
|
||||
void ChangeDynamicRange();
|
||||
void ChangeDynamicRange(Long_t);
|
||||
void ChangeImagePixels();
|
||||
void ChangeImagePixels(Long_t);
|
||||
|
||||
void canvasClicked();
|
||||
void FitADC();
|
||||
void plotBit();
|
||||
ClassDef(ctbAcquisition,0)
|
||||
};
|
||||
|
||||
#endif
|
@ -1,616 +0,0 @@
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-other
|
||||
// Copyright (C) 2021 Contributors to the SLS Detector Package
|
||||
#include <TApplication.h>
|
||||
#include <TGClient.h>
|
||||
#include <TCanvas.h>
|
||||
#include <TF1.h>
|
||||
#include <TRandom.h>
|
||||
#include <TGButton.h>
|
||||
#include <TRootEmbeddedCanvas.h>
|
||||
#include <TGButtonGroup.h>
|
||||
#include <TGNumberEntry.h>
|
||||
#include <TGLabel.h>
|
||||
#include <TList.h>
|
||||
#include <TGFileDialog.h>
|
||||
#include <TGComboBox.h>
|
||||
#include <TH2F.h>
|
||||
#include <TColor.h>
|
||||
#include <TH1F.h>
|
||||
#include <TGraphErrors.h>
|
||||
#include <TGColorSelect.h>
|
||||
#include <THStack.h>
|
||||
#include <TGTab.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
#include "ctbAdcs.h"
|
||||
#include "ctbDefs.h"
|
||||
#include "sls/Detector.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
|
||||
ctbAdc::ctbAdc(TGVerticalFrame *page, int i, sls::Detector *det)
|
||||
: TGHorizontalFrame(page, 800,800), id(i), myDet(det) {
|
||||
|
||||
TGHorizontalFrame *hframe=this;
|
||||
char tit[100];
|
||||
|
||||
page->AddFrame(hframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 1,1,1,1));
|
||||
hframe->MapWindow();
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
sprintf(tit, "ADC%d", id);
|
||||
|
||||
sAdcLabel= new TGLabel(hframe, tit);
|
||||
hframe->AddFrame(sAdcLabel,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1));
|
||||
sAdcLabel->MapWindow();
|
||||
sAdcLabel->SetTextJustify(kTextLeft);
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
sAdcInvert= new TGCheckButton(hframe, "Inv");
|
||||
hframe->AddFrame( sAdcInvert,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1));
|
||||
sAdcInvert->MapWindow();
|
||||
sAdcInvert->Connect("Toggled(Bool_t)","ctbAdc",this,"ToggledInvert(Bool_t)");
|
||||
|
||||
|
||||
sAdcEnable= new TGCheckButton(hframe, "En");
|
||||
hframe->AddFrame( sAdcEnable,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1));
|
||||
sAdcEnable->MapWindow();
|
||||
// sAdcEnable->SetOn(kTRUE);
|
||||
// sAdcEnable->SetEnabled(kFALSE);
|
||||
sAdcEnable->Connect("Toggled(Bool_t)","ctbAdc",this,"ToggledEnable(Bool_t)");
|
||||
|
||||
|
||||
|
||||
sAdcPlot= new TGCheckButton(hframe, "Plot");
|
||||
hframe->AddFrame( sAdcPlot,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1));
|
||||
sAdcPlot->MapWindow();
|
||||
|
||||
|
||||
sAdcPlot->Connect("Toggled(Bool_t)","ctbAdc",this,"ToggledPlot(Bool_t)");
|
||||
|
||||
|
||||
|
||||
fColorSel = new TGColorSelect(hframe, id+1, 0);
|
||||
|
||||
fColorSel->Connect("ColorSelected(Pixel_t)","ctbAdc",this,"ColorChanged(Pixel_t)");
|
||||
hframe->AddFrame(fColorSel, new TGLayoutHints(kLHintsTop |
|
||||
kLHintsLeft, 2, 0, 2, 2));
|
||||
|
||||
|
||||
fColorSel->SetColor(TColor::Number2Pixel(id+1));
|
||||
// sprintf(tit,"adc%d",id);
|
||||
// gADC=new TGraph();
|
||||
// gADC->SetName(tit);
|
||||
// gADC->SetLineColor(id+1);
|
||||
// gADC->SetMarkerColor(id+1);
|
||||
|
||||
|
||||
|
||||
};
|
||||
Pixel_t ctbAdc::getColor(){
|
||||
return fColorSel->GetColor();
|
||||
}
|
||||
Bool_t ctbAdc::getEnabled(){
|
||||
return getPlot();
|
||||
}
|
||||
Bool_t ctbAdc::getPlot(){
|
||||
return sAdcPlot->IsOn();
|
||||
}
|
||||
Bool_t ctbAdc::getInverted(){
|
||||
return sAdcInvert->IsOn();
|
||||
}
|
||||
|
||||
Bool_t ctbAdc::getEnable(){
|
||||
return sAdcEnable->IsOn();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ctbAdc::setInverted(Bool_t b){
|
||||
// cout << id << "set enabled " << b << endl;
|
||||
if (b)
|
||||
sAdcInvert->SetOn(kTRUE,kTRUE);
|
||||
else
|
||||
sAdcInvert->SetOn(kFALSE,kTRUE);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void ctbAdc::setEnable(Bool_t b){
|
||||
// cout << id << "set enabled " << b << endl;
|
||||
if (b)
|
||||
sAdcEnable->SetOn(kTRUE,kFALSE);
|
||||
else
|
||||
sAdcEnable->SetOn(kFALSE,kFALSE);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void ctbAdc::setAdcAlias(char *tit, int plot, int color) {
|
||||
if (tit)
|
||||
sAdcLabel->SetText(tit);
|
||||
if (plot>0)
|
||||
sAdcPlot->SetOn(kTRUE,kTRUE);
|
||||
else if (plot==0)
|
||||
sAdcPlot->SetOn(kFALSE,kTRUE);
|
||||
if (color>=0)
|
||||
fColorSel->SetColor(color);
|
||||
fColorSel->SetEnabled(sAdcPlot->IsOn());
|
||||
}
|
||||
|
||||
|
||||
string ctbAdc::getAdcAlias() {
|
||||
|
||||
char line[1000];
|
||||
sprintf(line,"ADC%d %s %d %lx\n",id,sAdcLabel->GetText()->Data(),sAdcPlot->IsOn(),fColorSel->GetColor());
|
||||
return string(line);
|
||||
}
|
||||
|
||||
void ctbAdc::update() {
|
||||
|
||||
|
||||
//Emit("ToggledAdcEnable(Int_t)", id);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void ctbAdc::ToggledPlot(Bool_t b){
|
||||
|
||||
// Long_t mask=b<<id;
|
||||
// ToggledAdcPlot(mask);
|
||||
cout << "Colsel " << id << " enable " << b << endl;
|
||||
if (b)
|
||||
fColorSel->SetEnabled(kTRUE);
|
||||
else
|
||||
fColorSel->SetEnabled(kFALSE);
|
||||
|
||||
// fColorSel->SetEnabled(sAdcPlot->IsOn());
|
||||
Emit("ToggledAdcPlot(Int_t)", id);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ctbAdc::ToggledInvert(Bool_t b){
|
||||
|
||||
|
||||
// fColorSel->SetEnabled(sAdcPlot->IsOn());
|
||||
Emit("ToggledAdcInvert(Int_t)", id);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ctbAdc::ToggledEnable(Bool_t b){
|
||||
|
||||
|
||||
fColorSel->SetEnabled(sAdcPlot->IsOn());
|
||||
Emit("ToggledAdcEnable(Int_t)", id);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void ctbAdc::ColorChanged(Pixel_t) {
|
||||
|
||||
Emit("ToggledAdcPlot(Int_t)", id);
|
||||
|
||||
}
|
||||
|
||||
void ctbAdc::ToggledAdcPlot(Int_t b){
|
||||
|
||||
|
||||
Emit("ToggledAdcPlot(Int_t)", id);
|
||||
|
||||
}
|
||||
|
||||
void ctbAdc::ToggledAdcInvert(Int_t b){
|
||||
|
||||
|
||||
Emit("ToggledAdcInvert(Int_t)", id);
|
||||
|
||||
}
|
||||
|
||||
void ctbAdc::ToggledAdcEnable(Int_t b){
|
||||
|
||||
|
||||
Emit("ToggledAdcEnable(Int_t)", id);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void ctbAdc::setEnabled(Bool_t b){
|
||||
// cout << id << "set enabled " << b << endl;
|
||||
if (b)
|
||||
sAdcPlot->SetOn(kTRUE,kFALSE);
|
||||
else
|
||||
sAdcPlot->SetOn(kFALSE,kFALSE);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ctbAdc::setPlot(Bool_t b){
|
||||
// cout << id << "set enabled " << b << endl;
|
||||
if (b)
|
||||
sAdcPlot->SetOn(kTRUE,kTRUE);
|
||||
else
|
||||
sAdcPlot->SetOn(kFALSE,kTRUE);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
ctbAdcs::ctbAdcs(TGVerticalFrame *page, sls::Detector *det)
|
||||
: TGGroupFrame(page,"Adcs",kVerticalFrame), myDet(det) {
|
||||
|
||||
|
||||
SetTitlePos(TGGroupFrame::kLeft);
|
||||
page->AddFrame(this,new TGLayoutHints( kLHintsTop | kLHintsExpandX , 10,10,10,10));
|
||||
MapWindow();
|
||||
|
||||
|
||||
|
||||
TGHorizontalFrame* hframe=new TGHorizontalFrame(this, 800,800);
|
||||
AddFrame(hframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 1,1,1,1));
|
||||
hframe->MapWindow();
|
||||
|
||||
|
||||
|
||||
|
||||
int idac=0;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
TGHorizontalFrame* hhframe=new TGHorizontalFrame(this, 800,800);
|
||||
AddFrame(hhframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 1,1,1,1));
|
||||
hhframe->MapWindow();
|
||||
|
||||
TGVerticalFrame *vframe;
|
||||
|
||||
|
||||
|
||||
|
||||
for (idac=0; idac<NADCS; idac++) {
|
||||
if (idac%16==0) {
|
||||
|
||||
|
||||
vframe=new TGVerticalFrame(hhframe, 400,800);
|
||||
hhframe->AddFrame(vframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 1,1,1,1));
|
||||
vframe->MapWindow();
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
sAdc[idac]=new ctbAdc(vframe,idac,myDet);
|
||||
|
||||
|
||||
sAdc[idac]->Connect("ToggledAdcPlot(Int_t)","ctbAdcs",this,"ToggledAdcPlot(Int_t)");
|
||||
sAdc[idac]->Connect("ToggledAdcInvert(Int_t)","ctbAdcs",this,"ToggledAdcInvert(Int_t)");
|
||||
sAdc[idac]->Connect("ToggledAdcEnable(Int_t)","ctbAdcs",this,"ToggledAdcEnable(Int_t)");
|
||||
|
||||
}
|
||||
|
||||
hframe=new TGHorizontalFrame(this, 800,800);
|
||||
AddFrame(hframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 1,1,1,1));
|
||||
hframe->MapWindow();
|
||||
|
||||
|
||||
bCheckHalf[0]=new TGTextButton(hframe, "All 0-15");
|
||||
hframe->AddFrame(bCheckHalf[0],new TGLayoutHints(kLHintsTop | kLHintsExpandX, 5, 5, 5, 5));
|
||||
bCheckHalf[0]->MapWindow();
|
||||
bCheckHalf[0]->Connect("Clicked()","ctbAdcs",this,"CheckHalf0()");
|
||||
|
||||
|
||||
bRemoveHalf[0]=new TGTextButton(hframe, "None 0-15");
|
||||
hframe->AddFrame(bRemoveHalf[0],new TGLayoutHints(kLHintsBottom | kLHintsExpandX, 5, 5, 5, 5));
|
||||
bRemoveHalf[0]->MapWindow();
|
||||
bRemoveHalf[0]->Connect("Clicked()","ctbAdcs",this,"RemoveHalf0()");
|
||||
|
||||
|
||||
bCheckHalf[1]=new TGTextButton(hframe, "All 16-23");
|
||||
hframe->AddFrame(bCheckHalf[1],new TGLayoutHints(kLHintsTop | kLHintsExpandX, 5, 5, 5, 5));
|
||||
bCheckHalf[1]->MapWindow();
|
||||
bCheckHalf[1]->Connect("Clicked()","ctbAdcs",this,"CheckHalf1()");
|
||||
// bCheckAll->Connect("Clicked()","ctbAdcs",this,"CheckAll()");
|
||||
|
||||
|
||||
bRemoveHalf[1]=new TGTextButton(hframe, "None 16-23");
|
||||
hframe->AddFrame(bRemoveHalf[1],new TGLayoutHints(kLHintsBottom | kLHintsExpandX, 5, 5, 5, 5));
|
||||
bRemoveHalf[1]->MapWindow();
|
||||
bRemoveHalf[1]->Connect("Clicked()","ctbAdcs",this,"RemoveHalf1()");
|
||||
// bRemoveAll->Connect("Clicked()","ctbAdcs",this,"RemoveAll()");
|
||||
|
||||
|
||||
|
||||
|
||||
hframe=new TGHorizontalFrame(this, 800,800);
|
||||
AddFrame(hframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 1,1,1,1));
|
||||
hframe->MapWindow();
|
||||
|
||||
|
||||
bCheckAll=new TGTextButton(hframe, "All");
|
||||
hframe->AddFrame(bCheckAll,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 5, 5, 5, 5));
|
||||
bCheckAll->MapWindow();
|
||||
bCheckAll->Connect("Clicked()","ctbAdcs",this,"CheckAll()");
|
||||
|
||||
|
||||
bRemoveAll=new TGTextButton(hframe, "None");
|
||||
hframe->AddFrame(bRemoveAll,new TGLayoutHints(kLHintsBottom | kLHintsExpandX, 5, 5, 5, 5));
|
||||
bRemoveAll->MapWindow();
|
||||
bRemoveAll->Connect("Clicked()","ctbAdcs",this,"RemoveAll()");
|
||||
|
||||
|
||||
|
||||
hframe=new TGHorizontalFrame(this, 800,50);
|
||||
AddFrame(hframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 1,1,1,1));
|
||||
hframe->MapWindow();
|
||||
|
||||
|
||||
TGLabel *label= new TGLabel(hframe, "Inversion mask: ");
|
||||
hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1));
|
||||
label->MapWindow();
|
||||
label->SetTextJustify(kTextLeft);
|
||||
|
||||
|
||||
eInversionMask = new TGNumberEntry(hframe, 0, 16,999, TGNumberFormat::kNESHex,
|
||||
TGNumberFormat::kNEANonNegative,
|
||||
TGNumberFormat::kNELNoLimits);
|
||||
|
||||
hframe->AddFrame(eInversionMask,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 1, 1, 1, 1));
|
||||
eInversionMask->MapWindow();
|
||||
eInversionMask->Resize(150,30);
|
||||
eInversionMask->SetState(kFALSE);
|
||||
|
||||
|
||||
hframe=new TGHorizontalFrame(this, 800,50);
|
||||
AddFrame(hframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 1,1,1,1));
|
||||
hframe->MapWindow();
|
||||
|
||||
|
||||
label= new TGLabel(hframe, "Enable mask: ");
|
||||
hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1));
|
||||
label->MapWindow();
|
||||
label->SetTextJustify(kTextLeft);
|
||||
|
||||
|
||||
eEnableMask = new TGNumberEntry(hframe, 0, 16,999, TGNumberFormat::kNESHex,
|
||||
TGNumberFormat::kNEANonNegative,
|
||||
TGNumberFormat::kNELNoLimits);
|
||||
|
||||
hframe->AddFrame(eEnableMask,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 1, 1, 1, 1));
|
||||
eEnableMask->MapWindow();
|
||||
eEnableMask->Resize(150,30);
|
||||
eEnableMask->SetState(kFALSE);
|
||||
|
||||
}
|
||||
|
||||
|
||||
int ctbAdcs::setEnable(int reg) {
|
||||
|
||||
try {
|
||||
if (reg > -1) {
|
||||
myDet->setADCEnableMask(reg);
|
||||
}
|
||||
auto retval = myDet->getADCEnableMask().tsquash("Different values");
|
||||
eEnableMask->SetHexNumber(retval);
|
||||
return retval;
|
||||
} CATCH_DISPLAY ("Could not set/get adc enablemask.", "ctbAdcs::setEnable")
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int ctbAdcs::setInvert(int reg) {
|
||||
|
||||
try {
|
||||
if (reg > -1) {
|
||||
myDet->setADCInvert(reg);
|
||||
}
|
||||
auto retval = myDet->getADCInvert().tsquash("Different values");
|
||||
eInversionMask->SetHexNumber(retval);
|
||||
return retval;
|
||||
} CATCH_DISPLAY ("Could not set/get adc enablemask.", "ctbAdcs::setEnable")
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ctbAdcs::update() {
|
||||
Int_t invreg;
|
||||
Int_t disreg;
|
||||
|
||||
disreg=setEnable();
|
||||
invreg=setInvert();
|
||||
|
||||
for (int is=0; is<NADCS; is++) {
|
||||
sAdc[is]->setAdcAlias(NULL,-1,-1);
|
||||
if (invreg & (1<<is) )
|
||||
sAdc[is]->setInverted(kTRUE);
|
||||
else
|
||||
sAdc[is]->setInverted(kFALSE);
|
||||
|
||||
if (disreg & (1<<is) )
|
||||
sAdc[is]->setEnable(kTRUE);
|
||||
else
|
||||
sAdc[is]->setEnable(kFALSE);
|
||||
}
|
||||
|
||||
Emit("AdcEnable(Int_t)", disreg);
|
||||
|
||||
}
|
||||
string ctbAdcs::getAdcParameters() {
|
||||
ostringstream line;
|
||||
line << "reg "<< hex << setInvert() << "# ADC invert reg" << dec << endl;
|
||||
line << "reg "<< hex << setEnable() << " # ADC enable reg"<< dec << endl;
|
||||
return line.str();
|
||||
|
||||
}
|
||||
|
||||
|
||||
void ctbAdcs::CheckAll() {
|
||||
for (int is=0; is<NADCS; is++){
|
||||
sAdc[is]->setPlot(kTRUE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ctbAdcs::RemoveAll() {
|
||||
for (int is=0; is<NADCS; is++) {
|
||||
sAdc[is]->setPlot(kFALSE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ctbAdcs::CheckHalf0() {
|
||||
for (int is=0; is<NADCS/2; is++) {
|
||||
sAdc[is]->setPlot(kTRUE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ctbAdcs::RemoveHalf0() {
|
||||
for (int is=0; is<NADCS/2; is++){
|
||||
sAdc[is]->setPlot(kFALSE);
|
||||
}
|
||||
}
|
||||
|
||||
void ctbAdcs::CheckHalf1() {
|
||||
for (int is=NADCS/2; is<NADCS; is++){
|
||||
sAdc[is]->setPlot(kTRUE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ctbAdcs::RemoveHalf1() {
|
||||
for (int is=NADCS/2; is<NADCS; is++){
|
||||
sAdc[is]->setPlot(kFALSE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int ctbAdcs::setAdcAlias(string line) {
|
||||
|
||||
int is=-1, plot=0, color=-1;
|
||||
char tit[100];
|
||||
int narg=sscanf(line.c_str(),"ADC%d %s %d %x",&is,tit,&plot, &color);
|
||||
if (narg<2)
|
||||
return -1;
|
||||
if (narg!=3)
|
||||
color=-1;
|
||||
if (is>=0 && is<NADCS) {
|
||||
sAdc[is]->setAdcAlias(tit,plot,color);
|
||||
}
|
||||
return is;
|
||||
|
||||
}
|
||||
|
||||
string ctbAdcs::getAdcAlias() {
|
||||
|
||||
ostringstream line;
|
||||
|
||||
for (int is=0; is<NADCS; is++)
|
||||
line << sAdc[is]->getAdcAlias();
|
||||
|
||||
return line.str();
|
||||
}
|
||||
|
||||
|
||||
void ctbAdcs::ToggledAdcPlot(Int_t b){
|
||||
|
||||
|
||||
Emit("ToggledAdcPlot(Int_t)", b);
|
||||
|
||||
}
|
||||
|
||||
void ctbAdcs::AdcEnable(Int_t b){
|
||||
Emit("AdcEnable(Int_t)", b);
|
||||
}
|
||||
|
||||
|
||||
void ctbAdcs::ToggledAdcEnable(Int_t b){
|
||||
|
||||
Int_t oreg=setEnable();
|
||||
Int_t m=1<<b;
|
||||
|
||||
if (sAdc[b]->getEnable())
|
||||
oreg|=m;
|
||||
else
|
||||
oreg&=~m;
|
||||
|
||||
setEnable(oreg);
|
||||
|
||||
Emit("AdcEnable(Int_t)", oreg);
|
||||
}
|
||||
|
||||
|
||||
void ctbAdcs::ToggledAdcInvert(Int_t b){
|
||||
|
||||
Int_t oreg=setInvert();
|
||||
Int_t m=1<<b;
|
||||
|
||||
|
||||
if (sAdc[b]->getInverted())
|
||||
oreg|=m;
|
||||
else
|
||||
oreg&=~m;
|
||||
|
||||
setInvert(oreg);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Pixel_t ctbAdcs::getColor(int i){
|
||||
if (i>=0 && i<NADCS)
|
||||
return sAdc[i]->getColor();
|
||||
return static_cast<Pixel_t>(-1);
|
||||
}
|
||||
|
||||
Bool_t ctbAdcs::getEnabled(int i){
|
||||
if (i>=0 && i<NADCS)
|
||||
return sAdc[i]->getEnabled();
|
||||
return static_cast<Bool_t>(-1);
|
||||
}
|
||||
|
||||
Bool_t ctbAdcs::getEnable(int i){
|
||||
if (i>=0 && i<NADCS)
|
||||
return sAdc[i]->getEnable();
|
||||
return static_cast<Bool_t>(-1);
|
||||
}
|
||||
|
||||
Bool_t ctbAdcs::getPlot(int i){
|
||||
if (i>=0 && i<NADCS)
|
||||
return sAdc[i]->getPlot();
|
||||
return static_cast<Bool_t>(-1);
|
||||
}
|
157
ctbGui/ctbAdcs.h
157
ctbGui/ctbAdcs.h
@ -1,157 +0,0 @@
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-other
|
||||
// Copyright (C) 2021 Contributors to the SLS Detector Package
|
||||
|
||||
|
||||
|
||||
#ifndef CTBADCS_H
|
||||
#define CTBADCS_H
|
||||
#include <TGFrame.h>
|
||||
|
||||
|
||||
#define NADCS 32
|
||||
|
||||
class TRootEmbeddedCanvas;
|
||||
class TGButtonGroup;
|
||||
class TGVerticalFrame;
|
||||
class TGHorizontalFrame;
|
||||
class TGTextEntry;
|
||||
class TGLabel;
|
||||
class TGNumberEntry;
|
||||
class TH2F;
|
||||
class TGComboBox;
|
||||
class TGCheckButton;
|
||||
class TGColorSelect;
|
||||
class TColor;
|
||||
|
||||
class THStack;
|
||||
class TGraphErrors;
|
||||
class TGTextButton;
|
||||
class TGTab;
|
||||
|
||||
class TGraph;
|
||||
|
||||
namespace sls
|
||||
{
|
||||
class Detector;
|
||||
};
|
||||
|
||||
#include <string>
|
||||
using namespace std;
|
||||
|
||||
class ctbAdc : public TGHorizontalFrame {
|
||||
|
||||
|
||||
private:
|
||||
|
||||
|
||||
TGLabel *sAdcLabel;
|
||||
TGCheckButton *sAdcEnable;
|
||||
TGCheckButton *sAdcPlot;
|
||||
TGCheckButton *sAdcInvert;
|
||||
|
||||
TGColorSelect *fColorSel;
|
||||
|
||||
// TGraph *gADC;
|
||||
|
||||
int id;
|
||||
sls::Detector *myDet;
|
||||
|
||||
public:
|
||||
ctbAdc(TGVerticalFrame *page, int i, sls::Detector *det);
|
||||
|
||||
|
||||
void setAdcAlias(char *tit, int plot, int color);
|
||||
string getAdcAlias();
|
||||
void ToggledAdcPlot(Int_t b);
|
||||
void ToggledAdcEnable(Int_t b);
|
||||
void ToggledAdcInvert(Int_t b);
|
||||
|
||||
|
||||
void ToggledPlot(Bool_t b);
|
||||
void ToggledEnable(Bool_t b);
|
||||
void ToggledInvert(Bool_t b);
|
||||
void ColorChanged(Pixel_t);
|
||||
void setEnabled(Bool_t b);
|
||||
Bool_t getEnabled();
|
||||
// TGraph *getGraph();
|
||||
void update();
|
||||
|
||||
Pixel_t getColor();
|
||||
|
||||
Bool_t getEnable();
|
||||
void setEnable(Bool_t);
|
||||
void setPlot(Bool_t);
|
||||
Bool_t getInverted();
|
||||
Bool_t getPlot();
|
||||
void setInverted(Bool_t);
|
||||
|
||||
ClassDef(ctbAdc,0)
|
||||
};
|
||||
|
||||
|
||||
|
||||
class ctbAdcs : public TGGroupFrame {
|
||||
private:
|
||||
|
||||
ctbAdc *sAdc[NADCS];
|
||||
sls::Detector *myDet;
|
||||
|
||||
|
||||
TGTextButton *bCheckAll;
|
||||
TGTextButton *bRemoveAll;
|
||||
TGTextButton *bCheckHalf[2];
|
||||
TGTextButton *bRemoveHalf[2];
|
||||
TGNumberEntry *eInversionMask;
|
||||
TGNumberEntry *eEnableMask;
|
||||
|
||||
|
||||
/* TGTextButton *bPlotSelected; */
|
||||
/* TGNumberEntry *eMinX; */
|
||||
/* TGNumberEntry *eMaxX; */
|
||||
/* TGNumberEntry *eMinY; */
|
||||
/* TGNumberEntry *eMaxY; */
|
||||
|
||||
|
||||
|
||||
/* TGTextButton *bGetPixel; */
|
||||
/* TGNumberEntry *ePixelX; */
|
||||
/* TGNumberEntry *ePixelY; */
|
||||
/* TGLabel *lPixelValue; */
|
||||
|
||||
public:
|
||||
|
||||
ctbAdcs(TGVerticalFrame *page, sls::Detector *det);
|
||||
int setAdcAlias(string line);
|
||||
string getAdcAlias();
|
||||
string getAdcParameters();
|
||||
void ToggledAdcPlot(Int_t);
|
||||
void ToggledAdcInvert(Int_t);
|
||||
void ToggledAdcEnable(Int_t);
|
||||
void AdcEnable(Int_t b);
|
||||
// TGraph *getGraph(int i);
|
||||
void CheckAll();
|
||||
void RemoveAll();
|
||||
void update();
|
||||
|
||||
int setInvert(int reg=-1);
|
||||
int setEnable(int reg=-1);
|
||||
|
||||
|
||||
Pixel_t getColor(int i);
|
||||
Bool_t getEnabled(int i);
|
||||
Bool_t getPlot(int i);
|
||||
Bool_t getEnable(int i);
|
||||
|
||||
void CheckHalf0();
|
||||
void RemoveHalf0();
|
||||
|
||||
void CheckHalf1();
|
||||
void RemoveHalf1();
|
||||
|
||||
|
||||
ClassDef(ctbAdcs,0)
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -1,235 +0,0 @@
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-other
|
||||
// Copyright (C) 2021 Contributors to the SLS Detector Package
|
||||
|
||||
#include <stdio.h>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
#include <TGTextEntry.h>
|
||||
#include <TGLabel.h>
|
||||
#include <TGNumberEntry.h>
|
||||
#include <TGButton.h>
|
||||
|
||||
#include "ctbDacs.h"
|
||||
#include "ctbDefs.h"
|
||||
#include "sls/Detector.h"
|
||||
#include "sls/sls_detector_defs.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
ctbDac::ctbDac(TGGroupFrame *page, int idac, sls::Detector *det) : TGHorizontalFrame(page, 800,50) , id(idac), myDet(det) {
|
||||
|
||||
TGHorizontalFrame *hframe=this;
|
||||
|
||||
page->AddFrame(hframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 1,1,1,1));
|
||||
MapWindow();
|
||||
|
||||
char tit[100];
|
||||
|
||||
|
||||
sprintf(tit, "DAC %d:",idac);
|
||||
|
||||
dacsLabel= new TGCheckButton(hframe, tit);// new TGLabel(hframe, tit);
|
||||
dacsLabel->SetOn(kTRUE, kTRUE);
|
||||
|
||||
dacsLabel->Connect("Toggled(Bool_t)","ctbDac",this,"setOn(Bool_t)");
|
||||
|
||||
|
||||
hframe->AddFrame(dacsLabel,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 5, 5, 5, 5));
|
||||
dacsLabel->MapWindow();
|
||||
dacsLabel->SetTextJustify(kTextLeft);
|
||||
|
||||
|
||||
dacsEntry = new TGNumberEntry(hframe, 0, 9,999, TGNumberFormat::kNESInteger,
|
||||
TGNumberFormat::kNEANonNegative,
|
||||
TGNumberFormat::kNELLimitMinMax,
|
||||
0, 65535);
|
||||
|
||||
hframe->AddFrame(dacsEntry,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 5, 5, 5, 5));
|
||||
dacsEntry->MapWindow();
|
||||
dacsEntry->Resize(150,30);
|
||||
|
||||
|
||||
dacsUnit= new TGCheckButton(hframe, "mV");
|
||||
// if (idac!=slsDetectorDefs::ADC_VPP) {
|
||||
hframe->AddFrame( dacsUnit,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 5, 5, 5, 5));
|
||||
dacsUnit->MapWindow();
|
||||
if (idac==slsDetectorDefs::ADC_VPP) {
|
||||
dacsUnit->SetEnabled(kFALSE);
|
||||
hframe->HideFrame(dacsUnit);
|
||||
dacsUnit->MapWindow();
|
||||
cout << "hiding!" << endl;
|
||||
}
|
||||
if (idac==slsDetectorDefs::HIGH_VOLTAGE) {
|
||||
dacsUnit->SetText("V");
|
||||
dacsUnit->SetOn(kTRUE,kTRUE);
|
||||
dacsUnit->SetEnabled(kFALSE);
|
||||
}
|
||||
//}
|
||||
|
||||
|
||||
|
||||
sprintf(tit, "xxx");
|
||||
dacsValue= new TGLabel(hframe, tit);
|
||||
hframe->AddFrame( dacsValue,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 5, 5, 5, 5));
|
||||
dacsValue->MapWindow();
|
||||
dacsValue->SetTextJustify(kTextLeft);
|
||||
|
||||
TGTextEntry *e=dacsEntry->TGNumberEntry::GetNumberEntry();
|
||||
e->Connect("ReturnPressed()","ctbDac",this,"setValue()");
|
||||
// e->Connect("ValueSet(Long_t)","ctbDac",this,"setValue(Long_t)");
|
||||
dacsEntry->Connect("ValueSet(Long_t)","ctbDac",this,"setValue(Long_t)");
|
||||
// cout << "(((((((((((((((((((((((((((((((" << dacsEntry->GetListOfSignals()->At(0)->IsA() << endl;
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
int ctbDac::setLabel(char *tit, int mv) {
|
||||
if(tit)
|
||||
dacsLabel->SetText(tit);
|
||||
if (mv==1)
|
||||
dacsUnit->SetOn(kTRUE,kTRUE);
|
||||
else if (mv==0)
|
||||
dacsUnit->SetOn(kFALSE,kTRUE);
|
||||
// else if (mv==2) {
|
||||
// ;}
|
||||
// else if (mv==3)
|
||||
// ;
|
||||
return id;
|
||||
|
||||
}
|
||||
|
||||
string ctbDac::getLabel() {
|
||||
ostringstream line;
|
||||
line << dacsLabel->GetText() << " " << dacsUnit->IsOn() << endl;
|
||||
// line << "DAC" << dec << id << " " << dacsUnit->IsOn() << endl;
|
||||
return line.str();
|
||||
|
||||
}
|
||||
|
||||
int ctbDac::getMoenchDacId() {
|
||||
slsDetectorDefs::dacIndex moenchDacIndices[8] = {slsDetectorDefs::VBP_COLBUF, slsDetectorDefs::VIPRE, slsDetectorDefs::VIN_CM, slsDetectorDefs::VB_SDA, slsDetectorDefs::VCASC_SFP, slsDetectorDefs::VOUT_CM, slsDetectorDefs::VIPRE_CDS, slsDetectorDefs::IBIAS_SFP};
|
||||
|
||||
if (id >= 8) {
|
||||
return id;
|
||||
}
|
||||
return static_cast<int>(moenchDacIndices[id]);
|
||||
}
|
||||
|
||||
void ctbDac::setValue(Long_t a) {setValue();}
|
||||
|
||||
void ctbDac::setValue() {
|
||||
cout << "setting dac! "<< id << " value " << dacsEntry->GetIntNumber() << " units " << dacsUnit->IsOn() << endl;
|
||||
|
||||
try {
|
||||
int sid = id;
|
||||
if (myDet->getDetectorType().squash() == slsDetectorDefs::MOENCH) {
|
||||
sid = getMoenchDacId();
|
||||
}
|
||||
myDet->setDAC(static_cast<slsDetectorDefs::dacIndex>(sid), dacsEntry->GetIntNumber(), dacsUnit->IsOn());
|
||||
} CATCH_DISPLAY ("Could not set dac " + to_string(id) + ".", "ctbDac::setValue")
|
||||
|
||||
getValue();
|
||||
}
|
||||
|
||||
void ctbDac::setOn(Bool_t b) {
|
||||
// cout << "setting dac! "<< id << endl;
|
||||
if ( dacsLabel->IsOn()) {
|
||||
setValue();
|
||||
} else {
|
||||
try {
|
||||
int sid = id;
|
||||
if (myDet->getDetectorType().squash() == slsDetectorDefs::MOENCH) {
|
||||
sid = getMoenchDacId();
|
||||
}
|
||||
myDet->setDAC(static_cast<slsDetectorDefs::dacIndex>(sid), -100, false);
|
||||
} CATCH_DISPLAY ("Could not power off dac " + to_string(id) + ".", "ctbDac::setOn")
|
||||
}
|
||||
getValue();
|
||||
}
|
||||
|
||||
int ctbDac::getValue() {
|
||||
try {
|
||||
int sid = id;
|
||||
if (myDet->getDetectorType().squash() == slsDetectorDefs::MOENCH) {
|
||||
sid = getMoenchDacId();
|
||||
}
|
||||
int val = myDet->getDAC(static_cast<slsDetectorDefs::dacIndex>(sid), dacsUnit->IsOn()).tsquash("Different values");
|
||||
cout << "dac " << id << " " << val << endl;
|
||||
dacsValue->SetText(to_string(val).c_str());
|
||||
if (val >= 0) {
|
||||
dacsLabel->SetOn(kTRUE);
|
||||
} else {
|
||||
dacsLabel->SetOn(kFALSE);
|
||||
}
|
||||
return val;
|
||||
} CATCH_DISPLAY ("Could not get dac " + to_string(id) + ".", "ctbDac::getValue")
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
ctbDacs::ctbDacs(TGVerticalFrame *page, sls::Detector *det) : TGGroupFrame(page,"DACs",kVerticalFrame) , myDet(det){
|
||||
|
||||
SetTitlePos(TGGroupFrame::kLeft);
|
||||
page->AddFrame(this,new TGLayoutHints( kLHintsTop | kLHintsExpandX , 10,10,10,10));
|
||||
MapWindow();
|
||||
|
||||
// cout << "window mapped " << endl;
|
||||
|
||||
for (int idac=0; idac<NDACS; idac++) {
|
||||
|
||||
dacs[idac]=new ctbDac(this, idac, myDet);
|
||||
|
||||
}
|
||||
dacs[NDACS]=new ctbDac(this, slsDetectorDefs::ADC_VPP, myDet);
|
||||
dacs[NDACS+1]=new ctbDac(this, slsDetectorDefs::HIGH_VOLTAGE, myDet);
|
||||
dacs[NDACS]->setLabel((char*)"ADC Vpp",2);
|
||||
dacs[NDACS+1]->setLabel((char*)"High Voltage",3);
|
||||
}
|
||||
|
||||
|
||||
int ctbDacs::setDacAlias(string line) {
|
||||
int is=-1, mv=0;
|
||||
char tit[100];
|
||||
int narg=sscanf(line.c_str(),"DAC%d %s %d",&is,tit,&mv);
|
||||
if (narg<2)
|
||||
return -1;
|
||||
if (is>=0 && is<NDACS)
|
||||
dacs[is]->setLabel(tit,mv);
|
||||
return is;
|
||||
|
||||
}
|
||||
|
||||
string ctbDacs::getDacAlias() {
|
||||
ostringstream line;
|
||||
|
||||
for (int i=0; i<NDACS; i++)
|
||||
line << dacs[i]->getLabel() << endl;
|
||||
return line.str();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
string ctbDacs::getDacParameters() {
|
||||
ostringstream line;
|
||||
|
||||
for (int i=0; i<NDACS; i++) {
|
||||
//line << "dacs:" << i << " " << dacs[i]->getValue << endl;
|
||||
line << "dac:" << i << " " << dacs[i]->getValue() << endl;
|
||||
}
|
||||
return line.str();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ctbDacs::update() {
|
||||
for (int idac=0; idac<NDACS+1; idac++) {
|
||||
dacs[idac]->getValue();
|
||||
}
|
||||
}
|
@ -1,77 +0,0 @@
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-other
|
||||
// Copyright (C) 2021 Contributors to the SLS Detector Package
|
||||
|
||||
|
||||
#ifndef CTBDACS_H
|
||||
#define CTBDACS_H
|
||||
#include <TGFrame.h>
|
||||
|
||||
|
||||
#define NDACS 18
|
||||
//#define NDACS 16
|
||||
|
||||
|
||||
class TGTextEntry;
|
||||
class TGLabel;
|
||||
class TGNumberEntry;
|
||||
class TGCheckButton;
|
||||
|
||||
|
||||
namespace sls
|
||||
{
|
||||
class Detector;
|
||||
};
|
||||
|
||||
#include <string>
|
||||
using namespace std;
|
||||
|
||||
|
||||
class ctbDac : public TGHorizontalFrame {
|
||||
|
||||
|
||||
protected:
|
||||
// TGLabel *dacsLabel;
|
||||
TGNumberEntry *dacsEntry;
|
||||
TGCheckButton *dacsUnit;
|
||||
TGCheckButton *dacsLabel;
|
||||
TGLabel *dacsValue;
|
||||
int id;
|
||||
|
||||
sls::Detector* myDet;
|
||||
public:
|
||||
ctbDac(TGGroupFrame*, int , sls::Detector*);
|
||||
void setValue();
|
||||
void setValue(Long_t);
|
||||
int getValue();
|
||||
void setOn(Bool_t);
|
||||
|
||||
int setLabel(char *tit, int mv);
|
||||
string getLabel();
|
||||
int getMoenchDacId();
|
||||
|
||||
|
||||
ClassDef(ctbDac,0)
|
||||
};
|
||||
|
||||
class ctbDacs : public TGGroupFrame {
|
||||
private:
|
||||
|
||||
ctbDac *dacs[NDACS+2];
|
||||
|
||||
sls::Detector* myDet;
|
||||
|
||||
public:
|
||||
ctbDacs(TGVerticalFrame *page, sls::Detector*);
|
||||
|
||||
int setDacAlias(string line);
|
||||
// int setDacAlias(string line);
|
||||
string getDacAlias();
|
||||
string getDacParameters();
|
||||
|
||||
void update();
|
||||
|
||||
ClassDef(ctbDacs,0)
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -1,86 +0,0 @@
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-other
|
||||
// Copyright (C) 2021 Contributors to the SLS Detector Package
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <chrono>
|
||||
|
||||
//#include "sls/sls_detector_exceptions.h"
|
||||
//#include "sls/ansi.h"
|
||||
#define RED "\x1b[31m"
|
||||
#define RESET "\x1b[0m"
|
||||
#define BOLD "\x1b[1m"
|
||||
#define cprintf(code, format, ...) printf(code format RESET, ##__VA_ARGS__)
|
||||
|
||||
|
||||
#define CATCH_DISPLAY(m, s) catch(...) { ctbDefs::DisplayExceptions(m, s); }
|
||||
#define CATCH_HANDLE(...) catch(...) { ctbDefs::HandleExceptions(__VA_ARGS__); }
|
||||
|
||||
class ctbDefs {
|
||||
public:
|
||||
/**
|
||||
* Empty Constructor
|
||||
*/
|
||||
ctbDefs(){};
|
||||
|
||||
// convert double seconds to chrono ns
|
||||
static std::chrono::nanoseconds ConvertDoubleStoChronoNS(double timeS) {
|
||||
using std::chrono::duration;
|
||||
using std::chrono::duration_cast;
|
||||
using std::chrono::nanoseconds;
|
||||
return duration_cast<nanoseconds>(duration<double>(timeS));
|
||||
}
|
||||
|
||||
// convert chrono ns to doubel s
|
||||
static double ConvertChronoNStoDoubleS(std::chrono::nanoseconds timeNs) {
|
||||
using std::chrono::duration;
|
||||
using std::chrono::duration_cast;
|
||||
return duration_cast<duration<double>>(timeNs).count();
|
||||
}
|
||||
|
||||
static void DisplayExceptions(std::string emsg, std::string src) {
|
||||
try {
|
||||
throw;
|
||||
} /* catch (const sls::SocketError &e) {
|
||||
throw;
|
||||
} catch (const sls::SharedMemoryError &e) {
|
||||
throw;
|
||||
} */catch (const std::exception &e) {
|
||||
ExceptionMessage(emsg, e.what(), src);
|
||||
}
|
||||
};
|
||||
|
||||
template <class CT> struct NonDeduced { using type = CT; };
|
||||
template <class S, typename RT, typename... CT>
|
||||
static void HandleExceptions(const std::string emsg, const std::string src, S* s,
|
||||
RT (S::*somefunc)(CT...),
|
||||
typename NonDeduced<CT>::type... Args) {
|
||||
try {
|
||||
throw;
|
||||
} /*catch (const sls::SocketError &e) {
|
||||
throw;
|
||||
} catch (const sls::SharedMemoryError &e) {
|
||||
throw;
|
||||
} */catch (const std::exception &e) {
|
||||
|
||||
ExceptionMessage(emsg, e.what(), src);
|
||||
(s->*somefunc)(Args...);
|
||||
}
|
||||
};
|
||||
|
||||
static void ExceptionMessage(std::string message,
|
||||
std::string exceptionMessage,
|
||||
std::string source) {
|
||||
// because sls_detector_exceptions cannot be included
|
||||
if (exceptionMessage.find("hared memory") != std::string::npos) {
|
||||
throw;
|
||||
}
|
||||
if (exceptionMessage.find("annot connect") != std::string::npos) {
|
||||
throw;
|
||||
}
|
||||
cprintf(RED, "Warning (%s): %s [Caught Exception: %s]\n", source.c_str(), message.c_str(), exceptionMessage.c_str());
|
||||
//return Message(qDefs::WARNING, message + std::string("\nCaught exception:\n") + exceptionMessage, source);
|
||||
};
|
||||
|
||||
};
|
@ -1,159 +0,0 @@
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-other
|
||||
// Copyright (C) 2021 Contributors to the SLS Detector Package
|
||||
#include <TApplication.h>
|
||||
#include <TColor.h>
|
||||
|
||||
#include <TStyle.h>
|
||||
#include <TROOT.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
|
||||
#include "sls/Detector.h"
|
||||
#include "sls/sls_detector_defs.h"
|
||||
//#include "sls_receiver_defs.h"
|
||||
#include "ctbMain.h"
|
||||
#include "ctbDefs.h"
|
||||
using namespace std;
|
||||
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
||||
|
||||
string afname, cfname, pfname;
|
||||
int id=0;
|
||||
|
||||
int af=0, cf=0, pf=0;
|
||||
|
||||
|
||||
cout << " *** " << argc << endl;
|
||||
for (int ia=0; ia<argc; ia++) {
|
||||
if (strcmp(argv[ia],"-alias")==0) {
|
||||
if (ia+1<argc) {
|
||||
afname=argv[ia+1];
|
||||
ia++;
|
||||
af=1;
|
||||
}
|
||||
|
||||
} else if (strcmp(argv[ia],"-config")==0) {
|
||||
if (ia+1<argc) {
|
||||
cfname=argv[ia+1];
|
||||
ia++;
|
||||
cf=1;
|
||||
}
|
||||
|
||||
|
||||
} else if (strcmp(argv[ia],"-par")==0) {
|
||||
if (ia+1<argc) {
|
||||
pfname=argv[ia+1];
|
||||
ia++;
|
||||
pf=1;
|
||||
}
|
||||
|
||||
|
||||
} else if (strcmp(argv[ia],"-id")==0) {
|
||||
if (ia+1<argc) {
|
||||
id=atoi(argv[ia+1]);
|
||||
ia++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
cout << " *** " << endl;
|
||||
sls::Detector *myDet = nullptr;
|
||||
try {
|
||||
/****** Create detector ****************/
|
||||
myDet=new sls::Detector(id);
|
||||
cout << "Created multi detector id " << id << endl;
|
||||
|
||||
if (cf) {
|
||||
myDet->loadConfig(cfname);
|
||||
cout << "Config file loaded successfully" << endl;
|
||||
} else {
|
||||
cout << "No config file specified" << endl;
|
||||
}
|
||||
cout << "hostname " << myDet->getHostname() << endl;
|
||||
|
||||
if (pf) {
|
||||
myDet->loadParameters(pfname);
|
||||
cout << "Loaded parameter file successfully" << endl;
|
||||
} else{
|
||||
cout << "No parameter file specified" << endl;
|
||||
}
|
||||
} CATCH_DISPLAY ("Could not create detector/ load config/parameters.", "ctbGui::main")
|
||||
|
||||
/***********Create GUI stuff *******************/
|
||||
TApplication theApp("App",&argc,argv);
|
||||
|
||||
|
||||
gStyle->SetDrawBorder(0);
|
||||
gStyle->SetCanvasColor(kWhite);
|
||||
gStyle->SetCanvasDefH(800);
|
||||
gStyle->SetCanvasDefW(800);
|
||||
gStyle->SetCanvasBorderMode(0);
|
||||
gStyle->SetPadBorderMode(0);
|
||||
gStyle->SetPaintTextFormat("5.2f");
|
||||
gStyle->SetLineWidth(2);
|
||||
gStyle->SetTextSize(1.1);
|
||||
gStyle->SetLabelSize(0.04,"xy");
|
||||
gStyle->SetTitleSize(0.05,"xy");
|
||||
gStyle->SetTitleOffset(1.0,"x");
|
||||
gStyle->SetTitleOffset(1.1,"y");
|
||||
gStyle->SetPadTopMargin(0.15);
|
||||
gStyle->SetPadRightMargin(0.15);
|
||||
gStyle->SetPadBottomMargin(0.15);
|
||||
gStyle->SetPadLeftMargin(0.15);
|
||||
gStyle->SetLegendBorderSize(1);
|
||||
gStyle->SetFrameBorderMode(0);
|
||||
gStyle->SetFrameFillColor(kWhite);
|
||||
// gStyle->SetLegendFillColor(kWhite);
|
||||
gStyle->SetTitleFillColor(kWhite);
|
||||
gStyle->SetFillColor(kWhite);
|
||||
gStyle->SetStatFontSize(0.03);
|
||||
gStyle->SetStatBorderSize(1);
|
||||
gStyle->SetStatFormat("6.4g");
|
||||
gStyle->SetStatX(0.95);
|
||||
gStyle->SetStatY(0.95);
|
||||
gStyle->SetStatW(0.2);
|
||||
gStyle->SetStatH(0.2);
|
||||
gStyle->SetTitleX(0.1);
|
||||
gStyle->SetTitleY(0.95);
|
||||
gStyle->SetTitleBorderSize(0);
|
||||
gStyle->SetTitleFontSize(0.05);
|
||||
gROOT->SetStyle("Default");
|
||||
|
||||
|
||||
TColor::InitializeColors();
|
||||
const Int_t NRGBs = 5;
|
||||
const Int_t NCont = 90;
|
||||
|
||||
Double_t stops[NRGBs] = { 0.00, 0.34, 0.61, 0.84, 1.00 };
|
||||
Double_t red[NRGBs] = { 0.00, 0.00, 0.87, 1.00, 0.51 };
|
||||
Double_t green[NRGBs] = { 0.00, 0.81, 1.00, 0.20, 0.00 };
|
||||
Double_t blue[NRGBs] = { 0.51, 1.00, 0.12, 0.00, 0.00 };
|
||||
TColor::CreateGradientColorTable(NRGBs, stops, red, green, blue, NCont);
|
||||
gStyle->SetNumberContours(NCont);
|
||||
|
||||
|
||||
gROOT->ForceStyle();
|
||||
ctbMain *mf=new ctbMain(gClient->GetRoot(), myDet);
|
||||
|
||||
cout << " *** " << argc << endl;
|
||||
for (int ia=0; ia<argc; ia++)
|
||||
cout << argv[ia] << endl;
|
||||
|
||||
|
||||
cout << " *** " << endl;
|
||||
|
||||
if (af)
|
||||
mf->loadAlias(afname);
|
||||
else
|
||||
cout << "no alias specified" << endl;
|
||||
|
||||
theApp.Run();
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-other
|
||||
// Copyright (C) 2021 Contributors to the SLS Detector Package
|
||||
#pragma link C++ class ctbMain;
|
||||
#pragma link C++ class ctbDacs;
|
||||
#pragma link C++ class ctbDac;
|
||||
#pragma link C++ class ctbSignals;
|
||||
#pragma link C++ class ctbSignal;
|
||||
#pragma link C++ class ctbAdc;
|
||||
#pragma link C++ class ctbAdcs;
|
||||
#pragma link C++ class ctbLoop;
|
||||
#pragma link C++ class ctbWait;
|
||||
#pragma link C++ class ctbPattern;
|
||||
#pragma link C++ class ctbAcquisition;
|
||||
#pragma link C++ class ctbPower;
|
||||
#pragma link C++ class ctbPowers;
|
||||
#pragma link C++ class ctbSlowAdc;
|
||||
#pragma link C++ class ctbSlowAdcs;
|
@ -1,588 +0,0 @@
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-other
|
||||
// Copyright (C) 2021 Contributors to the SLS Detector Package
|
||||
#include <TApplication.h>
|
||||
#include <TGClient.h>
|
||||
#include <TCanvas.h>
|
||||
#include <TF1.h>
|
||||
#include <TRandom.h>
|
||||
#include <TGButton.h>
|
||||
#include <TRootEmbeddedCanvas.h>
|
||||
#include <TGButtonGroup.h>
|
||||
#include <TGNumberEntry.h>
|
||||
#include <TGLabel.h>
|
||||
#include <TList.h>
|
||||
#include <TGFileDialog.h>
|
||||
#include <TGComboBox.h>
|
||||
#include <TH2F.h>
|
||||
#include <TColor.h>
|
||||
#include <TH1F.h>
|
||||
#include <TGraphErrors.h>
|
||||
#include <THStack.h>
|
||||
#include <TGTab.h>
|
||||
#include <TApplication.h>
|
||||
#include <TGCanvas.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <TGMenu.h>
|
||||
#include <TGDockableFrame.h>
|
||||
//#include <TGMenuBar.h>
|
||||
//#include <TGPopupMenu.h>
|
||||
|
||||
|
||||
|
||||
|
||||
#include <stdio.h>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
|
||||
#include "sls/Detector.h"
|
||||
#include "ctbDefs.h"
|
||||
#include "ctbMain.h"
|
||||
#include "ctbDacs.h"
|
||||
#include "ctbSlowAdcs.h"
|
||||
#include "ctbPowers.h"
|
||||
#include "ctbSignals.h"
|
||||
#include "ctbPattern.h"
|
||||
#include "ctbAdcs.h"
|
||||
#include "ctbAcquisition.h"
|
||||
//#include "ctbActions.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
|
||||
ctbMain::ctbMain(const TGWindow *p, sls::Detector *det)
|
||||
: TGMainFrame(p,800,800), pwrs(NULL), senses(NULL) {
|
||||
|
||||
myDet=det;
|
||||
|
||||
Connect("CloseWindow()", "ctbMain", this, "CloseWindow()");
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// fMenuDock = new TGDockableFrame(this);
|
||||
// AddFrame(fMenuDock, new TGLayoutHints(kLHintsExpandX, 0, 0, 1, 0));
|
||||
// fMenuDock->SetWindowName("GuiTest Menu");
|
||||
|
||||
fMenuBarLayout = new TGLayoutHints(kLHintsTop | kLHintsExpandX);
|
||||
fMenuBarItemLayout = new TGLayoutHints(kLHintsTop | kLHintsLeft, 0, 4, 0, 0);
|
||||
fMenuBarHelpLayout = new TGLayoutHints(kLHintsTop | kLHintsRight);
|
||||
|
||||
fMenuFile = new TGPopupMenu(gClient->GetRoot());
|
||||
int im=0;
|
||||
|
||||
fMenuFile->AddEntry("Open Alias", im++);
|
||||
fMenuFile->AddEntry("Save Alias", im++);
|
||||
fMenuFile->AddSeparator();
|
||||
fMenuFile->AddEntry("Open Parameters", im++);
|
||||
fMenuFile->AddEntry("Save Parameters", im++);
|
||||
fMenuFile->AddSeparator();
|
||||
fMenuFile->AddEntry("Open Configuration", im++);
|
||||
fMenuFile->AddEntry("Save Configuration", im++);
|
||||
fMenuFile->AddSeparator();
|
||||
fMenuFile->AddEntry("Open Pattern", im++);
|
||||
fMenuFile->AddEntry("Save Pattern", im++);
|
||||
fMenuFile->AddSeparator();
|
||||
fMenuFile->AddEntry("Exit", im++);
|
||||
|
||||
fMenuFile->Connect("Activated(Int_t)", "ctbMain", this,
|
||||
"HandleMenu(Int_t)");
|
||||
|
||||
|
||||
i_dacs=-1;
|
||||
i_pwrs=-1;
|
||||
i_senses=-1;
|
||||
i_sig=-1;
|
||||
i_adcs=-1;
|
||||
i_pat=-1;
|
||||
i_acq=-1;
|
||||
|
||||
int i_page=0;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
TGVerticalFrame *vframe=new TGVerticalFrame(this, 800,1200); //main frame
|
||||
|
||||
|
||||
|
||||
fMenuBar = new TGMenuBar(vframe, 1, 1, kHorizontalFrame);
|
||||
fMenuBar->AddPopup("&File", fMenuFile, fMenuBarItemLayout);
|
||||
// fMenuBar->AddPopup("&Test", fMenuTest, fMenuBarItemLayout);
|
||||
// fMenuBar->AddPopup("&View", fMenuView, fMenuBarItemLayout);
|
||||
// fMenuBar->AddPopup("&Help", fMenuHelp, fMenuBarHelpLayout);
|
||||
|
||||
vframe->AddFrame(fMenuBar, fMenuBarLayout);
|
||||
|
||||
TGHorizontalFrame* hpage=new TGHorizontalFrame(vframe, 800,1200); //horizontal frame. Inside there should be the tab and the canvas
|
||||
mtab=new TGTab(hpage, 1500, 1200); //tab!
|
||||
// page=new TGVerticalFrame(mtab, 1500,1200);
|
||||
|
||||
cout << "DACS" << endl;
|
||||
|
||||
TGCompositeFrame *tf = mtab->AddTab("DACs");
|
||||
TGVerticalFrame *page=new TGVerticalFrame(tf, 1500,1200);
|
||||
tf->AddFrame(page, new TGLayoutHints(kLHintsExpandX | kLHintsExpandY, 10,10,10,1));
|
||||
dacs=new ctbDacs(page, myDet);
|
||||
i_dacs=i_page++;
|
||||
|
||||
|
||||
cout << "power " << endl;
|
||||
tf = mtab->AddTab("Power Supplies");
|
||||
page=new TGVerticalFrame(tf, 1500,1200);
|
||||
tf->AddFrame(page, new TGLayoutHints(kLHintsExpandX | kLHintsExpandY, 10,10,10,1));
|
||||
pwrs=new ctbPowers(page, myDet);
|
||||
|
||||
i_pwrs=i_page++;
|
||||
|
||||
cout << "sense " << endl;
|
||||
tf = mtab->AddTab("Sense");
|
||||
page=new TGVerticalFrame(tf, 1500,1200);
|
||||
tf->AddFrame(page, new TGLayoutHints(kLHintsExpandX | kLHintsExpandY, 10,10,10,1));
|
||||
senses=new ctbSlowAdcs(page, myDet);
|
||||
|
||||
i_senses=i_page++;
|
||||
|
||||
|
||||
|
||||
cout << "signals " << endl;
|
||||
tf = mtab->AddTab("Signals");
|
||||
page=new TGVerticalFrame(tf, 1500,1200);
|
||||
tf->AddFrame(page, new TGLayoutHints(kLHintsExpandX | kLHintsExpandY, 10,10,10,1));
|
||||
sig=new ctbSignals(page, myDet);
|
||||
sig->Connect("ToggledSignalPlot(Int_t)","ctbMain",this,"setSignalPlot(Int_t)");
|
||||
|
||||
i_sig=i_page++;
|
||||
|
||||
cout << "adcs " << endl;
|
||||
tf = mtab->AddTab("ADCs");
|
||||
page=new TGVerticalFrame(tf, 1500,1200);
|
||||
tf->AddFrame(page, new TGLayoutHints(kLHintsExpandX | kLHintsExpandY, 10,10,10,1));
|
||||
adcs=new ctbAdcs(page, myDet);
|
||||
adcs->Connect("ToggledAdcPlot(Int_t)","ctbMain",this,"setADCPlot(Int_t)");
|
||||
adcs->Connect("AdcEnable(Int_t)","ctbMain",this,"setADCEnable(Int_t)");
|
||||
i_adcs=i_page++;
|
||||
|
||||
|
||||
cout << "pattern" << endl;
|
||||
|
||||
tf = mtab->AddTab("Pattern");
|
||||
page=new TGVerticalFrame(tf, 1500,1200);
|
||||
tf->AddFrame(page, new TGLayoutHints(kLHintsExpandX | kLHintsExpandY, 10,10,10,1));
|
||||
pat=new ctbPattern(page, myDet);
|
||||
pat->Connect("patternFileChanged(const char*)","ctbMain",this,"setPatternFile(const char*)");
|
||||
pat->Connect("patternCompilerChanged(const char*)","ctbMain",this,"setPatternCompiler(const char*)");
|
||||
pat->Connect("analogSamplesChanged(const int)","ctbMain",this,"setAnalogSamples(int)");
|
||||
pat->Connect("digitalSamplesChanged(const int)","ctbMain",this,"setDigitalSamples(int)");
|
||||
pat->Connect("readoutModeChanged(int)","ctbMain",this,"setReadoutMode(int)");
|
||||
|
||||
i_pat=i_page++;
|
||||
|
||||
cout << "acquisition" << endl;
|
||||
|
||||
tf = mtab->AddTab("Acquisition");
|
||||
page=new TGVerticalFrame(tf, 1500,1200);
|
||||
tf->AddFrame(page, new TGLayoutHints(kLHintsExpandX | kLHintsExpandY, 10,10,10,1));
|
||||
acq=new ctbAcquisition(page, myDet);
|
||||
|
||||
|
||||
i_acq=i_page++;
|
||||
|
||||
|
||||
// cout << "actions" << endl;
|
||||
// tf = mtab->AddTab("Actions");
|
||||
// page=new TGVerticalFrame(tf, 1500,1200);
|
||||
// tf->AddFrame(page, new TGLayoutHints(kLHintsExpandX | kLHintsExpandY, 10,10,10,1));
|
||||
// actions=new ctbActions(page, myDet);
|
||||
|
||||
|
||||
// i_actions=i_page++;
|
||||
|
||||
|
||||
|
||||
cout << "tabs finished" << endl;
|
||||
|
||||
hpage->AddFrame(mtab,new TGLayoutHints(kLHintsExpandX | kLHintsExpandY, 10,10,10,1));
|
||||
|
||||
vframe->AddFrame(hpage,new TGLayoutHints(kLHintsExpandX | kLHintsExpandY, 10,10,10,1));
|
||||
|
||||
AddFrame(vframe,new TGLayoutHints(kLHintsExpandX | kLHintsExpandY, 10,10,10,1));
|
||||
vframe->MapWindow();
|
||||
hpage->MapWindow();
|
||||
mtab->MapWindow();
|
||||
page->MapWindow();
|
||||
|
||||
// Sets window name and shows the main frame
|
||||
cout << "dockabel" << endl;
|
||||
TGDockableFrame *fdock=new TGDockableFrame(hpage);
|
||||
hpage->AddFrame(fdock, new TGLayoutHints(kLHintsBottom | kLHintsCenterX | kLHintsExpandX | kLHintsExpandY, 10,10,10,10));
|
||||
fdock->MapWindow();
|
||||
|
||||
cout << "canvas" << endl;
|
||||
// // Creates widgets of the example
|
||||
|
||||
|
||||
fEcanvas = new TRootEmbeddedCanvas ("Ecanvas",fdock,800,800);//hpage,800,800);
|
||||
//fEcanvas = new TRootEmbeddedCanvas ("Ecanvas",this,800,800);//hpage,800,800);
|
||||
// fEcanvas->Resize();
|
||||
// fEcanvas->GetCanvas()->Update();
|
||||
//AddFrame(fEcanvas, new TGLayoutHints(kLHintsBottom | kLHintsCenterX | kLHintsExpandX | kLHintsExpandY, 10,10,10,10));
|
||||
|
||||
// // hpage->
|
||||
fdock->AddFrame(fEcanvas, new TGLayoutHints(kLHintsBottom | kLHintsCenterX | kLHintsExpandX | kLHintsExpandY, 10,10,10,10));
|
||||
|
||||
|
||||
fEcanvas->MapWindow();
|
||||
|
||||
acq->setCanvas(getCanvas());
|
||||
|
||||
|
||||
|
||||
hpage->MapSubwindows();
|
||||
mtab->Connect("Selected(Int_t)","ctbMain",this,"tabSelected(Int_t)");
|
||||
|
||||
|
||||
|
||||
cout << "connect mtab" << endl;
|
||||
|
||||
try{
|
||||
setReadoutMode(pat->getReadoutMode());
|
||||
} CATCH_DISPLAY ("Could not get readout flags", "ctbPattern::getReadoutMode")
|
||||
|
||||
setADCEnable(adcs->setEnable());
|
||||
setAnalogSamples(pat->getAnalogSamples());
|
||||
setDigitalSamples(pat->getDigitalSamples());
|
||||
|
||||
tabSelected(0);
|
||||
|
||||
SetWindowName("CTB Gui");
|
||||
MapSubwindows();
|
||||
Resize(1500,1200);
|
||||
|
||||
MapWindow();
|
||||
}
|
||||
|
||||
void ctbMain::CloseWindow() {
|
||||
gApplication->Terminate();
|
||||
}
|
||||
|
||||
TCanvas* ctbMain::getCanvas() {
|
||||
return fEcanvas->GetCanvas();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ctbMain::HandleMenu(Int_t id)
|
||||
{
|
||||
// Handle menu items.
|
||||
|
||||
|
||||
|
||||
|
||||
switch (id) {
|
||||
|
||||
case 0: // fMenuFile->AddEntry("Open Alias", im++);
|
||||
cout << "Open Alias" << endl;
|
||||
{
|
||||
static TString dir(".");
|
||||
TGFileInfo fi;
|
||||
//fi.fFileTypes = filetypes;
|
||||
fi.fIniDir = StrDup(dir);
|
||||
printf("fIniDir = %s\n", fi.fIniDir);
|
||||
new TGFileDialog(gClient->GetRoot(), this, kFDOpen, &fi);
|
||||
printf("Open file: %s (dir: %s)\n", fi.fFilename, fi.fIniDir);
|
||||
// dir = fi.fIniDir;
|
||||
if (fi.fFilename)
|
||||
loadAlias(fi.fFilename);
|
||||
}
|
||||
break;
|
||||
|
||||
case 1: // fMenuFile->AddEntry("Save Alias", im++);
|
||||
cout << "Save Alias" << endl;
|
||||
{
|
||||
static TString dir(".");
|
||||
TGFileInfo fi;
|
||||
//fi.fFileTypes = filetypes;
|
||||
fi.fIniDir = StrDup(dir);
|
||||
printf("fIniDir = %s\n", fi.fIniDir);
|
||||
new TGFileDialog(gClient->GetRoot(), this, kFDSave, &fi);
|
||||
printf("Save file: %s (dir: %s)\n", fi.fFilename, fi.fIniDir);
|
||||
// dir = fi.fIniDir;
|
||||
if (fi.fFilename)
|
||||
saveAlias(fi.fFilename);
|
||||
}
|
||||
break;
|
||||
case 2: //fMenuFile->AddEntry("Open Parameters", im++);
|
||||
cout << "Open Parameters" << endl;
|
||||
{
|
||||
static TString dir(".");
|
||||
TGFileInfo fi;
|
||||
//fi.fFileTypes = filetypes;
|
||||
fi.fIniDir = StrDup(dir);
|
||||
printf("fIniDir = %s\n", fi.fIniDir);
|
||||
new TGFileDialog(gClient->GetRoot(), this, kFDOpen, &fi);
|
||||
printf("Open file: %s (dir: %s)\n", fi.fFilename, fi.fIniDir);
|
||||
// dir = fi.fIniDir;
|
||||
if (fi.fFilename)
|
||||
loadParameters(fi.fFilename);
|
||||
}
|
||||
break;
|
||||
|
||||
case 3: // fMenuFile->AddEntry("Open Configuration", im++);
|
||||
cout << "Open configuration" << endl;
|
||||
{
|
||||
static TString dir(".");
|
||||
TGFileInfo fi;
|
||||
//fi.fFileTypes = filetypes;
|
||||
fi.fIniDir = StrDup(dir);
|
||||
printf("fIniDir = %s\n", fi.fIniDir);
|
||||
new TGFileDialog(gClient->GetRoot(), this, kFDOpen, &fi);
|
||||
printf("Open file: %s (dir: %s)\n", fi.fFilename, fi.fIniDir);
|
||||
// dir = fi.fIniDir;
|
||||
if (fi.fFilename)
|
||||
loadConfiguration(fi.fFilename);
|
||||
}
|
||||
break;
|
||||
|
||||
case 4: //fMenuFile->AddEntry("Open Pattern", im++);
|
||||
cout << "Open pattern" << endl;
|
||||
{
|
||||
static TString dir(".");
|
||||
TGFileInfo fi;
|
||||
//fi.fFileTypes = filetypes;
|
||||
fi.fIniDir = StrDup(dir);
|
||||
printf("fIniDir = %s\n", fi.fIniDir);
|
||||
new TGFileDialog(gClient->GetRoot(), this, kFDOpen, &fi);
|
||||
printf("Open file: %s (dir: %s)\n", fi.fFilename, fi.fIniDir);
|
||||
// dir = fi.fIniDir;
|
||||
if (fi.fFilename)
|
||||
loadParameters(fi.fFilename);
|
||||
}
|
||||
break;
|
||||
|
||||
case 5: //fMenuFile->AddEntry("Save Pattern", im++);
|
||||
cout << "Save pattern" << endl;
|
||||
{
|
||||
static TString dir(".");
|
||||
TGFileInfo fi;
|
||||
//fi.fFileTypes = filetypes;
|
||||
fi.fIniDir = StrDup(dir);
|
||||
printf("fIniDir = %s\n", fi.fIniDir);
|
||||
new TGFileDialog(gClient->GetRoot(), this, kFDSave, &fi);
|
||||
printf("Open file: %s (dir: %s)\n", fi.fFilename, fi.fIniDir);
|
||||
// dir = fi.fIniDir;
|
||||
if (fi.fFilename)
|
||||
savePattern(fi.fFilename);
|
||||
}
|
||||
break;
|
||||
|
||||
case 6: // fMenuFile->AddEntry("Exit", im++);
|
||||
CloseWindow();
|
||||
|
||||
default:
|
||||
printf("Menu item %d selected\n", id);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
int ctbMain::setADCPlot(Int_t i) {
|
||||
|
||||
// cout << "ADC " << i << " plot or color toggled" << endl;
|
||||
// acq->setGraph(i,adcs->getGraph(i));
|
||||
acq->setGraph(i,adcs->getEnabled(i),adcs->getColor(i));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
int ctbMain::setSignalPlot(Int_t i) {
|
||||
|
||||
// cout << "ADC " << i << " plot or color toggled" << endl;
|
||||
// acq->setGraph(i,adcs->getGraph(i));
|
||||
acq->setBitGraph(i,sig->getPlot(i),sig->getColor(i));
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ctbMain::loadConfiguration(string fname) {
|
||||
try{
|
||||
myDet->loadConfig(fname);
|
||||
} CATCH_DISPLAY ("Could not load config.", "ctbMain::loadConfiguration")
|
||||
}
|
||||
|
||||
void ctbMain::loadParameters(string fname) {
|
||||
try{
|
||||
myDet->loadParameters(fname);
|
||||
} CATCH_DISPLAY ("Could not load parameters.", "ctbMain::loadParameters")
|
||||
}
|
||||
|
||||
void ctbMain::savePattern(string fname) {
|
||||
try{
|
||||
myDet->savePattern(fname);
|
||||
} CATCH_DISPLAY ("Could not save pattern.", "ctbMain::savePattern")
|
||||
}
|
||||
|
||||
|
||||
|
||||
int ctbMain::loadAlias(string fname) {
|
||||
|
||||
|
||||
string line;
|
||||
char aaaa[1000];
|
||||
int i;
|
||||
ifstream myfile (fname.c_str());
|
||||
if (myfile.is_open())
|
||||
{
|
||||
while ( getline (myfile,line) )
|
||||
{
|
||||
// cout << line ;
|
||||
if (sscanf(line.c_str(),"BIT%d",&i)>0) {
|
||||
//cout << "*******" << line<< endl;
|
||||
sig->setSignalAlias(line);
|
||||
// cout << line ;
|
||||
} else if (sscanf(line.c_str(),"DAC%d",&i)>0) {
|
||||
dacs->setDacAlias(line);
|
||||
// cout << "+++++++++" << line<< endl;
|
||||
} else if (sscanf(line.c_str(),"ADC%d",&i)>0) {
|
||||
adcs->setAdcAlias(line);
|
||||
// cout << "---------" << line<< endl;
|
||||
} // else
|
||||
// cout << "<<<<<<<" << line << endl;
|
||||
else if (sscanf(line.c_str(),"PAT%s",aaaa)>0) {
|
||||
pat->setPatternAlias(line);
|
||||
// cout << "---------" << line<< endl;
|
||||
} else if (sscanf(line.c_str(),"V%s",aaaa)>0) {
|
||||
if (pwrs) pwrs->setPwrAlias(line);
|
||||
// cout << "+++++++++" << line<< endl;
|
||||
} else if (sscanf(line.c_str(),"SENSE%d",&i)>0) {
|
||||
if (senses) senses->setSlowAdcAlias(line);
|
||||
// cout << "+++++++++" << line<< endl;
|
||||
}
|
||||
|
||||
}
|
||||
myfile.close();
|
||||
}
|
||||
|
||||
else cout << "Unable to open file";
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
int ctbMain::saveAlias(string fname) {
|
||||
|
||||
|
||||
string line;
|
||||
ofstream myfile (fname.c_str());
|
||||
if (myfile.is_open())
|
||||
{
|
||||
//while ( getline (myfile,line) )
|
||||
// {
|
||||
// cout << line ;
|
||||
//if (sscanf(line.c_str(),"BIT%d",&i)>0) {
|
||||
//cout << "*******" << line<< endl;
|
||||
myfile << sig->getSignalAlias();
|
||||
// cout << line ;
|
||||
// } else if (sscanf(line.c_str(),"DAC%d",&i)>0) {
|
||||
myfile << dacs->getDacAlias();
|
||||
if (pwrs) myfile << pwrs->getPwrAlias();
|
||||
if (senses) myfile << senses->getSlowAdcAlias();
|
||||
// cout << "+++++++++" << line<< endl;
|
||||
// } else if (sscanf(line.c_str(),"ADC%d",&i)>0) {
|
||||
myfile << adcs->getAdcAlias();
|
||||
// cout << "---------" << line<< endl;
|
||||
// } // else
|
||||
// cout << "<<<<<<<" << line << endl;
|
||||
myfile << pat->getPatternAlias();
|
||||
|
||||
//}
|
||||
myfile.close();
|
||||
}
|
||||
|
||||
else cout << "Unable to open file";
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void ctbMain::tabSelected(Int_t i) {
|
||||
|
||||
// cout << "Selected tab " << i << endl;
|
||||
// cout << "Current tab is " << mtab->GetCurrent() << endl;
|
||||
|
||||
if (i==i_dacs) dacs->update();
|
||||
else if (i==i_pwrs) pwrs->update();
|
||||
else if (i==i_senses) ;//senses->update();
|
||||
else if (i==i_sig) sig->update();
|
||||
else if (i==i_adcs) adcs->update();
|
||||
else if (i==i_pat) pat->update();
|
||||
else if (i==i_acq) acq->update();
|
||||
else if (i==i_acq) acq->update();
|
||||
// else if (i==i_actions) actions->update();
|
||||
else cout << "Unknown tab " << i << endl;
|
||||
|
||||
|
||||
}
|
||||
|
||||
void ctbMain::setPatternFile(const char* t) {
|
||||
acq->setPatternFile(t);
|
||||
|
||||
}
|
||||
|
||||
void ctbMain::setPatternCompiler(const char* t) {
|
||||
acq->setPatternCompiler(t);
|
||||
|
||||
|
||||
}
|
||||
|
||||
void ctbMain::setAnalogSamples(const int n) {
|
||||
acq->setAnalogSamples(n);
|
||||
|
||||
|
||||
}
|
||||
|
||||
void ctbMain::setDigitalSamples(const int n) {
|
||||
acq->setDigitalSamples(n);
|
||||
|
||||
|
||||
}
|
||||
|
||||
void ctbMain::setReadoutMode(int flags) {
|
||||
acq->setReadoutMode(flags);
|
||||
}
|
||||
|
||||
void ctbMain::setADCEnable(Int_t reg){
|
||||
acq->setADCEnable(reg);
|
||||
}
|
130
ctbGui/ctbMain.h
130
ctbGui/ctbMain.h
@ -1,130 +0,0 @@
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-other
|
||||
// Copyright (C) 2021 Contributors to the SLS Detector Package
|
||||
#ifndef CTBMAIN_H
|
||||
#define CTBMAIN_H
|
||||
#include <TGFrame.h>
|
||||
|
||||
|
||||
class TRootEmbeddedCanvas;
|
||||
class TGButtonGroup;
|
||||
class TGVerticalFrame;
|
||||
class TGHorizontalFrame;
|
||||
class TGTextEntry;
|
||||
class TGLabel;
|
||||
class TGNumberEntry;
|
||||
class TH2F;
|
||||
class TGComboBox;
|
||||
class TGCheckButton;
|
||||
|
||||
class THStack;
|
||||
class TGraphErrors;
|
||||
class TGTextButton;
|
||||
class TGTab;
|
||||
|
||||
class TGMenuBar;
|
||||
class TGPopupMenu;
|
||||
class TGDockableFrame;
|
||||
class TGLayoutHints;
|
||||
class TGCanvas;
|
||||
class TCanvas;
|
||||
|
||||
class ctbDacs;
|
||||
class ctbSlowAdcs;
|
||||
class ctbPowers;
|
||||
|
||||
|
||||
class ctbSignals;
|
||||
|
||||
namespace sls
|
||||
{
|
||||
class Detector;
|
||||
};
|
||||
|
||||
class ctbPattern;
|
||||
class ctbAdcs;
|
||||
class ctbAcquisition;
|
||||
//class ctbActions;
|
||||
|
||||
#include <string>
|
||||
using namespace std;
|
||||
|
||||
class ctbMain : public TGMainFrame {
|
||||
private:
|
||||
|
||||
|
||||
sls::Detector *myDet;
|
||||
|
||||
|
||||
|
||||
TRootEmbeddedCanvas *fEcanvas;
|
||||
TRootEmbeddedCanvas *fModulecanvas;
|
||||
TGButtonGroup *br;
|
||||
|
||||
TGTab *mtab;
|
||||
|
||||
|
||||
ctbDacs *dacs;
|
||||
int i_dacs;
|
||||
|
||||
ctbPowers *pwrs;
|
||||
int i_pwrs;
|
||||
|
||||
ctbSlowAdcs *senses;
|
||||
int i_senses;
|
||||
|
||||
|
||||
ctbSignals *sig;
|
||||
int i_sig;
|
||||
|
||||
|
||||
ctbAdcs *adcs;
|
||||
int i_adcs;
|
||||
|
||||
|
||||
ctbPattern *pat;
|
||||
int i_pat;
|
||||
|
||||
ctbAcquisition *acq;
|
||||
int i_acq;
|
||||
|
||||
// ctbActions *actions;
|
||||
int i_actions;
|
||||
|
||||
TGDockableFrame *fMenuDock;
|
||||
|
||||
TGMenuBar *fMenuBar;
|
||||
TGPopupMenu *fMenuFile, *fMenuTest, *fMenuView, *fMenuHelp;
|
||||
TGPopupMenu *fCascadeMenu, *fCascade1Menu, *fCascade2Menu;
|
||||
TGPopupMenu *fMenuNew1, *fMenuNew2;
|
||||
TGLayoutHints *fMenuBarLayout, *fMenuBarItemLayout, *fMenuBarHelpLayout;
|
||||
TGCanvas *myCanvas;
|
||||
|
||||
|
||||
public:
|
||||
ctbMain(const TGWindow *p, sls::Detector *det);
|
||||
|
||||
|
||||
int loadAlias(string fname);
|
||||
int saveAlias(string fname);
|
||||
void loadParameters(string fname);
|
||||
void savePattern(string fname);
|
||||
void loadConfiguration(string fname);
|
||||
void tabSelected(Int_t);
|
||||
int setADCPlot(Int_t);
|
||||
int setSignalPlot(Int_t);
|
||||
void CloseWindow();
|
||||
|
||||
void setPatternFile(const char* t);
|
||||
|
||||
void setPatternCompiler(const char* t);
|
||||
void setAnalogSamples(const int);
|
||||
void setDigitalSamples(const int);
|
||||
void setReadoutMode(int);
|
||||
void setADCEnable(Int_t);
|
||||
|
||||
void HandleMenu(Int_t);
|
||||
TCanvas* getCanvas();
|
||||
ClassDef(ctbMain,0)
|
||||
};
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
@ -1,181 +0,0 @@
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-other
|
||||
// Copyright (C) 2021 Contributors to the SLS Detector Package
|
||||
#ifndef CTBPATTERN_H
|
||||
#define CTBPATTERN_H
|
||||
#include <TGFrame.h>
|
||||
|
||||
|
||||
#define NLOOPS 3
|
||||
#define NWAITS 3
|
||||
#define NADCS 32
|
||||
#define PATLEN 1024
|
||||
|
||||
class TRootEmbeddedCanvas;
|
||||
class TGButtonGroup;
|
||||
class TGVerticalFrame;
|
||||
class TGHorizontalFrame;
|
||||
class TGTextEntry;
|
||||
class TGLabel;
|
||||
class TGNumberEntry;
|
||||
class TH2F;
|
||||
class TGComboBox;
|
||||
class TGCheckButton;
|
||||
class TGTextEntry;
|
||||
class TGCheckButton;
|
||||
|
||||
class THStack;
|
||||
class TGraphErrors;
|
||||
class energyCalibration;
|
||||
class TGTextButton;
|
||||
class TGTab;
|
||||
|
||||
namespace sls
|
||||
{
|
||||
class Detector;
|
||||
};
|
||||
|
||||
|
||||
#include <string>
|
||||
using namespace std;
|
||||
|
||||
|
||||
|
||||
class ctbLoop : public TGHorizontalFrame {
|
||||
|
||||
|
||||
private:
|
||||
|
||||
TGNumberEntry *eLoopStartAddr;
|
||||
TGNumberEntry *eLoopStopAddr;
|
||||
TGNumberEntry *eLoopNumber;
|
||||
|
||||
int id;
|
||||
|
||||
sls::Detector *myDet;
|
||||
|
||||
public:
|
||||
ctbLoop(TGGroupFrame *page, int i,sls::Detector *det);
|
||||
|
||||
void setNLoops();
|
||||
void update();
|
||||
|
||||
ClassDef(ctbLoop,0)
|
||||
};
|
||||
|
||||
class ctbWait : public TGHorizontalFrame {
|
||||
|
||||
|
||||
private:
|
||||
|
||||
TGNumberEntry *eWaitAddr;
|
||||
TGNumberEntry *eWaitTime;
|
||||
|
||||
int id;
|
||||
|
||||
sls::Detector *myDet;
|
||||
|
||||
public:
|
||||
ctbWait(TGGroupFrame *page, int i,sls::Detector *det);
|
||||
|
||||
void setWaitTime();
|
||||
void update();
|
||||
|
||||
ClassDef(ctbWait,0)
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
class ctbPattern : public TGGroupFrame {
|
||||
private:
|
||||
|
||||
|
||||
TGNumberEntry *eAdcClkFreq;
|
||||
TGNumberEntry *eRunClkFreq;
|
||||
TGNumberEntry *eDBitClkFreq;
|
||||
TGNumberEntry *eAdcClkPhase;
|
||||
TGNumberEntry *eDBitClkPhase;
|
||||
//TGNumberEntry *eRunClkPhase;
|
||||
|
||||
TGNumberEntry *eStartAddr;
|
||||
TGNumberEntry *eStopAddr;
|
||||
TGNumberEntry *eFrames;
|
||||
TGNumberEntry *ePeriod;
|
||||
TGNumberEntry *eTriggers;
|
||||
// TGNumberEntry *eMeasurements;
|
||||
TGNumberEntry *eAdcPipeline;
|
||||
TGNumberEntry *eDBitPipeline;
|
||||
|
||||
ctbLoop *eLoop[NLOOPS];
|
||||
ctbWait *eWait[NWAITS];
|
||||
|
||||
TGTextEntry *patternCompiler;
|
||||
TGTextEntry *patternFile;
|
||||
|
||||
TGTextButton *browseCompiler;
|
||||
TGTextButton *browseFile;
|
||||
|
||||
|
||||
TGNumberEntry *eAnalogSamples;
|
||||
TGNumberEntry *eDigitalSamples;
|
||||
|
||||
TGCheckButton *cbAnalog;
|
||||
TGCheckButton *cbDigital;
|
||||
|
||||
char pat[PATLEN*8];
|
||||
|
||||
sls::Detector *myDet;
|
||||
|
||||
public:
|
||||
|
||||
ctbPattern(TGVerticalFrame *page, sls::Detector *det);
|
||||
|
||||
void update();
|
||||
void setAdcFreq();
|
||||
void setRunFreq();
|
||||
void setDBitFreq();
|
||||
void setAdcPhase();
|
||||
void setDBitPhase();
|
||||
// void setRunPhase();
|
||||
void setAdcPipeline();
|
||||
void setDBitPipeline();
|
||||
void setFrames();
|
||||
void setTriggers();
|
||||
// void setMeasurements();
|
||||
void setPeriod();
|
||||
|
||||
|
||||
void chooseCompiler();
|
||||
void choosePattern();
|
||||
|
||||
string getCompiler();
|
||||
string getPatternFile();
|
||||
|
||||
void setPatternAlias(string);
|
||||
string getPatternAlias();
|
||||
|
||||
|
||||
int getAnalogSamples();
|
||||
void setAnalogSamples();
|
||||
int getDigitalSamples();
|
||||
void setDigitalSamples();
|
||||
void setReadoutMode(Bool_t);
|
||||
int getReadoutMode();
|
||||
|
||||
|
||||
void setFile();
|
||||
void setCompiler();
|
||||
void patternFileChanged(const char*);
|
||||
void patternCompilerChanged(const char*);
|
||||
void analogSamplesChanged(const int t);
|
||||
void digitalSamplesChanged(const int t);
|
||||
void readoutModeChanged(int);
|
||||
|
||||
|
||||
ClassDef(ctbPattern,0)
|
||||
};
|
||||
|
||||
#endif
|
@ -1,225 +0,0 @@
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-other
|
||||
// Copyright (C) 2021 Contributors to the SLS Detector Package
|
||||
#include <TGFrame.h>
|
||||
|
||||
|
||||
#include <TGButtonGroup.h>
|
||||
#include <TGNumberEntry.h>
|
||||
#include <TGLabel.h>
|
||||
#include <TList.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
#include "ctbDefs.h"
|
||||
#include "ctbDacs.h"
|
||||
#include "ctbPowers.h"
|
||||
#include "sls/Detector.h"
|
||||
#include "sls/sls_detector_defs.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
|
||||
ctbPower::ctbPower(TGGroupFrame* f, int i, sls::Detector* d)
|
||||
: ctbDac(f, i, d)
|
||||
{
|
||||
cout << "****************************************************************power " << i << endl;
|
||||
dacsUnit->SetOn(kTRUE);
|
||||
dacsUnit->SetEnabled(kFALSE);
|
||||
|
||||
switch(i) {
|
||||
case slsDetectorDefs::V_POWER_IO:
|
||||
dacsLabel->SetText("VIO");
|
||||
break;
|
||||
case slsDetectorDefs::V_POWER_A:
|
||||
dacsLabel->SetText("VA");
|
||||
break;
|
||||
case slsDetectorDefs::V_POWER_B:
|
||||
dacsLabel->SetText("VB");
|
||||
break;
|
||||
case slsDetectorDefs::V_POWER_C:
|
||||
dacsLabel->SetText("VC");
|
||||
break;
|
||||
case slsDetectorDefs::V_POWER_D:
|
||||
dacsLabel->SetText("VD");
|
||||
break;
|
||||
case slsDetectorDefs::V_POWER_CHIP:
|
||||
dacsLabel->SetText("VCHIP");
|
||||
dacsLabel->SetEnabled(kFALSE);
|
||||
break;
|
||||
default:
|
||||
dacsLabel->SetText("Bad index");
|
||||
break;
|
||||
};
|
||||
|
||||
|
||||
TGTextEntry *e=dacsEntry->TGNumberEntry::GetNumberEntry();
|
||||
e->Disconnect ("ReturnPressed()");
|
||||
e->Disconnect ("ValueSet(Long_t)");
|
||||
|
||||
e->Connect("ReturnPressed()","ctbPower",this,"setValue()");
|
||||
dacsEntry->Connect("ValueSet(Long_t)","ctbPower",this,"setValue(Long_t)");
|
||||
};
|
||||
|
||||
|
||||
string ctbPower::getLabel() {
|
||||
|
||||
ostringstream line;
|
||||
switch (id) {
|
||||
case slsDetectorDefs::V_POWER_IO:
|
||||
line << "VIO";
|
||||
break;
|
||||
case slsDetectorDefs::V_POWER_A:
|
||||
line << "VA";
|
||||
break;
|
||||
case slsDetectorDefs::V_POWER_B:
|
||||
line << "VB";
|
||||
break;
|
||||
case slsDetectorDefs::V_POWER_C:
|
||||
line << "VC";
|
||||
break;
|
||||
case slsDetectorDefs::V_POWER_D:
|
||||
line << "VD";
|
||||
break;
|
||||
case slsDetectorDefs::V_POWER_CHIP:
|
||||
line << "VCHIP";
|
||||
break;
|
||||
default:
|
||||
line << "VBAD";
|
||||
break;
|
||||
|
||||
}
|
||||
line << " " << dacsLabel->GetText() << endl;
|
||||
return line.str();
|
||||
}
|
||||
|
||||
void ctbPower::setValue(Long_t a) {ctbPower::setValue();}
|
||||
|
||||
void ctbPower::setValue() {
|
||||
cout << "***************************Setting power " << dacsEntry->GetIntNumber() << " " << id << " " << 1 << endl;
|
||||
|
||||
try {
|
||||
myDet->setVoltage(static_cast<slsDetectorDefs::dacIndex>(id), dacsEntry->GetIntNumber());
|
||||
} CATCH_DISPLAY ("Could not set power " + to_string(id) + ".", "ctbPower::setValue")
|
||||
|
||||
getValue();
|
||||
}
|
||||
|
||||
|
||||
int ctbPower::getValue() {
|
||||
try {
|
||||
|
||||
int val = myDet->getVoltage(static_cast<slsDetectorDefs::dacIndex>(id)).tsquash("Different values");
|
||||
cout << "****************************Getting power " << val << " " << id << " " << 1 << endl;
|
||||
|
||||
dacsValue->SetText(to_string(val).c_str());
|
||||
if (val > 0) {
|
||||
if (id != static_cast<int>(slsDetectorDefs::V_POWER_CHIP))
|
||||
dacsLabel->SetOn(kTRUE);
|
||||
} else {
|
||||
dacsLabel->SetOn(kFALSE);
|
||||
}
|
||||
|
||||
return val;
|
||||
|
||||
} CATCH_DISPLAY ("Could not get power " + to_string(id) + ".", "ctbPower::getValue")
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
ctbPowers::ctbPowers(TGVerticalFrame* page, sls::Detector* det) : TGGroupFrame(page,"Power Supplies",kVerticalFrame) , myDet(det){
|
||||
|
||||
|
||||
SetTitlePos(TGGroupFrame::kLeft);
|
||||
page->AddFrame(this,new TGLayoutHints( kLHintsTop | kLHintsExpandX , 10,10,10,10));
|
||||
MapWindow();
|
||||
|
||||
// cout << "window mapped " << endl;
|
||||
|
||||
for (int idac=0; idac<NPOWERS; idac++) {
|
||||
dacs[idac]=new ctbPower(this, slsDetectorDefs::V_POWER_A+idac, myDet);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int ctbPowers::setPwrAlias(string line) {
|
||||
|
||||
int is=-1;
|
||||
char tit[100];
|
||||
|
||||
if (sscanf(line.c_str(),"VA %s",tit)) {
|
||||
dacs[0]->setLabel(tit,1);
|
||||
is=0;
|
||||
}
|
||||
|
||||
if (sscanf(line.c_str(),"VB %s",tit)) {
|
||||
dacs[1]->setLabel(tit,1);
|
||||
is=1;
|
||||
}
|
||||
|
||||
if (sscanf(line.c_str(),"VC %s",tit)) {
|
||||
dacs[2]->setLabel(tit,1);
|
||||
is=2;
|
||||
}
|
||||
|
||||
if (sscanf(line.c_str(),"VD %s",tit)) {
|
||||
dacs[3]->setLabel(tit,1);
|
||||
is=3;
|
||||
}
|
||||
|
||||
if (sscanf(line.c_str(),"VIO %s",tit)) {
|
||||
dacs[4]->setLabel(tit,1);
|
||||
is=4;
|
||||
}
|
||||
|
||||
if (sscanf(line.c_str(),"VCHIP %s",tit)) {
|
||||
dacs[5]->setLabel(tit,1);
|
||||
is=5;
|
||||
}
|
||||
|
||||
return is;
|
||||
|
||||
}
|
||||
|
||||
string ctbPowers::getPwrAlias() {
|
||||
|
||||
ostringstream line;
|
||||
|
||||
for (int i=0; i<NPOWERS; i++)
|
||||
line << dacs[i]->getLabel() << endl;
|
||||
return line.str();
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
string ctbPowers::getPwrParameters() {
|
||||
|
||||
ostringstream line;
|
||||
line << "v_a" << " " << dacs[0]->getValue() << " mv" << endl;
|
||||
line << "v_b" << " " << dacs[1]->getValue() << " mv" << endl;
|
||||
line << "v_c" << " " << dacs[2]->getValue() << " mv" << endl;
|
||||
line << "v_d" << " " << dacs[3]->getValue() << " mv" << endl;
|
||||
line << "v_io" << " " << dacs[4]->getValue() << " mv" << endl;
|
||||
line << "v_chip" << " " << dacs[5]->getValue() << " mv" << endl;
|
||||
// for (int i=0; i<POWERS; i++) {
|
||||
// //line << "dacs:" << i << " " << dacs[i]->getValue << endl;
|
||||
// line << "dac:" << i << " " << dacs[i]->getValue() << endl;
|
||||
// }
|
||||
return line.str();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ctbPowers::update() {
|
||||
for (int idac=0; idac<NPOWERS; idac++) {
|
||||
dacs[idac]->getValue();
|
||||
|
||||
}
|
||||
}
|
@ -1,69 +0,0 @@
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-other
|
||||
// Copyright (C) 2021 Contributors to the SLS Detector Package
|
||||
#ifndef CTBPOWERS_H
|
||||
#define CTBPOWERS_H
|
||||
|
||||
#include <TGFrame.h>
|
||||
|
||||
#define NPOWERS 6
|
||||
|
||||
|
||||
|
||||
class TGTextEntry;
|
||||
class TGLabel;
|
||||
class TGNumberEntry;
|
||||
class TGCheckButton;
|
||||
|
||||
|
||||
|
||||
|
||||
namespace sls
|
||||
{
|
||||
class Detector;
|
||||
};
|
||||
|
||||
#include <string>
|
||||
using namespace std;
|
||||
|
||||
|
||||
class ctbPower : public ctbDac {
|
||||
|
||||
|
||||
|
||||
|
||||
public:
|
||||
|
||||
ctbPower(TGGroupFrame* f, int i, sls::Detector* d);
|
||||
|
||||
string getLabel();
|
||||
|
||||
int getValue();
|
||||
void setValue();
|
||||
void setValue(Long_t);
|
||||
|
||||
ClassDef(ctbPower,0)
|
||||
};
|
||||
|
||||
|
||||
class ctbPowers : public TGGroupFrame
|
||||
{
|
||||
private:
|
||||
|
||||
ctbPower *dacs[NPOWERS];
|
||||
|
||||
sls::Detector* myDet;
|
||||
|
||||
public:
|
||||
//ctbPowers();
|
||||
ctbPowers(TGVerticalFrame*, sls::Detector*);
|
||||
|
||||
int setPwrAlias(string);
|
||||
string getPwrAlias();
|
||||
string getPwrParameters();
|
||||
|
||||
void update();
|
||||
|
||||
ClassDef(ctbPowers,0)
|
||||
};
|
||||
|
||||
#endif
|
@ -1,543 +0,0 @@
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-other
|
||||
// Copyright (C) 2021 Contributors to the SLS Detector Package
|
||||
#include <TApplication.h>
|
||||
#include <TGClient.h>
|
||||
#include <TCanvas.h>
|
||||
#include <TF1.h>
|
||||
#include <TRandom.h>
|
||||
#include <TGButton.h>
|
||||
#include <TRootEmbeddedCanvas.h>
|
||||
#include <TGButtonGroup.h>
|
||||
#include <TGNumberEntry.h>
|
||||
#include <TGLabel.h>
|
||||
#include <TList.h>
|
||||
#include <TGFileDialog.h>
|
||||
#include <TGComboBox.h>
|
||||
#include <TH2F.h>
|
||||
#include <TColor.h>
|
||||
#include <TH1F.h>
|
||||
#include <TGraphErrors.h>
|
||||
#include <THStack.h>
|
||||
#include <TGTab.h>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <TGButton.h>
|
||||
#include <TRootEmbeddedCanvas.h>
|
||||
#include <TGButtonGroup.h>
|
||||
#include <TGNumberEntry.h>
|
||||
#include <TGLabel.h>
|
||||
#include <stdio.h>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <TColor.h>
|
||||
#include <TGColorSelect.h>
|
||||
|
||||
|
||||
#include "ctbSignals.h"
|
||||
#include "ctbDefs.h"
|
||||
#include "sls/Detector.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
|
||||
//#define DEFAULTFN "run_0.encal"
|
||||
|
||||
|
||||
ctbSignal::ctbSignal(TGFrame *page, int i, sls::Detector *det)
|
||||
: TGHorizontalFrame(page, 800,50), myDet(det), id(i), hsig(NULL) {
|
||||
|
||||
|
||||
TGHorizontalFrame *hframe=this;
|
||||
char tit[100];
|
||||
|
||||
|
||||
|
||||
sprintf(tit, "BIT%d ",id);
|
||||
|
||||
sLabel= new TGLabel(hframe, tit);
|
||||
hframe->AddFrame( sLabel,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1));
|
||||
sLabel->MapWindow();
|
||||
sLabel->SetTextJustify(kTextLeft);
|
||||
|
||||
|
||||
|
||||
sOutput= new TGCheckButton(hframe, "Out");
|
||||
hframe->AddFrame( sOutput,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1));
|
||||
sOutput->MapWindow();
|
||||
|
||||
|
||||
sOutput->Connect("Toggled(Bool_t)","ctbSignal",this,"ToggledOutput(Bool_t)");
|
||||
|
||||
sDbitList= new TGCheckButton(hframe, "DB List");
|
||||
hframe->AddFrame( sDbitList,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1));
|
||||
sDbitList->MapWindow();
|
||||
|
||||
sDbitList->Connect("Toggled(Bool_t)","ctbSignal",this,"ToggledDbitList(Bool_t)");
|
||||
|
||||
|
||||
sPlot= new TGCheckButton(hframe, "Plot");
|
||||
hframe->AddFrame( sPlot,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1));
|
||||
sPlot->MapWindow();
|
||||
|
||||
sPlot->Connect("Toggled(Bool_t)","ctbSignal",this,"ToggledPlot(Bool_t)");
|
||||
|
||||
fColorSel = new TGColorSelect(hframe, id+1, 0);
|
||||
fColorSel->Connect("ColorSelected(Pixel_t)","ctbSignal",this,"ColorChanged(Pixel_t)");
|
||||
hframe->AddFrame(fColorSel, new TGLayoutHints(kLHintsTop |
|
||||
kLHintsLeft, 2, 0, 2, 2));
|
||||
|
||||
|
||||
fColorSel->SetColor(TColor::Number2Pixel(id+1));
|
||||
|
||||
|
||||
ToggledOutput(kFALSE);
|
||||
|
||||
|
||||
ToggledPlot(kFALSE);
|
||||
|
||||
// if (id==63) {
|
||||
// sOutput->SetOn(kTRUE);
|
||||
// sOutput->SetEnabled(kFALSE);
|
||||
// }
|
||||
// #ifdef CTB
|
||||
// if (id==62) {
|
||||
// sOutput->SetOn(kTRUE);
|
||||
// sOutput->SetEnabled(kFALSE);
|
||||
// }
|
||||
|
||||
// // if (id>=32 && id<48)
|
||||
// // fixOutput(1);
|
||||
// // else if (id>=48 && id<64)
|
||||
// // fixOutput(0);
|
||||
|
||||
// #endif
|
||||
}
|
||||
int ctbSignal::setSignalAlias(char *tit, int plot, int col) {
|
||||
|
||||
if (tit)
|
||||
sLabel->SetText(tit);
|
||||
|
||||
if (plot>0) {
|
||||
sPlot->SetOn(kTRUE,kTRUE);
|
||||
} else if (plot==0)
|
||||
sPlot->SetOn(kFALSE,kTRUE);
|
||||
|
||||
if (col>=0)
|
||||
fColorSel->SetColor(col);//TColor::Number2Pixel(col+1));
|
||||
|
||||
fColorSel->SetEnabled(sPlot->IsOn());
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
string ctbSignal::getSignalAlias() {
|
||||
|
||||
|
||||
ostringstream oss;
|
||||
oss << "BIT" << dec << id << " " << sLabel->GetText()->Data() << " " << sPlot->IsOn() << hex << " " << fColorSel->GetColor() << endl;
|
||||
return oss.str();
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
int ctbSignal::setOutput(Long64_t r) {
|
||||
|
||||
|
||||
// cout << hex << r << dec <<endl;
|
||||
|
||||
Long64_t mask=((Long64_t)1<<id);
|
||||
|
||||
if (r&mask)
|
||||
sOutput->SetOn(kTRUE,kTRUE);
|
||||
else
|
||||
sOutput->SetOn(kFALSE,kTRUE);
|
||||
|
||||
return sOutput->IsOn();
|
||||
|
||||
}
|
||||
|
||||
int ctbSignal::fixOutput(int i) {
|
||||
|
||||
if (i) {
|
||||
sPlot->SetOn(kFALSE);
|
||||
//sClock->SetOn(kFALSE,kTRUE);
|
||||
sOutput->SetOn(kTRUE);
|
||||
// sPlot->SetEnabled(kFALSE);
|
||||
// sClock->SetEnabled(kTRUE);
|
||||
} else {
|
||||
sOutput->SetOn(kFALSE,kTRUE);
|
||||
// sClock->SetOn(kFALSE);
|
||||
// sClock->SetEnabled(kFALSE);
|
||||
sPlot->SetEnabled(kTRUE);
|
||||
}
|
||||
sOutput->SetEnabled(kFALSE);
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int ctbSignal::setDbitList(Long64_t r) {
|
||||
|
||||
if (r)
|
||||
sDbitList->SetOn(kTRUE,kFALSE);
|
||||
else
|
||||
sDbitList->SetOn(kFALSE,kFALSE);
|
||||
|
||||
return sDbitList->IsOn();
|
||||
|
||||
}
|
||||
|
||||
int ctbSignal::isDbitList() { return sDbitList->IsOn();}
|
||||
int ctbSignal::isOutput() { return sOutput->IsOn();}
|
||||
int ctbSignal::isPlot() { return sPlot->IsOn();}
|
||||
Pixel_t ctbSignal::getColor(){return fColorSel->GetColor();}
|
||||
|
||||
void ctbSignal::ToggledOutput(Bool_t b) {
|
||||
ToggledSignalOutput(id);
|
||||
if (b) {
|
||||
// sClock->SetEnabled(kTRUE);
|
||||
sPlot->SetOn(kFALSE);
|
||||
// sPlot->SetEnabled(kFALSE);
|
||||
fColorSel->SetEnabled(kFALSE);
|
||||
} else {
|
||||
// sClock->SetEnabled(kFALSE);
|
||||
// sClock->SetOn(kFALSE);
|
||||
sPlot->SetEnabled(kTRUE);
|
||||
if ( sPlot->IsOn())
|
||||
fColorSel->SetEnabled(kFALSE);
|
||||
else
|
||||
fColorSel->SetEnabled(kTRUE);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void ctbSignal::ToggledDbitList(Bool_t b){
|
||||
Long_t mask=id;
|
||||
ToggledSignalDbitList(mask);
|
||||
}
|
||||
|
||||
|
||||
void ctbSignal::ToggledPlot(Bool_t b){
|
||||
Long_t mask=b<<id;
|
||||
ToggledSignalPlot(mask);
|
||||
fColorSel->SetEnabled(b);
|
||||
}
|
||||
|
||||
void ctbSignal::ColorChanged(Pixel_t p){
|
||||
ToggledSignalPlot(id);
|
||||
}
|
||||
|
||||
|
||||
void ctbSignal::ToggledSignalOutput(Int_t b) {
|
||||
cout << "Toggle signal " << id << " " << b << " " << sOutput->IsOn() <<endl;;
|
||||
Emit("ToggledSignalOutput(Int_t)", id);
|
||||
}
|
||||
|
||||
void ctbSignal::ToggledSignalDbitList(Int_t b){
|
||||
cout << "Toggle dbitlist " << id << " " << b << endl;;
|
||||
Emit("ToggledSignalDbitList(Int_t)", id);
|
||||
}
|
||||
|
||||
void ctbSignal::ToggledSignalPlot(Int_t b){
|
||||
Emit("ToggledSignalPlot(Int_t)", id);
|
||||
}
|
||||
|
||||
|
||||
ctbSignals::ctbSignals(TGVerticalFrame *page, sls::Detector *det)
|
||||
: TGGroupFrame(page,"IO Signals",kVerticalFrame), myDet(det) {
|
||||
|
||||
|
||||
SetTitlePos(TGGroupFrame::kLeft);
|
||||
page->AddFrame(this,new TGLayoutHints( kLHintsTop | kLHintsExpandX , 10,10,10,10));
|
||||
MapWindow();
|
||||
|
||||
|
||||
TGHorizontalFrame *hframe;
|
||||
|
||||
TGHorizontalFrame* hhframe=new TGHorizontalFrame(this, 800,800);
|
||||
AddFrame(hhframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 1,1,1,1));
|
||||
hhframe->MapWindow();
|
||||
|
||||
TGVerticalFrame *vframe;
|
||||
|
||||
|
||||
|
||||
|
||||
int idac=0;
|
||||
for (idac=0; idac<NSIGNALS; idac++) {
|
||||
if (idac%((NSIGNALS+2)/2)==0) {
|
||||
vframe=new TGVerticalFrame(hhframe, 400,800);
|
||||
hhframe->AddFrame(vframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 1,1,1,1));
|
||||
vframe->MapWindow();
|
||||
}
|
||||
|
||||
|
||||
signals[idac]=new ctbSignal(vframe,idac,myDet);
|
||||
signals[idac]->Connect("ToggledSignalOutput(Int_t)","ctbSignals",this,"ToggledOutReg(Int_t)");
|
||||
signals[idac]->Connect("ToggledSignalDbitList(Int_t)","ctbSignals",this,"ToggledDbitList(Int_t)");
|
||||
signals[idac]->Connect("ToggledSignalPlot(Int_t)","ctbSignals",this,"ToggledPlot(Int_t)");
|
||||
|
||||
vframe->AddFrame(signals[idac],new TGLayoutHints(kLHintsTop | kLHintsExpandX , 1,1,1,1));
|
||||
signals[idac]->MapWindow();
|
||||
|
||||
|
||||
}
|
||||
|
||||
hframe=new TGHorizontalFrame(vframe, 800,50);
|
||||
vframe->AddFrame(hframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 1,1,1,1));
|
||||
hframe->MapWindow();
|
||||
|
||||
|
||||
TGLabel *label= new TGLabel(hframe, "IO Control Register: ");
|
||||
hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1));
|
||||
label->MapWindow();
|
||||
label->SetTextJustify(kTextLeft);
|
||||
|
||||
|
||||
eIOCntrlRegister = new TGNumberEntry(hframe, 0, 16,999, TGNumberFormat::kNESHex,
|
||||
TGNumberFormat::kNEANonNegative,
|
||||
TGNumberFormat::kNELNoLimits);
|
||||
|
||||
hframe->AddFrame(eIOCntrlRegister,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 1, 1, 1, 1));
|
||||
eIOCntrlRegister->MapWindow();
|
||||
eIOCntrlRegister->Resize(150,30);
|
||||
|
||||
|
||||
|
||||
|
||||
hframe=new TGHorizontalFrame(vframe, 800,50);
|
||||
vframe->AddFrame(hframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 1,1,1,1));
|
||||
hframe->MapWindow();
|
||||
|
||||
|
||||
label= new TGLabel(hframe, "DBit Offset: ");
|
||||
hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1));
|
||||
label->MapWindow();
|
||||
label->SetTextJustify(kTextLeft);
|
||||
|
||||
|
||||
eDbitOffset = new TGNumberEntry(hframe, 0, 9,999, TGNumberFormat::kNESInteger,
|
||||
TGNumberFormat::kNEANonNegative,
|
||||
TGNumberFormat::kNELNoLimits);
|
||||
|
||||
hframe->AddFrame(eDbitOffset,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 1, 1, 1, 1));
|
||||
eDbitOffset->MapWindow();
|
||||
eDbitOffset->Resize(150,30);
|
||||
|
||||
|
||||
TGTextEntry *e= eDbitOffset->TGNumberEntry::GetNumberEntry();
|
||||
e->Connect("ReturnPressed()","ctbSignals",this,"setDbitOffset()");
|
||||
|
||||
e->Connect("ValueSet(Long_t)","ctbSignals",this,"setDbitOffset(Long_t)");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int ctbSignals::setSignalAlias(string line) {
|
||||
|
||||
int is=-1, plot=0, col=-1;
|
||||
char tit[100];
|
||||
int narg=sscanf(line.c_str(),"BIT%d %s %d %d",&is,tit,&plot,&col);
|
||||
if (narg<2)
|
||||
return -1;
|
||||
if (is>=0 && is<NIOSIGNALS) {
|
||||
signals[is]->setSignalAlias(tit,plot,col);
|
||||
}
|
||||
return is;
|
||||
|
||||
}
|
||||
|
||||
string ctbSignals::getSignalAlias() {
|
||||
|
||||
ostringstream oss;
|
||||
for (int is=0; is<NIOSIGNALS; is++)
|
||||
oss << signals[is]->getSignalAlias() << endl;
|
||||
|
||||
|
||||
return oss.str();
|
||||
|
||||
}
|
||||
|
||||
|
||||
void ctbSignals::update() {
|
||||
try {
|
||||
|
||||
Long64_t oreg = static_cast<Long64_t>(myDet->getPatternIOControl().tsquash("Different values"));
|
||||
cout << hex << oreg << dec << endl;
|
||||
|
||||
for (int idac=0; idac<NIOSIGNALS; idac++) {
|
||||
signals[idac]->setOutput(oreg);
|
||||
}
|
||||
|
||||
} CATCH_DISPLAY ("Could not get patternIOcontrol.", "ctbSignals::update")
|
||||
|
||||
if (myDet->getDetectorType().squash() == slsDetectorDefs::MOENCH) {
|
||||
// enable all
|
||||
for (int is=0; is<64; is++) {
|
||||
signals[is]->setDbitList(1);
|
||||
}
|
||||
eDbitOffset->SetNumber(0);
|
||||
}
|
||||
|
||||
// ctb
|
||||
else {
|
||||
try {
|
||||
|
||||
auto dbitlist = myDet->getRxDbitList().tsquash("Different values");
|
||||
// enable all
|
||||
if (dbitlist.empty()) {
|
||||
for (int is=0; is<64; is++) {
|
||||
signals[is]->setDbitList(1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// disable all
|
||||
for (int is=0; is<64; is++) {
|
||||
signals[is]->setDbitList(0);
|
||||
}
|
||||
// enable selected
|
||||
for (const auto &value : dbitlist) {
|
||||
signals[value]->setDbitList(1);
|
||||
}
|
||||
}
|
||||
|
||||
} CATCH_DISPLAY ("Could not get receiver dbit list.", "ctbSignals::update")
|
||||
|
||||
try {
|
||||
auto val = myDet->getRxDbitOffset().tsquash("Different values");
|
||||
eDbitOffset->SetNumber(val);
|
||||
} CATCH_DISPLAY ("Could not get receiver dbit offset.", "ctbSignals::update")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
string ctbSignals::getSignalParameters() {
|
||||
|
||||
try {
|
||||
|
||||
auto val = myDet->getPatternIOControl().tsquash("Different values");
|
||||
ostringstream line;
|
||||
line << "patioctrl " << hex << val << dec << endl;
|
||||
return line.str();
|
||||
|
||||
} CATCH_DISPLAY ("Could not get patternIOcontrol.", "ctbSignals::getSignalParameters")
|
||||
|
||||
return ("");
|
||||
}
|
||||
|
||||
void ctbSignals::ToggledOutReg(Int_t mask) {
|
||||
try {
|
||||
|
||||
Long64_t oreg = static_cast<Long64_t>(myDet->getPatternIOControl().tsquash("Different values"));
|
||||
Long64_t m=((Long64_t)1)<<mask;
|
||||
cout << dec << sizeof(Long64_t) << " " << mask << " " << hex << m << " ioreg " << oreg;
|
||||
|
||||
if (signals[mask]->isOutput()) {
|
||||
cout << " or " << m ;
|
||||
oreg|=m;
|
||||
} else {
|
||||
cout << " not " << ~m ;
|
||||
oreg&=~m;
|
||||
}
|
||||
cout << " after " << oreg << endl;
|
||||
|
||||
myDet->setPatternIOControl(static_cast<uint64_t>(oreg));
|
||||
oreg = static_cast<Long64_t>(myDet->getPatternIOControl().tsquash("Different values"));
|
||||
cout << dec << sizeof(Long64_t) << " " << mask << " " << hex << m << " ioreg " << oreg << endl;
|
||||
|
||||
eIOCntrlRegister->SetText(to_string(oreg).c_str());
|
||||
|
||||
} CATCH_DISPLAY ("Could not get/set patternIOcontrol.", "ctbSignals::ToggledOutReg")
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ctbSignals::ToggledDbitList(Int_t mask){
|
||||
try {
|
||||
|
||||
auto dbitlist = myDet->getRxDbitList().tsquash("Different values");
|
||||
|
||||
// anyway all enabled
|
||||
if ((dbitlist.empty()) && (signals[mask]->isDbitList())) {
|
||||
;
|
||||
}
|
||||
// set the dbitlist
|
||||
else {
|
||||
std::vector <int> new_dbitlist;
|
||||
for (int is=0; is<64; is++) {
|
||||
if (signals[is]->isDbitList()){
|
||||
new_dbitlist.push_back(is);
|
||||
cout << is << " " << new_dbitlist.size() - 1 << endl;
|
||||
}
|
||||
}
|
||||
if (new_dbitlist.size() > 64)
|
||||
new_dbitlist.clear();
|
||||
myDet->setRxDbitList(new_dbitlist);
|
||||
// get list again
|
||||
dbitlist = myDet->getRxDbitList().tsquash("Different values");
|
||||
}
|
||||
|
||||
// enable all
|
||||
if (dbitlist.empty()) {
|
||||
for (int is=0; is<64; is++) {
|
||||
signals[is]->setDbitList(1);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// disable all
|
||||
for (int is=0; is<64; is++) {
|
||||
signals[is]->setDbitList(0);
|
||||
}
|
||||
// enable selected
|
||||
for (const auto &value : dbitlist) {
|
||||
signals[value]->setDbitList(1);
|
||||
}
|
||||
}
|
||||
|
||||
} CATCH_DISPLAY ("Could not get/set receiver dbit list.", "ctbSignals::ToggledDbitList")
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void ctbSignals::ToggledPlot(Int_t b) {
|
||||
|
||||
Emit("ToggledSignalPlot(Int_t)", b);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void ctbSignals::ToggledSignalPlot(Int_t b) {
|
||||
|
||||
Emit("ToggledSignalPlot(Int_t)", b);
|
||||
|
||||
}
|
||||
|
||||
|
||||
Pixel_t ctbSignals::getColor(int i){
|
||||
if (i>=0 && i<NSIGNALS)
|
||||
return signals[i]->getColor();
|
||||
return static_cast<Pixel_t>(-1);
|
||||
}
|
||||
|
||||
int ctbSignals::getPlot(int i){
|
||||
if (i>=0 && i<NSIGNALS)
|
||||
return signals[i]->isPlot();
|
||||
return -1;
|
||||
};
|
||||
|
||||
void ctbSignals::setDbitOffset(Long_t) {
|
||||
setDbitOffset();
|
||||
}
|
||||
|
||||
void ctbSignals::setDbitOffset(){
|
||||
try {
|
||||
myDet->setRxDbitOffset(eDbitOffset->GetNumber());
|
||||
} CATCH_DISPLAY ("Could not set receiver dbit offset.", "ctbSignals::setDbitOffset")
|
||||
}
|
@ -1,123 +0,0 @@
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-other
|
||||
// Copyright (C) 2021 Contributors to the SLS Detector Package
|
||||
#ifndef CTBSIGNALS_H
|
||||
#define CTBSIGNALS_H
|
||||
#include <TGFrame.h>
|
||||
|
||||
|
||||
#define NSIGNALS 64
|
||||
|
||||
#define NIOSIGNALS 64 //for moench board was 52
|
||||
|
||||
|
||||
#define ADCLATCH 63
|
||||
#define DIGSIGLATCH 62
|
||||
|
||||
|
||||
|
||||
|
||||
class TGTextEntry;
|
||||
class TGLabel;
|
||||
class TGNumberEntry;
|
||||
class TGCheckButton;
|
||||
class TH1I;
|
||||
class TGTextButton;
|
||||
class TGColorSelect;
|
||||
|
||||
|
||||
|
||||
class TGNumberEntry;
|
||||
namespace sls
|
||||
{
|
||||
class Detector;
|
||||
};
|
||||
class ctbSignal;
|
||||
|
||||
#include <string>
|
||||
using namespace std;
|
||||
|
||||
class ctbSignal : public TGHorizontalFrame {
|
||||
|
||||
// RQ_OBJECT("ctbSignal")
|
||||
|
||||
private:
|
||||
|
||||
TGLabel *sLabel;
|
||||
TGCheckButton *sOutput;
|
||||
TGCheckButton *sDbitList;
|
||||
TGCheckButton *sPlot;
|
||||
TGLabel *sValue;
|
||||
TGNumberEntry *sEntry;
|
||||
TGColorSelect *fColorSel;
|
||||
|
||||
sls::Detector *myDet;
|
||||
Int_t id;
|
||||
|
||||
TH1I *hsig;
|
||||
|
||||
public:
|
||||
|
||||
ctbSignal(TGFrame *page, int i, sls::Detector *det);
|
||||
int setSignalAlias(char *tit, int plot, int col);
|
||||
string getSignalAlias();
|
||||
|
||||
TH1I *getPlot() {return hsig;};
|
||||
int setOutput(Long64_t);
|
||||
int fixOutput(int);
|
||||
int setDbitList(Long64_t);
|
||||
|
||||
void ToggledOutput(Bool_t);
|
||||
void ToggledDbitList(Bool_t);
|
||||
void ToggledPlot(Bool_t);
|
||||
void ColorChanged(Pixel_t);
|
||||
|
||||
int isDbitList();
|
||||
int isOutput();
|
||||
int isPlot();
|
||||
Pixel_t getColor();
|
||||
|
||||
|
||||
void ToggledSignalOutput(Int_t); //*SIGNAL*
|
||||
void ToggledSignalDbitList(Int_t); //*SIGNAL*
|
||||
void ToggledSignalPlot(Int_t); //*SIGNAL*
|
||||
|
||||
|
||||
|
||||
ClassDef(ctbSignal,0)
|
||||
};
|
||||
|
||||
class ctbSignals : public TGGroupFrame {
|
||||
private:
|
||||
|
||||
ctbSignal *signals[NSIGNALS];
|
||||
|
||||
TGNumberEntry *eIOCntrlRegister;
|
||||
TGNumberEntry *eDbitOffset;
|
||||
|
||||
sls::Detector *myDet;
|
||||
|
||||
public:
|
||||
ctbSignals(TGVerticalFrame *page, sls::Detector *det);
|
||||
int setSignalAlias(string line);
|
||||
string getSignalAlias();
|
||||
|
||||
int getPlot(int);
|
||||
Pixel_t getColor(int);
|
||||
|
||||
void update();
|
||||
// void saveParameters();
|
||||
string getSignalParameters();
|
||||
|
||||
//void setDbitList(Int_t);
|
||||
void setDbitOffset(Long_t);
|
||||
void setDbitOffset();
|
||||
|
||||
void ToggledOutReg(Int_t);
|
||||
void ToggledDbitList(Int_t);
|
||||
void ToggledPlot(Int_t);
|
||||
void ToggledSignalPlot(Int_t); //*SIGNAL*
|
||||
|
||||
ClassDef(ctbSignals,0)
|
||||
};
|
||||
|
||||
#endif
|
@ -1,184 +0,0 @@
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-other
|
||||
// Copyright (C) 2021 Contributors to the SLS Detector Package
|
||||
|
||||
#include <stdio.h>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
|
||||
#include <TGTextEntry.h>
|
||||
#include <TGLabel.h>
|
||||
#include <TGNumberEntry.h>
|
||||
#include <TGButton.h>
|
||||
|
||||
#include "ctbSlowAdcs.h"
|
||||
#include "ctbDefs.h"
|
||||
#include "sls/Detector.h"
|
||||
#include "sls/sls_detector_defs.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
|
||||
|
||||
|
||||
ctbSlowAdc::ctbSlowAdc(TGGroupFrame *page, int idac, sls::Detector *det) : TGHorizontalFrame(page, 800,50) , id(idac), myDet(det) {
|
||||
|
||||
|
||||
TGHorizontalFrame *hframe=this;
|
||||
|
||||
page->AddFrame(hframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 1,1,1,1));
|
||||
MapWindow();
|
||||
|
||||
char tit[100];
|
||||
|
||||
|
||||
sprintf(tit, "SENSE %d:",idac-1000);
|
||||
|
||||
dacsLabel= new TGLabel(hframe, tit);// new TGLabel(hframe, tit);
|
||||
|
||||
|
||||
|
||||
hframe->AddFrame(dacsLabel,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 5, 5, 5, 5));
|
||||
dacsLabel->MapWindow();
|
||||
dacsLabel->SetTextJustify(kTextLeft);
|
||||
|
||||
|
||||
|
||||
|
||||
sprintf(tit, "xxx");
|
||||
dacsValue= new TGLabel(hframe, tit);
|
||||
hframe->AddFrame( dacsValue,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 5, 5, 5, 5));
|
||||
dacsValue->MapWindow();
|
||||
dacsValue->SetTextJustify(kTextLeft);
|
||||
|
||||
|
||||
|
||||
TGTextButton *b= new TGTextButton(hframe, "Update");
|
||||
hframe->AddFrame( b,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 5, 5, 5, 5));
|
||||
b->MapWindow();
|
||||
b->SetTextJustify(kTextLeft);
|
||||
|
||||
b->Connect("Clicked()","ctbSlowAdc",this,"getValue()");
|
||||
}
|
||||
|
||||
|
||||
|
||||
int ctbSlowAdc::setLabel(char *tit) {
|
||||
if(tit)
|
||||
dacsLabel->SetText(tit);
|
||||
|
||||
return id;
|
||||
|
||||
}
|
||||
|
||||
string ctbSlowAdc::getLabel() {
|
||||
ostringstream line;
|
||||
line << dacsLabel->GetText() << endl;
|
||||
|
||||
// line << "DAC" << dec << id << " " << dacsUnit->IsOn() << endl;
|
||||
|
||||
return line.str();
|
||||
}
|
||||
|
||||
|
||||
|
||||
int ctbSlowAdc::getValue() {
|
||||
try {
|
||||
std::string s;
|
||||
|
||||
// temp
|
||||
if (id == static_cast<int>(slsDetectorDefs::SLOW_ADC_TEMP)) {
|
||||
|
||||
int val = myDet->getTemperature(static_cast<slsDetectorDefs::dacIndex>(id)).tsquash("Different values");
|
||||
cout << "slow adc temp" << " " << val << endl;
|
||||
|
||||
s = to_string(val) + " " + to_string(0x00b0) + "C";//<2F>C
|
||||
dacsValue->SetText(s.c_str());
|
||||
return val;
|
||||
}
|
||||
|
||||
// mv
|
||||
else {
|
||||
|
||||
int val = myDet->getSlowADC(static_cast<slsDetectorDefs::dacIndex>(id)).tsquash("Different values");
|
||||
cout << "slow adc " << id << " " << val << endl;
|
||||
|
||||
s = to_string(val) + " mV";
|
||||
dacsValue->SetText(s.c_str());
|
||||
return val;
|
||||
}
|
||||
|
||||
} CATCH_DISPLAY ("Could not get slow dac " + to_string(id) + ".", "ctbSlowAdc::getValue")
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
ctbSlowAdcs::ctbSlowAdcs(TGVerticalFrame *page, sls::Detector *det) : TGGroupFrame(page,"Sense",kVerticalFrame) , myDet(det){
|
||||
|
||||
SetTitlePos(TGGroupFrame::kLeft);
|
||||
page->AddFrame(this,new TGLayoutHints( kLHintsTop | kLHintsExpandX , 10,10,10,10));
|
||||
MapWindow();
|
||||
|
||||
// cout << "window mapped " << endl;
|
||||
|
||||
|
||||
for (int idac=0; idac<NSLOWADCS + 1; idac++) {
|
||||
|
||||
adcs[idac]=new ctbSlowAdc(this, idac+1000, myDet);
|
||||
|
||||
}
|
||||
adcs[NSLOWADCS]->setLabel((char*)"Temperature");
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
int ctbSlowAdcs::setSlowAdcAlias(string line) {
|
||||
|
||||
int is=-1, mv=0;
|
||||
char tit[100];
|
||||
int narg=sscanf(line.c_str(),"SENSE%d %s %d",&is,tit,&mv);
|
||||
if (narg<2)
|
||||
return -1;
|
||||
if (is>=0 && is<NSLOWADCS)
|
||||
adcs[is]->setLabel(tit);
|
||||
return is;
|
||||
|
||||
}
|
||||
|
||||
string ctbSlowAdcs::getSlowAdcAlias() {
|
||||
|
||||
ostringstream line;
|
||||
|
||||
for (int i=0; i<NSLOWADCS; i++)
|
||||
line << adcs[i]->getLabel() << endl;
|
||||
return line.str();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
string ctbSlowAdcs::getAdcParameters() {
|
||||
|
||||
ostringstream line;
|
||||
|
||||
for (int i=0; i<NSLOWADCS; i++) {
|
||||
//line << "dacs:" << i << " " << dacs[i]->getValue << endl;
|
||||
line << "adc:" << i << " " << adcs[i]->getValue() << endl;
|
||||
}
|
||||
line << "adc:-1" << adcs[NSLOWADCS]->getValue() << endl;
|
||||
return line.str();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void ctbSlowAdcs::update() {
|
||||
for (int idac=0; idac<NSLOWADCS+1; idac++) {
|
||||
adcs[idac]->getValue();
|
||||
}
|
||||
}
|
@ -1,80 +0,0 @@
|
||||
// SPDX-License-Identifier: LGPL-3.0-or-other
|
||||
// Copyright (C) 2021 Contributors to the SLS Detector Package
|
||||
|
||||
|
||||
#ifndef CTBSLOWADCS_H
|
||||
#define CTBSLOWADCS_H
|
||||
#include <TGFrame.h>
|
||||
|
||||
|
||||
//#define NDACS 16
|
||||
#define NSLOWADCS 8
|
||||
|
||||
|
||||
|
||||
|
||||
class TGTextEntry;
|
||||
class TGLabel;
|
||||
class TGNumberEntry;
|
||||
class TGCheckButton;
|
||||
class TGTextButton;
|
||||
|
||||
|
||||
|
||||
namespace sls
|
||||
{
|
||||
class Detector;
|
||||
};
|
||||
|
||||
#include <string>
|
||||
using namespace std;
|
||||
|
||||
class ctbSlowAdc : public TGHorizontalFrame {
|
||||
|
||||
|
||||
protected:
|
||||
// TGLabel *dacsLabel;
|
||||
// TGNumberEntry *dacsEntry;
|
||||
// TGCheckButton *dacsUnit;
|
||||
TGLabel *dacsLabel;
|
||||
TGLabel *dacsValue;
|
||||
int id;
|
||||
|
||||
sls::Detector* myDet;
|
||||
public:
|
||||
ctbSlowAdc(TGGroupFrame*, int , sls::Detector*);
|
||||
int getValue();
|
||||
|
||||
int setLabel(char *tit);
|
||||
string getLabel();
|
||||
|
||||
|
||||
|
||||
ClassDef(ctbSlowAdc,0)
|
||||
};
|
||||
|
||||
|
||||
class ctbSlowAdcs : public TGGroupFrame {
|
||||
private:
|
||||
|
||||
|
||||
|
||||
ctbSlowAdc *adcs[NSLOWADCS+1];
|
||||
|
||||
sls::Detector* myDet;
|
||||
|
||||
public:
|
||||
ctbSlowAdcs(TGVerticalFrame *page, sls::Detector*);
|
||||
|
||||
int setSlowAdcAlias(string line);
|
||||
// int setDacAlias(string line);
|
||||
string getSlowAdcAlias();
|
||||
string getAdcParameters();
|
||||
|
||||
void update();
|
||||
|
||||
ClassDef(ctbSlowAdcs,0)
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -58,6 +58,12 @@ set(SPHINX_SOURCE_FILES
|
||||
src/udpheader.rst
|
||||
src/udpconfig.rst
|
||||
src/udpdetspec.rst
|
||||
src/fileformat.rst
|
||||
src/slsreceiverheaderformat.rst
|
||||
src/masterfileattributes.rst
|
||||
src/binaryfileformat.rst
|
||||
src/hdf5fileformat.rst
|
||||
src/zmqjsonheaderformat.rst
|
||||
)
|
||||
|
||||
foreach(filename ${SPHINX_SOURCE_FILES})
|
||||
|
438
docs/src/binaryfileformat.rst
Normal file
438
docs/src/binaryfileformat.rst
Normal file
@ -0,0 +1,438 @@
|
||||
Binary File Format
|
||||
====================
|
||||
|
||||
This is the default file format that can be configured using command `fformat <commandline.html#term-fformat-binary-hdf5>`_.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
sls_detector_put fformat binary
|
||||
|
||||
|
||||
Master File
|
||||
--------------
|
||||
|
||||
* File Name: [fpath]/[fname]_master_[findex].json :ref:`Details here<file name format>`
|
||||
|
||||
* It is in json format and created for every acquisition.
|
||||
|
||||
* It contains :ref:`attributes<master file attributes>` relevant to the acquisition. This can vary with detector type shown in :ref:`master json file examples <json master file examples>` here.
|
||||
|
||||
* It shows the :ref:`**SLS Receiver Header** <sls receiver header format>` format used in data files.
|
||||
|
||||
* Enabled/disabled using command `fmaster <commandline.html#term-fmaster-0-1>`_.
|
||||
|
||||
|
||||
Data File
|
||||
----------
|
||||
|
||||
* File Name: [fpath]/[fname]_dx_fy_[findex].raw :ref:`Details here<file name format>`
|
||||
|
||||
* It store multiple frames sequentially, with total number of frames determined by `rx_framesperfile <commandline.html#term-rx_framesperfile-n_frames>`_ parameter.
|
||||
|
||||
* Each frame includes a :ref:`**sls_receiver_header** <sls receiver header format>` structure, followed by the actual frame data.
|
||||
|
||||
|
||||
|
||||
.. _json master file examples:
|
||||
|
||||
JSON Master File Examples
|
||||
---------------------------------------------------
|
||||
|
||||
Eiger
|
||||
^^^^^
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
{
|
||||
"Version": 7.2,
|
||||
"Timestamp": "Wed Nov 13 15:46:30 2024",
|
||||
"Detector Type": "Eiger",
|
||||
"Timing Mode": "auto",
|
||||
"Geometry": {
|
||||
"x": 2,
|
||||
"y": 1
|
||||
},
|
||||
"Image Size in bytes": 262144,
|
||||
"Pixels": {
|
||||
"x": 512,
|
||||
"y": 256
|
||||
},
|
||||
"Max Frames Per File": 10000,
|
||||
"Frame Discard Policy": "nodiscard",
|
||||
"Frame Padding": 1,
|
||||
"Scan Parameters": "[disabled]",
|
||||
"Total Frames": 1,
|
||||
"Receiver Roi": {
|
||||
"xmin": 4294967295,
|
||||
"xmax": 4294967295,
|
||||
"ymin": 4294967295,
|
||||
"ymax": 4294967295
|
||||
},
|
||||
"Dynamic Range": 16,
|
||||
"Ten Giga": 0,
|
||||
"Exptime": "1s",
|
||||
"Period": "1s",
|
||||
"Threshold Energy": -1,
|
||||
"Sub Exptime": "2.62144ms",
|
||||
"Sub Period": "2.62144ms",
|
||||
"Quad": 0,
|
||||
"Number of rows": 256,
|
||||
"Rate Corrections": "[0]",
|
||||
"Frames in File": 1,
|
||||
"Frame Header Format": {
|
||||
"Frame Number": "8 bytes",
|
||||
"SubFrame Number/ExpLength": "4 bytes",
|
||||
"Packet Number": "4 bytes",
|
||||
"Bunch ID": "8 bytes",
|
||||
"Timestamp": "8 bytes",
|
||||
"Module Id": "2 bytes",
|
||||
"Row": "2 bytes",
|
||||
"Column": "2 bytes",
|
||||
"Reserved": "2 bytes",
|
||||
"Debug": "4 bytes",
|
||||
"Round Robin Number": "2 bytes",
|
||||
"Detector Type": "1 byte",
|
||||
"Header Version": "1 byte",
|
||||
"Packets Caught Mask": "64 bytes"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Jungfrau
|
||||
^^^^^^^^
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
{
|
||||
"Version": 7.2,
|
||||
"Timestamp": "Wed Nov 13 13:03:53 2024",
|
||||
"Detector Type": "Jungfrau",
|
||||
"Timing Mode": "auto",
|
||||
"Geometry": {
|
||||
"x": 1,
|
||||
"y": 1
|
||||
},
|
||||
"Image Size in bytes": 1048576,
|
||||
"Pixels": {
|
||||
"x": 1024,
|
||||
"y": 512
|
||||
},
|
||||
"Max Frames Per File": 10000,
|
||||
"Frame Discard Policy": "nodiscard",
|
||||
"Frame Padding": 1,
|
||||
"Scan Parameters": "[disabled]",
|
||||
"Total Frames": 1000,
|
||||
"Receiver Roi": {
|
||||
"xmin": 4294967295,
|
||||
"xmax": 4294967295,
|
||||
"ymin": 4294967295,
|
||||
"ymax": 4294967295
|
||||
},
|
||||
"Exptime": "10us",
|
||||
"Period": "2ms",
|
||||
"Number of UDP Interfaces": 1,
|
||||
"Number of rows": 512,
|
||||
"Frames in File": 10,
|
||||
"Frame Header Format": {
|
||||
"Frame Number": "8 bytes",
|
||||
"SubFrame Number/ExpLength": "4 bytes",
|
||||
"Packet Number": "4 bytes",
|
||||
"Bunch ID": "8 bytes",
|
||||
"Timestamp": "8 bytes",
|
||||
"Module Id": "2 bytes",
|
||||
"Row": "2 bytes",
|
||||
"Column": "2 bytes",
|
||||
"Reserved": "2 bytes",
|
||||
"Debug": "4 bytes",
|
||||
"Round Robin Number": "2 bytes",
|
||||
"Detector Type": "1 byte",
|
||||
"Header Version": "1 byte",
|
||||
"Packets Caught Mask": "64 bytes"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Gotthard2
|
||||
^^^^^^^^^^^^
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
{
|
||||
"Version": 7.2,
|
||||
"Timestamp": "Wed Nov 13 14:18:17 2024",
|
||||
"Detector Type": "Gotthard2",
|
||||
"Timing Mode": "auto",
|
||||
"Geometry": {
|
||||
"x": 1,
|
||||
"y": 1
|
||||
},
|
||||
"Image Size in bytes": 2560,
|
||||
"Pixels": {
|
||||
"x": 1280,
|
||||
"y": 1
|
||||
},
|
||||
"Max Frames Per File": 20000,
|
||||
"Frame Discard Policy": "nodiscard",
|
||||
"Frame Padding": 1,
|
||||
"Scan Parameters": "[disabled]",
|
||||
"Total Frames": 10,
|
||||
"Receiver Roi": {
|
||||
"xmin": 4294967295,
|
||||
"xmax": 4294967295,
|
||||
"ymin": 4294967295,
|
||||
"ymax": 4294967295
|
||||
},
|
||||
"Exptime": "0ns",
|
||||
"Period": "0ns",
|
||||
"Burst Mode": "burst_internal",
|
||||
"Frames in File": 10,
|
||||
"Frame Header Format": {
|
||||
"Frame Number": "8 bytes",
|
||||
"SubFrame Number/ExpLength": "4 bytes",
|
||||
"Packet Number": "4 bytes",
|
||||
"Bunch ID": "8 bytes",
|
||||
"Timestamp": "8 bytes",
|
||||
"Module Id": "2 bytes",
|
||||
"Row": "2 bytes",
|
||||
"Column": "2 bytes",
|
||||
"Reserved": "2 bytes",
|
||||
"Debug": "4 bytes",
|
||||
"Round Robin Number": "2 bytes",
|
||||
"Detector Type": "1 byte",
|
||||
"Header Version": "1 byte",
|
||||
"Packets Caught Mask": "64 bytes"
|
||||
}
|
||||
}
|
||||
|
||||
Mythen3
|
||||
^^^^^^^
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
{
|
||||
"Version": 7.2,
|
||||
"Timestamp": "Wed Nov 13 14:39:14 2024",
|
||||
"Detector Type": "Mythen3",
|
||||
"Timing Mode": "auto",
|
||||
"Geometry": {
|
||||
"x": 1,
|
||||
"y": 1
|
||||
},
|
||||
"Image Size in bytes": 15360,
|
||||
"Pixels": {
|
||||
"x": 3840,
|
||||
"y": 1
|
||||
},
|
||||
"Max Frames Per File": 10000,
|
||||
"Frame Discard Policy": "nodiscard",
|
||||
"Frame Padding": 1,
|
||||
"Scan Parameters": "[disabled]",
|
||||
"Total Frames": 1,
|
||||
"Receiver Roi": {
|
||||
"xmin": 4294967295,
|
||||
"xmax": 4294967295,
|
||||
"ymin": 4294967295,
|
||||
"ymax": 4294967295
|
||||
},
|
||||
"Dynamic Range": 32,
|
||||
"Ten Giga": 1,
|
||||
"Period": "2ms",
|
||||
"Counter Mask": "0x7",
|
||||
"Exptime1": "0.1s",
|
||||
"Exptime2": "0.1s",
|
||||
"Exptime3": "0.1s",
|
||||
"GateDelay1": "0ns",
|
||||
"GateDelay2": "0ns",
|
||||
"GateDelay3": "0ns",
|
||||
"Gates": 1,
|
||||
"Threshold Energies": "[-1, -1, -1]",
|
||||
"Frames in File": 1,
|
||||
"Frame Header Format": {
|
||||
"Frame Number": "8 bytes",
|
||||
"SubFrame Number/ExpLength": "4 bytes",
|
||||
"Packet Number": "4 bytes",
|
||||
"Bunch ID": "8 bytes",
|
||||
"Timestamp": "8 bytes",
|
||||
"Module Id": "2 bytes",
|
||||
"Row": "2 bytes",
|
||||
"Column": "2 bytes",
|
||||
"Reserved": "2 bytes",
|
||||
"Debug": "4 bytes",
|
||||
"Round Robin Number": "2 bytes",
|
||||
"Detector Type": "1 byte",
|
||||
"Header Version": "1 byte",
|
||||
"Packets Caught Mask": "64 bytes"
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Moench
|
||||
^^^^^^
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
{
|
||||
"Version": 7.2,
|
||||
"Timestamp": "Wed Nov 13 14:41:32 2024",
|
||||
"Detector Type": "Moench",
|
||||
"Timing Mode": "auto",
|
||||
"Geometry": {
|
||||
"x": 1,
|
||||
"y": 1
|
||||
},
|
||||
"Image Size in bytes": 320000,
|
||||
"Pixels": {
|
||||
"x": 400,
|
||||
"y": 400
|
||||
},
|
||||
"Max Frames Per File": 100000,
|
||||
"Frame Discard Policy": "discardpartial",
|
||||
"Frame Padding": 1,
|
||||
"Scan Parameters": "[disabled]",
|
||||
"Total Frames": 1,
|
||||
"Receiver Roi": {
|
||||
"xmin": 4294967295,
|
||||
"xmax": 4294967295,
|
||||
"ymin": 4294967295,
|
||||
"ymax": 4294967295
|
||||
},
|
||||
"Exptime": "10us",
|
||||
"Period": "2ms",
|
||||
"Number of UDP Interfaces": 1,
|
||||
"Number of rows": 400,
|
||||
"Frames in File": 1,
|
||||
"Frame Header Format": {
|
||||
"Frame Number": "8 bytes",
|
||||
"SubFrame Number/ExpLength": "4 bytes",
|
||||
"Packet Number": "4 bytes",
|
||||
"Bunch ID": "8 bytes",
|
||||
"Timestamp": "8 bytes",
|
||||
"Module Id": "2 bytes",
|
||||
"Row": "2 bytes",
|
||||
"Column": "2 bytes",
|
||||
"Reserved": "2 bytes",
|
||||
"Debug": "4 bytes",
|
||||
"Round Robin Number": "2 bytes",
|
||||
"Detector Type": "1 byte",
|
||||
"Header Version": "1 byte",
|
||||
"Packets Caught Mask": "64 bytes"
|
||||
}
|
||||
}
|
||||
|
||||
Gotthard I
|
||||
^^^^^^^^^^^
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
{
|
||||
"Version": 7.2,
|
||||
"Timestamp": "Wed Nov 13 15:16:19 2024",
|
||||
"Detector Type": "Gotthard",
|
||||
"Timing Mode": "auto",
|
||||
"Geometry": {
|
||||
"x": 1,
|
||||
"y": 1
|
||||
},
|
||||
"Image Size in bytes": 2560,
|
||||
"Pixels": {
|
||||
"x": 1280,
|
||||
"y": 1
|
||||
},
|
||||
"Max Frames Per File": 20000,
|
||||
"Frame Discard Policy": "nodiscard",
|
||||
"Frame Padding": 1,
|
||||
"Scan Parameters": "[disabled]",
|
||||
"Total Frames": 1,
|
||||
"Receiver Roi": {
|
||||
"xmin": 4294967295,
|
||||
"xmax": 4294967295,
|
||||
"ymin": 4294967295,
|
||||
"ymax": 4294967295
|
||||
},
|
||||
"Exptime": "1.00001ms",
|
||||
"Period": "1s",
|
||||
"Detector Roi": {
|
||||
"xmin": 4294967295,
|
||||
"xmax": 4294967295
|
||||
},
|
||||
"Frames in File": 1,
|
||||
"Frame Header Format": {
|
||||
"Frame Number": "8 bytes",
|
||||
"SubFrame Number/ExpLength": "4 bytes",
|
||||
"Packet Number": "4 bytes",
|
||||
"Bunch ID": "8 bytes",
|
||||
"Timestamp": "8 bytes",
|
||||
"Module Id": "2 bytes",
|
||||
"Row": "2 bytes",
|
||||
"Column": "2 bytes",
|
||||
"Reserved": "2 bytes",
|
||||
"Debug": "4 bytes",
|
||||
"Round Robin Number": "2 bytes",
|
||||
"Detector Type": "1 byte",
|
||||
"Header Version": "1 byte",
|
||||
"Packets Caught Mask": "64 bytes"
|
||||
}
|
||||
}
|
||||
|
||||
Chip Test Board
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
{
|
||||
"Version": 7.2,
|
||||
"Timestamp": "Wed Nov 13 15:32:59 2024",
|
||||
"Detector Type": "ChipTestBoard",
|
||||
"Timing Mode": "auto",
|
||||
"Geometry": {
|
||||
"x": 1,
|
||||
"y": 1
|
||||
},
|
||||
"Image Size in bytes": 48018,
|
||||
"Pixels": {
|
||||
"x": 3,
|
||||
"y": 1
|
||||
},
|
||||
"Max Frames Per File": 20000,
|
||||
"Frame Discard Policy": "nodiscard",
|
||||
"Frame Padding": 1,
|
||||
"Scan Parameters": "[disabled]",
|
||||
"Total Frames": 1,
|
||||
"Receiver Roi": {
|
||||
"xmin": 4294967295,
|
||||
"xmax": 4294967295,
|
||||
"ymin": 4294967295,
|
||||
"ymax": 4294967295
|
||||
},
|
||||
"Exptime": "0ns",
|
||||
"Period": "0.18s",
|
||||
"Ten Giga": 0,
|
||||
"ADC Mask": "0x2202",
|
||||
"Analog Flag": 1,
|
||||
"Analog Samples": 8003,
|
||||
"Digital Flag": 0,
|
||||
"Digital Samples": 1000,
|
||||
"Dbit Offset": 0,
|
||||
"Dbit Bitset": 0,
|
||||
"Transceiver Mask": "0x3",
|
||||
"Transceiver Flag": 0,
|
||||
"Transceiver Samples": 1,
|
||||
"Frames in File": 1,
|
||||
"Frame Header Format": {
|
||||
"Frame Number": "8 bytes",
|
||||
"SubFrame Number/ExpLength": "4 bytes",
|
||||
"Packet Number": "4 bytes",
|
||||
"Bunch ID": "8 bytes",
|
||||
"Timestamp": "8 bytes",
|
||||
"Module Id": "2 bytes",
|
||||
"Row": "2 bytes",
|
||||
"Column": "2 bytes",
|
||||
"Reserved": "2 bytes",
|
||||
"Debug": "4 bytes",
|
||||
"Round Robin Number": "2 bytes",
|
||||
"Detector Type": "1 byte",
|
||||
"Header Version": "1 byte",
|
||||
"Packets Caught Mask": "64 bytes"
|
||||
}
|
||||
}
|
@ -8,7 +8,7 @@ Commands can be used either with sls_detector_get or sls_detector_put
|
||||
|
||||
.. code-block::
|
||||
|
||||
sls_detector_get vrf
|
||||
sls_detector_get exptime
|
||||
|
||||
Help
|
||||
--------
|
||||
@ -24,6 +24,16 @@ Help
|
||||
# get help for a particular command
|
||||
sls_detector_get -h fpath
|
||||
sls_detector_help fpath
|
||||
|
||||
# list of deprecated commands
|
||||
list deprecated
|
||||
|
||||
# autocompletion
|
||||
# bash_autocomplete.sh or zsh_autocomplete.sh must be sourced from the
|
||||
# main package folder to enable auto completion of commands and arguments
|
||||
# for the command line on that shell.
|
||||
source bash_autocomplete.sh
|
||||
|
||||
|
||||
|
||||
Commands
|
||||
@ -32,14 +42,14 @@ Commands
|
||||
.. include:: ../commands.rst
|
||||
|
||||
|
||||
Depreciated commands
|
||||
Deprecated commands
|
||||
------------------------
|
||||
|
||||
.. note ::
|
||||
All the dac commands are preceded with the **dac** command. Use command **daclist** to get correct list of dac command arguments for current detector.
|
||||
|
||||
.. csv-table:: Depreciated commands
|
||||
:file: ../depreciated.csv
|
||||
.. csv-table:: Deprecated commands
|
||||
:file: ../deprecated.csv
|
||||
:widths: 35, 35
|
||||
:header-rows: 1
|
||||
|
||||
|
@ -20,8 +20,8 @@ the shared libraries these are needed:
|
||||
Python bindings
|
||||
-----------------------
|
||||
|
||||
* Python > 3.6
|
||||
* pybind11 2.11.0 (packaged in libs)
|
||||
* Python >= 3.8
|
||||
* pybind11 2.13.6 (packaged in libs)
|
||||
|
||||
.. note ::
|
||||
|
||||
|
62
docs/src/fileformat.rst
Normal file
62
docs/src/fileformat.rst
Normal file
@ -0,0 +1,62 @@
|
||||
File format
|
||||
================================
|
||||
|
||||
If `fwrite <commandline.html#term-fwrite-0-1>`_ is enabled, the receiver will write data to files.
|
||||
|
||||
Number of Files
|
||||
----------------
|
||||
|
||||
Every acquisition will create a master file and data files.
|
||||
|
||||
An acquisition can have multiple data files for a single frame. The number of files is determined by the number of UDP ports per module and the number of modules.
|
||||
|
||||
* Every modules has its own receiver process. Every receiver process can have 1 or 2 UDP ports.
|
||||
* Each UDP port will create its own file. Therefore, each receiver can write 1 or 2 files.
|
||||
* So, for example a detector with 4 modules with 2 UDP ports each will create a total of 8 files with file names containing UDP port index **'_d0'** to **'_d7'**.
|
||||
|
||||
A new file containing **'_f[file_index]'** in file name is also created when reaching the maximum frames per file. Configured using `rx_framesperfile <commandline.html#term-rx_framesperfile-n_frames>`_.
|
||||
|
||||
.. _file name format:
|
||||
|
||||
Naming
|
||||
-------
|
||||
| Master File Name: [fpath]/[fname]_master_[findex].[ext]
|
||||
|
||||
|
||||
| Data File Name: [fpath]/[fname]_dx_fy_[findex].[ext]
|
||||
|
||||
* fpath: file path set using command `fpath <commandline.html#term-fpath-path>`_. Default: '/'
|
||||
* fname: file name prefix using command `fname <commandline.html#term-fname-name>`_. Default: "run"
|
||||
* findex: acquisition index using command `findex <commandline.html#term-findex-n_value>`_. Automatically incremented for every acquisition with `sls_detector_acquire <commandline.html#term-acquire>`_ (if `fwrite <commandline.html#term-fwrite-0-1>`_ enabled).
|
||||
* x: unique udp port index. New file per UDP port.
|
||||
* y: file index. New file created after reaching max frames per file.
|
||||
* ext: file extension. Default: "raw"(data file) or "json"(master file)
|
||||
|
||||
|
||||
Some file name examples:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
# first file
|
||||
path-to-file/run_d0_f0_0.raw
|
||||
|
||||
# first file for second UDP port
|
||||
path-to-file/run_d1_f0_0.raw
|
||||
|
||||
# second file after reaching max frames in first file
|
||||
path-to-file/run_d0_f1_0.raw
|
||||
|
||||
# second acquisition, first file
|
||||
path-to-file/run_d0_f0_1.raw
|
||||
|
||||
|
||||
Formats
|
||||
--------
|
||||
|
||||
There are 2 file formats supported by the receiver:
|
||||
|
||||
* Binary - extension .json (master file) or .raw (data files)
|
||||
* HDF5 - extension .h5
|
||||
|
||||
The default is binary. HDF5 can be enabled by compiling the package with HDF5 option enabled. The file format is set using the command `fformat <commandline.html#term-fformat-binary-hdf5>`_.
|
||||
|
@ -98,7 +98,7 @@ Upgrade
|
||||
|
||||
* 6.1.2 server has a fix for seamless fpga programming
|
||||
|
||||
* We recommend first updating the on-board detector server to 6.1.2 (with client 6.1.x) using command 'updatedetectorserver' or 'copydetectorserver'.
|
||||
* We recommend first updating the on-board detector server to 6.1.2 (with client 6.1.x) using command `updatedetectorserver <commandline.html#term-updatedetectorserver-server_name-with-full-path>`_.
|
||||
|
||||
* Then use command 'programfpga' to only update firmware or use command 'update' to update firmware and server to the latest release.
|
||||
|
||||
@ -257,7 +257,7 @@ Upgrade
|
||||
|
||||
* 6.1.2 server has a fix for seamless fpga programming
|
||||
|
||||
* We recommend first updating the on-board detector server to 6.1.2 (with client 6.1.x) using command 'updatedetectorserver' or 'copydetectorserver'.
|
||||
* We recommend first updating the on-board detector server to 6.1.2 (with client 6.1.x) using command `updatedetectorserver <commandline.html#term-updatedetectorserver-server_name-with-full-path>`_.
|
||||
|
||||
* Then use command 'programfpga' to only update firmware or use command 'update' to update firmware and server to the latest release.
|
||||
|
||||
|
@ -11,7 +11,7 @@
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "CmdProxy.h"
|
||||
#include "Caller.h"
|
||||
#include "sls/Detector.h"
|
||||
#include "sls/sls_detector_defs.h"
|
||||
|
||||
@ -37,8 +37,8 @@ int main() {
|
||||
|
||||
std::cout << "Generating command line documentation!\n";
|
||||
|
||||
sls::CmdProxy proxy(nullptr);
|
||||
auto commands = proxy.GetProxyCommands();
|
||||
sls::Caller caller(nullptr);
|
||||
auto commands = caller.getAllCommands();
|
||||
|
||||
std::ofstream fs("commands.rst");
|
||||
fs << ".. glossary::\n";
|
||||
@ -46,7 +46,7 @@ int main() {
|
||||
for (const auto &cmd : commands) {
|
||||
std::ostringstream os;
|
||||
std::cout << cmd << '\n';
|
||||
proxy.Call(cmd, {}, -1, slsDetectorDefs::HELP_ACTION, os);
|
||||
caller.call(cmd, {}, -1, slsDetectorDefs::HELP_ACTION, os);
|
||||
|
||||
auto tmp = os.str().erase(0, cmd.size());
|
||||
auto usage = tmp.substr(0, tmp.find_first_of('\n'));
|
||||
@ -55,9 +55,9 @@ int main() {
|
||||
fs << '\t' << cmd << usage << help << "\n";
|
||||
}
|
||||
|
||||
std::ofstream fs2("depreciated.csv");
|
||||
std::ofstream fs2("deprecated.csv");
|
||||
fs2 << "Old, New\n";
|
||||
auto cmds = proxy.GetDepreciatedCommands();
|
||||
auto cmds = caller.GetDeprecatedCommands();
|
||||
for (auto it : cmds) {
|
||||
fs2 << it.first << ", " << it.second << '\n';
|
||||
}
|
||||
|
89
docs/src/hdf5fileformat.rst
Normal file
89
docs/src/hdf5fileformat.rst
Normal file
@ -0,0 +1,89 @@
|
||||
|
||||
|
||||
HDF5 File Format
|
||||
================================
|
||||
|
||||
Compilation
|
||||
-------------
|
||||
|
||||
#. Compile the package with HDF5 option enabled
|
||||
|
||||
#. Using cmk script: ./cmk.sh -hj9 -d [path of hdf5 dir] (-d is optional and for custom installation folder)
|
||||
|
||||
#. Enable using cmake option **-DSLS_USE_HDF5=ON** and **-DCMAKE_INSTALL_PREFIX=/path/to/custom/hdf/installation** (optional).
|
||||
|
||||
|
||||
Setup
|
||||
-------
|
||||
|
||||
#. Start Receiver process
|
||||
|
||||
#. Load config file
|
||||
|
||||
#. Set file format using command `fformat <commandline.html#term-fformat-binary-hdf5>`_.
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
sls_detector_put fformat hdf5
|
||||
|
||||
|
||||
Master File
|
||||
-------------
|
||||
|
||||
* File Name: [fpath]/[fname]_master_[findex].h5 :ref:`Details here<file name format>`
|
||||
|
||||
* It contains :ref:`attributes<master file attributes>` relevant to the acquisition. This can vary with detector type.
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
/ # Root level
|
||||
|---> entry # entry group
|
||||
| |---> data # data group
|
||||
| |---> column # dataset of each sls_receiver_header member
|
||||
| |---> data
|
||||
| |---> detector header version
|
||||
| |---> detector specific 1
|
||||
| |---> detector specific 2
|
||||
| |---> detector specific 3
|
||||
| |---> detector specific 4
|
||||
| |---> detector type
|
||||
| |---> exp length or sub exposure time
|
||||
| |---> frame number
|
||||
| |---> mod id
|
||||
| |---> packets caught
|
||||
| |---> packets caught bit mask
|
||||
| |---> row
|
||||
| |---> timestamp
|
||||
| |---> instrument # instrument group
|
||||
| |---> beam # beam group
|
||||
| |---> detector # detector group
|
||||
| |---> Master File Attribute 1 # dataset of each master file attribute
|
||||
| |---> Master File Attribute 2
|
||||
| |---> Master File Attribute 3
|
||||
| |---> Master File Attribute ..
|
||||
| |---> sample # sample group
|
||||
|
||||
|
||||
If more than 1 data file per frame:
|
||||
* The dataset of each :ref:`**SLS Receiver Header** <sls receiver header format>` member is a virtual dataset.
|
||||
* **data** dataset is a virtual dataset.
|
||||
|
||||
|
||||
More details regarding master file attributes can be found :ref:`here<master file attributes>`.
|
||||
|
||||
Data File
|
||||
-----------
|
||||
|
||||
* File Name: [fpath]/[fname]_dx_fy_[findex].h5 :ref:`Details here<file name format>`
|
||||
|
||||
|
||||
Virtual Data File
|
||||
------------------
|
||||
|
||||
* File Name: [fpath]/[fname]_virtual_[findex].h5 :ref:`Details here<file name format>`
|
||||
|
||||
* For multiple modules, a virtual file linking data from all the modules is created. The individual files are expected to be present.
|
||||
|
||||
* It is linked in the master file.
|
||||
|
||||
|
@ -12,7 +12,7 @@ Welcome to slsDetectorPackage's documentation!
|
||||
For further documentation, visit the official page: https://www.psi.ch/en/detectors/documentation
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 1
|
||||
:maxdepth: 3
|
||||
:caption: Installation:
|
||||
|
||||
installation
|
||||
@ -82,6 +82,22 @@ Welcome to slsDetectorPackage's documentation!
|
||||
receivers
|
||||
slsreceiver
|
||||
|
||||
.. toctree::
|
||||
:caption: Receiver Files
|
||||
:maxdepth: 3
|
||||
|
||||
fileformat
|
||||
slsreceiverheaderformat
|
||||
masterfileattributes
|
||||
binaryfileformat
|
||||
hdf5fileformat
|
||||
|
||||
.. toctree::
|
||||
:caption: Receiver ZMQ Stream
|
||||
:maxdepth: 2
|
||||
|
||||
zmqjsonheaderformat
|
||||
|
||||
.. toctree::
|
||||
:caption: Troubleshooting
|
||||
|
||||
|
@ -1,9 +1,4 @@
|
||||
.. warning ::
|
||||
|
||||
Before building from source make sure that you have the
|
||||
:doc:`dependencies <../dependencies>` installed. If installing using conda, conda will
|
||||
manage the dependencies. Avoid also installing packages with pip.
|
||||
|
||||
|
||||
|
||||
.. _Installation:
|
||||
|
||||
@ -11,8 +6,18 @@
|
||||
Installation
|
||||
===============
|
||||
|
||||
One can either install pre-built binaries using conda or build from source.
|
||||
|
||||
.. warning ::
|
||||
|
||||
Before building from source make sure that you have the
|
||||
:doc:`dependencies <../dependencies>` installed. If installing using conda, conda will
|
||||
manage the dependencies. Avoid also installing packages with pip.
|
||||
|
||||
|
||||
|
||||
Install binaries using conda
|
||||
-------------------------------
|
||||
----------------------------------
|
||||
|
||||
Conda is not only useful to manage python environments but can also
|
||||
be used as a user space package manager. Dates in the tag (for eg. 2020.07.23.dev0)
|
||||
@ -55,7 +60,7 @@ We have three different packages available:
|
||||
|
||||
|
||||
Build from source
|
||||
-------------------
|
||||
----------------------
|
||||
|
||||
1. Download Source Code from github
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@ -75,8 +80,10 @@ Build from source
|
||||
2. Build from Source
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
One can either build using cmake or use the in-built cmk.sh script.
|
||||
|
||||
Build using CMake
|
||||
^^^^^^^^^^^^^^^^^^^^^^
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
@ -103,7 +110,7 @@ Instead of the cmake command, one can use ccmake to get a list of options to con
|
||||
ccmake ..
|
||||
|
||||
# choose the options
|
||||
# first press [c] - configure (maybe multiple times till you see [g])
|
||||
# first press [c] - configure (until you see [g])
|
||||
# then press [g] - generate
|
||||
|
||||
|
||||
@ -123,7 +130,7 @@ Example cmake options Comment
|
||||
|
||||
|
||||
Build using in-built cmk.sh script
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
|
||||
.. code-block:: bash
|
||||
@ -173,7 +180,7 @@ Build using in-built cmk.sh script
|
||||
|
||||
|
||||
Build on old distributions
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
If your linux distribution doesn't come with a C++11 compiler (gcc>4.8) then
|
||||
it's possible to install a newer gcc using conda and build the slsDetectorPackage
|
||||
@ -198,9 +205,10 @@ using this compiler
|
||||
|
||||
|
||||
Build slsDetectorGui (Qt5)
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
1. Using pre-built binary on conda
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
conda create -n myenv slsdetgui=7.0.0
|
||||
@ -208,13 +216,22 @@ Build slsDetectorGui (Qt5)
|
||||
|
||||
|
||||
2. Using system installation on RHEL7
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
yum install qt5-qtbase-devel.x86_64
|
||||
yum install qt5-qtsvg-devel.x86_64
|
||||
|
||||
3. Using system installation on RHEL8
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
yum install qt5-qtbase-devel.x86_64
|
||||
yum install qt5-qtsvg-devel.x86_64
|
||||
yum install expat-devel.x86_64
|
||||
|
||||
4. Using conda
|
||||
|
||||
3. Using conda
|
||||
.. code-block:: bash
|
||||
|
||||
#Add channels for dependencies and our library
|
||||
@ -249,7 +266,7 @@ Build slsDetectorGui (Qt5)
|
||||
|
||||
|
||||
Build this documentation
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
The documentation for the slsDetectorPackage is build using a combination
|
||||
of Doxygen, Sphinx and Breathe. The easiest way to install the dependencies
|
||||
@ -272,16 +289,18 @@ is to use conda
|
||||
|
||||
|
||||
Pybind and Zeromq
|
||||
^^^^^^^^^^^^^^^^^^^
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
.. _pybind for different slsDetectorPackage versions:
|
||||
|
||||
|
||||
| **Pybind for Python**
|
||||
| v8.0.0+:
|
||||
| pybind11 (v2.11.0) is built
|
||||
| * by default from tar file in repo (libs/pybind/v2.11.0.tar.gz)
|
||||
| **Pybind11 for Python**
|
||||
| v8.0.0+:
|
||||
| pybind11 is built
|
||||
| * by default from tar file in repo (libs/pybind/v2.1x.0.tar.gz)
|
||||
| * or use advanced option SLS_FETCH_PYBIND11_FROM_GITHUB [`link <https://github.com/pybind/pybind11>`__].
|
||||
| * v9.0.0+: pybind11 (v2.13.6)
|
||||
| * v8.x.x : pybind11 (v2.11.0)
|
||||
|
|
||||
| v7.x.x:
|
||||
| pybind11 packaged into 'libs/pybind'. No longer a submodule. No need for "recursive" or "submodule update".
|
||||
@ -312,7 +331,7 @@ Pybind and Zeromq
|
||||
| * or use advanced option SLS_FETCH_ZMQ_FROM_GITHUB [`link <https://github.com/zeromq/libzmq.git>`__].
|
||||
|
|
||||
| v7.x.x and older:
|
||||
| zeromq must be installed and one can hint its location using
|
||||
| zeromq-devel must be installed and one can hint its location using
|
||||
| * cmake option:'-DZeroMQ_HINT=/usr/lib64' or
|
||||
| * option '-q' in cmk.sh script: : ./cmk.sh -cbj5 -q /usr/lib64
|
||||
| * 'zeromq' dependency added when installing using conda
|
||||
|
408
docs/src/masterfileattributes.rst
Normal file
408
docs/src/masterfileattributes.rst
Normal file
@ -0,0 +1,408 @@
|
||||
|
||||
.. _master file attributes:
|
||||
Master File Attributes
|
||||
=======================
|
||||
|
||||
These attributes are the same in binary and HDF5 file, but vary depending on detector type.
|
||||
|
||||
|
||||
Eiger
|
||||
^^^^^
|
||||
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| **Key** | **Description** |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Version | Version of the master file |
|
||||
| | Current value:8.0 |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Timestamp | Timestamp of creation of master file |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Detector Type | Detector type |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Timing Mode | Timing Mode |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Geometry | Number of UDP ports in x and y dimension for |
|
||||
| | complete detector |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Image Size in bytes | Image size in bytes per UDP port |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Pixels | Number of pixels in x and y dimension |
|
||||
| | per UDP port |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Max Frames Per File | Maximum frames per file |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Frame Discard Policy | Receiever Frame discard policy |
|
||||
| | for partial frames |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Frame Padding | Receiver Frame padding enable |
|
||||
| | for partial frames |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Scan Parameters | Scanning mode on detector |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Total Frames | Total number of frames and triggers expected |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Receiver Roi | Receiver ROI in file including xmax and ymax |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Dynamic Range | Bits per pixel |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Ten Giga | 10GbE enable for data |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Exptime | Exposure time |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Period | Period between frames |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Threshold Energy | Threshold energy |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Sub Exptime | Sub exposure time in 32 bit mode |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Sub Period | Sub period between frames in 32 bit mode |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Quad | Quad enable (hardware) |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Number of rows | Number of rows enabled for readout |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Rate Corrections | Rate Corrections |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Frames in File | Number of frames written to file by Receiver 0 |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Frame Header Format | Expected frame header format for the data files |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
|
||||
|
||||
Jungfrau
|
||||
^^^^^^^^
|
||||
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| **Key** | **Description** |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Version | Version of the master file |
|
||||
| | Current value:8.0 |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Timestamp | Timestamp of creation of master file |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Detector Type | Detector type |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Timing Mode | Timing Mode |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Geometry | Number of UDP ports in x and y dimension for |
|
||||
| | complete detector |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Image Size in bytes | Image size in bytes per UDP port |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Pixels | Number of pixels in x and y dimension |
|
||||
| | per UDP port |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Max Frames Per File | Maximum frames per file |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Frame Discard Policy | Receiever Frame discard policy |
|
||||
| | for partial frames |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Frame Padding | Receiver Frame padding enable |
|
||||
| | for partial frames |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Scan Parameters | Scanning mode on detector |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Total Frames | Total number of frames and triggers expected |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Receiver Roi | Receiver ROI in file including xmax and ymax |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Exptime | Exposure time |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Period | Period between frames |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Number of UDP | Number of UDP Interfaces enabled per module |
|
||||
| Interfaces | |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Number of rows | Number of rows enabled for readout |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Frames in File | Number of frames written to file by Receiver 0 |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Frame Header Format | Expected frame header format for the data files |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
|
||||
Gotthard II
|
||||
^^^^^^^^^^^^
|
||||
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| **Key** | **Description** |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Version | Version of the master file |
|
||||
| | Current value:8.0 |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Timestamp | Timestamp of creation of master file |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Detector Type | Detector type |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Timing Mode | Timing Mode |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Geometry | Number of UDP ports in x and y dimension for |
|
||||
| | complete detector |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Image Size in bytes | Image size in bytes per UDP port |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Pixels | Number of pixels in x and y dimension |
|
||||
| | per UDP port |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Max Frames Per File | Maximum frames per file |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Frame Discard Policy | Receiever Frame discard policy |
|
||||
| | for partial frames |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Frame Padding | Receiver Frame padding enable |
|
||||
| | for partial frames |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Scan Parameters | Scanning mode on detector |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Total Frames | Total number of frames and triggers expected |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Receiver Roi | Receiver ROI in file including xmax and ymax |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Exptime | Exposure time |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Period | Period between frames |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Burst Mode | Burst mode of detector |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Frames in File | Number of frames written to file by Receiver 0 |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Frame Header Format | Expected frame header format for the data files |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
|
||||
Mythen3
|
||||
^^^^^^^
|
||||
|
||||
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| **Key** | **Description** |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Version | Version of the master file |
|
||||
| | Current value:8.0 |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Timestamp | Timestamp of creation of master file |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Detector Type | Detector type |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Timing Mode | Timing Mode |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Geometry | Number of UDP ports in x and y dimension for |
|
||||
| | complete detector |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Image Size in bytes | Image size in bytes per UDP port |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Pixels | Number of pixels in x and y dimension |
|
||||
| | per UDP port |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Max Frames Per File | Maximum frames per file |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Frame Discard Policy | Receiever Frame discard policy |
|
||||
| | for partial frames |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Frame Padding | Receiver Frame padding enable |
|
||||
| | for partial frames |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Scan Parameters | Scanning mode on detector |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Total Frames | Total number of frames and triggers expected |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Receiver Roi | Receiver ROI in file including xmax and ymax |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Dynamic Range | Bits per pixel |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Ten Giga | 10GbE enable for data |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Period | Period between frames |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Counter Mask | Mask of counters enabled |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Exptime1 | Exposure time of counter 1 |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Exptime2 | Exposure time of counter 2 |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Exptime3 | Exposure time of counter 3 |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| GateDelay1 | Gate delay of counter 1 |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| GateDelay2 | Gate delay of counter 2 |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| GateDelay3 | Gate delay of counter 3 |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Gates | Number of gates |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Threshold energies | Threshold energy of all 3 counters |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Frames in File | Number of frames written to file by Receiver 0 |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Frame Header Format | Expected frame header format for the data files |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
|
||||
|
||||
Moench
|
||||
^^^^^^
|
||||
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| **Key** | **Description** |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Version | Version of the master file |
|
||||
| | Current value:8.0 |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Timestamp | Timestamp of creation of master file |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Detector Type | Detector type |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Timing Mode | Timing Mode |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Geometry | Number of UDP ports in x and y dimension for |
|
||||
| | complete detector |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Image Size in bytes | Image size in bytes per UDP port |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Pixels | Number of pixels in x and y dimension |
|
||||
| | per UDP port |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Max Frames Per File | Maximum frames per file |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Frame Discard Policy | Receiever Frame discard policy |
|
||||
| | for partial frames |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Frame Padding | Receiver Frame padding enable |
|
||||
| | for partial frames |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Scan Parameters | Scanning mode on detector |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Total Frames | Total number of frames and triggers expected |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Receiver Roi | Receiver ROI in file including xmax and ymax |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Exptime | Exposure time |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Period | Period between frames |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Number of UDP | Number of UDP Interfaces enabled per module |
|
||||
| Interfaces | |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Number of rows | Number of rows enabled for readout |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Frames in File | Number of frames written to file by Receiver 0 |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Frame Header Format | Expected frame header format for the data files |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
|
||||
Gotthard I
|
||||
^^^^^^^^^^^
|
||||
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| **Key** | **Description** |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Version | Version of the master file |
|
||||
| | Current value:8.0 |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Timestamp | Timestamp of creation of master file |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Detector Type | Detector type |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Timing Mode | Timing Mode |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Geometry | Number of UDP ports in x and y dimension for |
|
||||
| | complete detector |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Image Size in bytes | Image size in bytes per UDP port |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Pixels | Number of pixels in x and y dimension |
|
||||
| | per UDP port |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Max Frames Per File | Maximum frames per file |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Frame Discard Policy | Receiever Frame discard policy |
|
||||
| | for partial frames |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Frame Padding | Receiver Frame padding enable |
|
||||
| | for partial frames |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Scan Parameters | Scanning mode on detector |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Total Frames | Total number of frames and triggers expected |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Receiver Roi | Receiver ROI in file including xmax and ymax |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Exptime | Exposure time |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Period | Period between frames |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Detector Roi | Roi in detector restricted to an ADC. |
|
||||
| | Includes xmax |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Burst Mode | Burst mode of detector |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Frames in File | Number of frames written to file by Receiver 0 |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Frame Header Format | Expected frame header format for the data files |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
|
||||
Chip Test Board
|
||||
^^^^^^^^^^^^^^^
|
||||
|
||||
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| **Key** | **Description** |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Version | Version of the master file |
|
||||
| | Current value:8.0 |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Timestamp | Timestamp of creation of master file |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Detector Type | Detector type |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Timing Mode | Timing Mode |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Geometry | Number of UDP ports in x and y dimension for |
|
||||
| | complete detector |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Image Size in bytes | Image size in bytes per UDP port |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Pixels | Number of pixels in x and y dimension |
|
||||
| | per UDP port |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Max Frames Per File | Maximum frames per file |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Frame Discard Policy | Receiever Frame discard policy |
|
||||
| | for partial frames |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Frame Padding | Receiver Frame padding enable |
|
||||
| | for partial frames |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Scan Parameters | Scanning mode on detector |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Total Frames | Total number of frames and triggers expected |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Receiver Roi | Receiver ROI in file including xmax and ymax |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Exptime | Exposure time |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Period | Period between frames |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Ten Giga | Ten giga enable |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| ADC Mask | Mask of channels enabled in ADC |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Analog Flag | Analog readout enable |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Analog Samples | Number of analog samples |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Digital Flag | Digital readout enable |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Digital Samples | Number of digital samples |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Dbit Offset | Digital offset of valid data in bytes |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Dbit Bitset | Digital 64 bit mask of bits enabled in receiver |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Transceiver Mask | Mask of channels enabled in Transceiver |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Transceiver Flag | Transceiver readout enable |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Transceiver Samples | Number of transceiver samples |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Frames in File | Number of frames written to file by Receiver 0 |
|
||||
+-----------------------+-------------------------------------------------+
|
||||
| Frame Header Format | Expected frame header format for the data files |
|
||||
+-----------------------+-------------------------------------------------+
|
@ -6,7 +6,7 @@ Getting Started
|
||||
Which Python?
|
||||
--------------------
|
||||
|
||||
We require at least Python 3.6 and strongly recommended that you don't use the system
|
||||
We require at least Python 3.8 and strongly recommended that you don't use the system
|
||||
Python installation. The examples in this documentation uses `conda
|
||||
<https://docs.conda.io/en/latest/miniconda.html>`_ since it provides good support
|
||||
also for non Python packages but there are also other alternatives like, pyenv.
|
||||
|
@ -91,245 +91,6 @@ Client Commands
|
||||
sls_detector_get -h rx_framescaught
|
||||
|
||||
|
||||
ZMQ: Json Header Format
|
||||
------------------------
|
||||
|
||||
|
||||
**Change in field names from slsDetectorPackage v6.x.x to v7.0.0**
|
||||
|
||||
* detSpec1 <- bunchId
|
||||
* detSpec2 <- reserved
|
||||
* detSpec3 <- debug
|
||||
* detSpec4 <- roundRNumber
|
||||
|
||||
|
||||
**Format**
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
{
|
||||
"jsonversion": unsigned int,
|
||||
"bitmode": unsigned int,
|
||||
"fileIndex": unsigned long int,
|
||||
"detshape": [
|
||||
unsigned int,
|
||||
unsigned int
|
||||
],
|
||||
"shape": [
|
||||
unsigned int,
|
||||
unsigned int
|
||||
],
|
||||
"size": unsigned int,
|
||||
"acqIndex": unsigned long int,
|
||||
"frameIndex": unsigned long int,
|
||||
"progress": double,
|
||||
"fname": string,
|
||||
"data": unsigned int,
|
||||
"completeImage": unsigned int,
|
||||
|
||||
"frameNumber": unsigned long long int,
|
||||
"expLength": unsigned int,
|
||||
"packetNumber": unsigned int,
|
||||
"detSpec1": unsigned long int,
|
||||
"timestamp": unsigned long int,
|
||||
"modId": unsigned int,
|
||||
"row": unsigned int,
|
||||
"column": unsigned int,
|
||||
"detSpec2": unsigned int,
|
||||
"detSpec3": unsigned int,
|
||||
"detSpec4": unsigned int,
|
||||
"detType": unsigned int,
|
||||
"version": unsigned int,
|
||||
|
||||
"flipRows": unsigned int,
|
||||
"quad": unsigned int,
|
||||
"addJsonHeader": {
|
||||
string : string
|
||||
}
|
||||
}
|
||||
|
||||
+--------------+----------------------------------------------+
|
||||
| Field | Description |
|
||||
+--------------+----------------------------------------------+
|
||||
| jsonversion | Version of the json header. |
|
||||
| | Value at 4 for v6.x.x and v7.x.x |
|
||||
+--------------+----------------------------------------------+
|
||||
| bitmode | Bits per pixel [4|8|16|32] |
|
||||
+--------------+----------------------------------------------+
|
||||
| fileIndex | Current file acquisition index |
|
||||
+--------------+----------------------------------------------+
|
||||
| detshape | Geometry of the entire detector |
|
||||
+--------------+----------------------------------------------+
|
||||
| shape | Geometry of the current port streamed out |
|
||||
+--------------+----------------------------------------------+
|
||||
| size | Size of image of current port in bytesout |
|
||||
+--------------+----------------------------------------------+
|
||||
| acqIndex | Frame number from the detector (redundant) |
|
||||
+--------------+----------------------------------------------+
|
||||
| frameIndex | Frame number of current acquisition |
|
||||
| | (Starting at 0) |
|
||||
+--------------+----------------------------------------------+
|
||||
| progress | Progress of current acquisition in % |
|
||||
+--------------+----------------------------------------------+
|
||||
| fname | Current file name |
|
||||
+--------------+----------------------------------------------+
|
||||
| data | 1 if there is data following |
|
||||
| | 0 if dummy header |
|
||||
+--------------+----------------------------------------------+
|
||||
| completeImage| 1 if no missing packets for this frame |
|
||||
| | in this port, else 0 |
|
||||
+--------------+----------------------------------------------+
|
||||
| frameNumber | Frame number |
|
||||
| | [From detector udp header] |
|
||||
+--------------+----------------------------------------------+
|
||||
| expLength | subframe number (32 bit eiger) |
|
||||
| | or real time exposure time in 100ns (others) |
|
||||
| | [From detector udp header] |
|
||||
+--------------+----------------------------------------------+
|
||||
| packetNumber | Number of packets caught for that frame |
|
||||
+--------------+----------------------------------------------+
|
||||
| detSpec1 | See :ref:`here<Detector Specific Fields>` |
|
||||
| | [From detector udp header] |
|
||||
+--------------+----------------------------------------------+
|
||||
| timestamp | Timestamp with 10 MHz clock |
|
||||
| | [From detector udp header] |
|
||||
+--------------+----------------------------------------------+
|
||||
| modId | Module Id |
|
||||
| | [From detector udp header] |
|
||||
+--------------+----------------------------------------------+
|
||||
| row | Row number in detector |
|
||||
| | [From detector udp header] |
|
||||
+--------------+----------------------------------------------+
|
||||
| column | Column number in detector |
|
||||
| | [From detector udp header] |
|
||||
+--------------+----------------------------------------------+
|
||||
| detSpec2 | See :ref:`here<Detector Specific Fields>` |
|
||||
| | [From detector udp header] |
|
||||
+--------------+----------------------------------------------+
|
||||
| detSpec3 | See :ref:`here<Detector Specific Fields>` |
|
||||
| | [From detector udp header] |
|
||||
+--------------+----------------------------------------------+
|
||||
| detSpec4 | See :ref:`here<Detector Specific Fields>` |
|
||||
| | [From detector udp header] |
|
||||
+--------------+----------------------------------------------+
|
||||
| detType | Detector type enum |
|
||||
| detSpec3 | See :ref:`Detector enum<Detector Enum>` |
|
||||
| | [From detector udp header] |
|
||||
+--------------+----------------------------------------------+
|
||||
| version | Detector header version. At 2 |
|
||||
| | [From detector udp header] |
|
||||
+--------------+----------------------------------------------+
|
||||
| flipRows | 1 if rows should be flipped. |
|
||||
| | Usually for Eiger bottom. |
|
||||
+--------------+----------------------------------------------+
|
||||
| quad | 1 if its an Eiger quad. |
|
||||
+--------------+----------------------------------------------+
|
||||
| addJsonHeader| Optional custom parameters that is required |
|
||||
| | for processing code. |
|
||||
+--------------+----------------------------------------------+
|
||||
|
||||
|
||||
SLS Receiver Header Format
|
||||
--------------------------
|
||||
|
||||
It is 112 bytes and consists of:
|
||||
* 48 bytes of the SLS Detector Header (described in :ref:`the current detector header <detector udp header>`)
|
||||
* 64 bytes of packet mask
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
typedef struct {
|
||||
uint64_t frameNumber;
|
||||
uint32_t expLength;
|
||||
uint32_t packetNumber;
|
||||
uint64_t detSpec1;
|
||||
uint64_t timestamp;
|
||||
uint16_t modId;
|
||||
uint16_t row;
|
||||
uint16_t column;
|
||||
uint16_t detSpec2;
|
||||
uint32_t detSpec3;
|
||||
uint16_t detSpec4;
|
||||
uint8_t detType;
|
||||
uint8_t version;
|
||||
} sls_detector_header;
|
||||
|
||||
struct sls_receiver_header {
|
||||
sls_detector_header detHeader; /**< is the detector header */
|
||||
sls_bitset packetsMask; /**< is the packets caught bit mask */
|
||||
};
|
||||
|
||||
|
||||
.. note ::
|
||||
|
||||
| The packetNumber in the SLS Receiver Header will be modified to number of packets caught by receiver for that frame. For eg. Jungfrau will have 128 packets per frame. If it is less, then this is a partial frame due to missing packets.
|
||||
|
||||
| Furthermore, the bit mask will specify which packets have been received.
|
||||
|
||||
|
||||
|
||||
|
||||
File format
|
||||
--------------
|
||||
|
||||
Master file is in json format.
|
||||
|
||||
The file name format is [fpath]/[fname]_dx_fy_[findex].raw, where x is module index and y is file index. **fname** is file name prefix and by default "run". **fpath** is '/' by default.
|
||||
|
||||
|
||||
Each acquisition will have an increasing acquisition index or findex (if file write enabled). This can be retrieved by using **findex** command.
|
||||
|
||||
|
||||
Each acquisition can have multiple files (the file index number **y**), with **rx_framesperfile** being the maximum number of frames per file. The default varies for each detector type.
|
||||
|
||||
|
||||
Some file name examples:
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
# first file
|
||||
path-to-file/run_d0_f0_0.raw
|
||||
|
||||
# second file after reaching max frames in first file
|
||||
path-to-file/run_d0_f1_0.raw
|
||||
|
||||
# second acquisition, first file
|
||||
path-to-file/run_d0_f0_1.raw
|
||||
|
||||
|
||||
Each acquisition will create a master file that can be enabled/disabled using **fmaster**. This should have parameters relevant to the acquisition.
|
||||
|
||||
|
||||
**Binary file format**
|
||||
|
||||
This is the default file format.
|
||||
|
||||
|
||||
Each data file will consist of frames, each consisting of slsReceiver Header followed by data for 1 frame.
|
||||
|
||||
|
||||
Master file is of ASCII format and will also include the format of the slsReceiver Header.
|
||||
|
||||
|
||||
**HDF5 file formats**
|
||||
|
||||
#. Compile the package with HDF5 option enabled
|
||||
|
||||
#. Using cmk script: ./cmk.sh -hj9 -d [path of hdf5 dir]
|
||||
|
||||
#. Enable using cmake **-DCMAKE_INSTALL_PREFIX=/path/to/hdf/installation** and **-DSLS_USE_HDF5=ON**
|
||||
|
||||
#. Start Receiver process
|
||||
|
||||
#. Load config file
|
||||
|
||||
#. Set file format from client or in config file
|
||||
.. code-block:: bash
|
||||
|
||||
sls_detector_put fformat hdf5
|
||||
|
||||
|
||||
| For multiple, modules, a virtual file linking all the modules is created. Both the data files and virtual files are linked in the master file.
|
||||
|
||||
|
||||
Performance
|
||||
|
40
docs/src/slsreceiverheaderformat.rst
Normal file
40
docs/src/slsreceiverheaderformat.rst
Normal file
@ -0,0 +1,40 @@
|
||||
|
||||
.. _sls receiver header format:
|
||||
|
||||
SLS Receiver Header Format
|
||||
====================================================
|
||||
|
||||
It is 112 bytes and consists of:
|
||||
* 48 bytes of the SLS Detector Header
|
||||
* 64 bytes of packet mask
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
typedef struct {
|
||||
uint64_t frameNumber;
|
||||
uint32_t expLength;
|
||||
uint32_t packetNumber;
|
||||
uint64_t detSpec1;
|
||||
uint64_t timestamp;
|
||||
uint16_t modId;
|
||||
uint16_t row;
|
||||
uint16_t column;
|
||||
uint16_t detSpec2;
|
||||
uint32_t detSpec3;
|
||||
uint16_t detSpec4;
|
||||
uint8_t detType;
|
||||
uint8_t version;
|
||||
} sls_detector_header;
|
||||
|
||||
struct sls_receiver_header {
|
||||
sls_detector_header detHeader; /**< is the detector header */
|
||||
sls_bitset packetsMask; /**< is the packets caught bit mask */
|
||||
};
|
||||
|
||||
|
||||
|
||||
| **sls_detector_header** (described in :ref:`the current detector header <detector udp header>`)
|
||||
|
||||
| The **packetNumber** from detector UDP header is modified in **sls_receiver_header** to number of packets caught by receiver for that frame and the bit mask for each packet caught is the **packetsMask**. The packetsMask is a total of 512 bits due to the largest number of packets per frame among our detectors.
|
||||
|
||||
| For eg. Jungfrau has 128 packets per frame. If **packetNumeber** is 128, then this frame is complete. If it is 127 or less, it is a partial frame due to missing packets. If one would still like to use it, the **packetsMask** will specify which packet has been received or is missing.
|
@ -394,6 +394,14 @@ Missing first frame or next frame after a delay
|
||||
Connect the data link from the Module directly to receiver pc or to a private network.
|
||||
|
||||
|
||||
Mythen3
|
||||
--------
|
||||
|
||||
Detector status is waiting even in auto timing mode
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
Check if the control board or the flat band cable is connected properly. If not, connect them properly and try again.
|
||||
|
||||
|
||||
Jungfrau
|
||||
---------
|
||||
|
||||
|
@ -3,7 +3,7 @@
|
||||
Format
|
||||
=======
|
||||
|
||||
The UDP data format for the packets consist of a common header for all detectors, followed by the data for that one packet.
|
||||
The UDP data format for the packets consist of a common header of 48 bytes for all detectors, followed by the data for that one packet.
|
||||
|
||||
|
||||
Current Version
|
||||
@ -11,6 +11,25 @@ Current Version
|
||||
|
||||
**v2.0 (slsDetectorPackage v7.0.0+)**
|
||||
|
||||
.. code-block:: cpp
|
||||
|
||||
typedef struct {
|
||||
uint64_t frameNumber;
|
||||
uint32_t expLength;
|
||||
uint32_t packetNumber;
|
||||
uint64_t detSpec1;
|
||||
uint64_t timestamp;
|
||||
uint16_t modId;
|
||||
uint16_t row;
|
||||
uint16_t column;
|
||||
uint16_t detSpec2;
|
||||
uint32_t detSpec3;
|
||||
uint16_t detSpec4;
|
||||
uint8_t detType;
|
||||
uint8_t version;
|
||||
} sls_detector_header;
|
||||
|
||||
|
||||
.. table:: <---------------------------------------------------- 8 bytes per row --------------------------------------------->
|
||||
:align: center
|
||||
:widths: 30,30,30,15,15
|
||||
@ -63,6 +82,8 @@ Description
|
||||
* **version**: current version of the detector header (0x2).
|
||||
|
||||
|
||||
.. _detector enum:
|
||||
|
||||
Detector Enum
|
||||
--------------
|
||||
|
||||
|
137
docs/src/zmqjsonheaderformat.rst
Normal file
137
docs/src/zmqjsonheaderformat.rst
Normal file
@ -0,0 +1,137 @@
|
||||
ZMQ: Json Header Format
|
||||
========================
|
||||
|
||||
|
||||
**Change in field names from slsDetectorPackage v6.x.x to v7.0.0**
|
||||
|
||||
* detSpec1 <- bunchId
|
||||
* detSpec2 <- reserved
|
||||
* detSpec3 <- debug
|
||||
* detSpec4 <- roundRNumber
|
||||
|
||||
|
||||
**Format**
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
{
|
||||
"jsonversion": unsigned int,
|
||||
"bitmode": unsigned int,
|
||||
"fileIndex": unsigned long int,
|
||||
"detshape": [
|
||||
unsigned int,
|
||||
unsigned int
|
||||
],
|
||||
"shape": [
|
||||
unsigned int,
|
||||
unsigned int
|
||||
],
|
||||
"size": unsigned int,
|
||||
"acqIndex": unsigned long int,
|
||||
"frameIndex": unsigned long int,
|
||||
"progress": double,
|
||||
"fname": string,
|
||||
"data": unsigned int,
|
||||
"completeImage": unsigned int,
|
||||
|
||||
"frameNumber": unsigned long long int,
|
||||
"expLength": unsigned int,
|
||||
"packetNumber": unsigned int,
|
||||
"detSpec1": unsigned long int,
|
||||
"timestamp": unsigned long int,
|
||||
"modId": unsigned int,
|
||||
"row": unsigned int,
|
||||
"column": unsigned int,
|
||||
"detSpec2": unsigned int,
|
||||
"detSpec3": unsigned int,
|
||||
"detSpec4": unsigned int,
|
||||
"detType": unsigned int,
|
||||
"version": unsigned int,
|
||||
|
||||
"flipRows": unsigned int,
|
||||
"quad": unsigned int,
|
||||
"addJsonHeader": {
|
||||
string : string
|
||||
}
|
||||
}
|
||||
|
||||
+--------------+----------------------------------------------+
|
||||
| Field | Description |
|
||||
+--------------+----------------------------------------------+
|
||||
| jsonversion | Version of the json header. |
|
||||
| | Value at 4 for v6.x.x and v7.x.x |
|
||||
+--------------+----------------------------------------------+
|
||||
| bitmode | Bits per pixel [4|8|16|32] |
|
||||
+--------------+----------------------------------------------+
|
||||
| fileIndex | Current file acquisition index |
|
||||
+--------------+----------------------------------------------+
|
||||
| detshape | Geometry of the entire detector |
|
||||
+--------------+----------------------------------------------+
|
||||
| shape | Geometry of the current port streamed out |
|
||||
+--------------+----------------------------------------------+
|
||||
| size | Size of image of current port in bytesout |
|
||||
+--------------+----------------------------------------------+
|
||||
| acqIndex | Frame number from the detector (redundant) |
|
||||
+--------------+----------------------------------------------+
|
||||
| frameIndex | Frame number of current acquisition |
|
||||
| | (Starting at 0) |
|
||||
+--------------+----------------------------------------------+
|
||||
| progress | Progress of current acquisition in % |
|
||||
+--------------+----------------------------------------------+
|
||||
| fname | Current file name |
|
||||
+--------------+----------------------------------------------+
|
||||
| data | 1 if there is data following |
|
||||
| | 0 if dummy header |
|
||||
+--------------+----------------------------------------------+
|
||||
| completeImage| 1 if no missing packets for this frame |
|
||||
| | in this port, else 0 |
|
||||
+--------------+----------------------------------------------+
|
||||
| frameNumber | Frame number |
|
||||
| | [From detector udp header] |
|
||||
+--------------+----------------------------------------------+
|
||||
| expLength | subframe number (32 bit eiger) |
|
||||
| | or real time exposure time in 100ns (others) |
|
||||
| | [From detector udp header] |
|
||||
+--------------+----------------------------------------------+
|
||||
| packetNumber | Number of packets caught for that frame |
|
||||
+--------------+----------------------------------------------+
|
||||
| detSpec1 | See :ref:`here<Detector Specific Fields>` |
|
||||
| | [From detector udp header] |
|
||||
+--------------+----------------------------------------------+
|
||||
| timestamp | Timestamp with 10 MHz clock |
|
||||
| | [From detector udp header] |
|
||||
+--------------+----------------------------------------------+
|
||||
| modId | Module Id |
|
||||
| | [From detector udp header] |
|
||||
+--------------+----------------------------------------------+
|
||||
| row | Row number in detector |
|
||||
| | [From detector udp header] |
|
||||
+--------------+----------------------------------------------+
|
||||
| column | Column number in detector |
|
||||
| | [From detector udp header] |
|
||||
+--------------+----------------------------------------------+
|
||||
| detSpec2 | See :ref:`here<Detector Specific Fields>` |
|
||||
| | [From detector udp header] |
|
||||
+--------------+----------------------------------------------+
|
||||
| detSpec3 | See :ref:`here<Detector Specific Fields>` |
|
||||
| | [From detector udp header] |
|
||||
+--------------+----------------------------------------------+
|
||||
| detSpec4 | See :ref:`here<Detector Specific Fields>` |
|
||||
| | [From detector udp header] |
|
||||
+--------------+----------------------------------------------+
|
||||
| detType | Detector type enum |
|
||||
| detSpec3 | See :ref:`Detector enum<detector enum>` |
|
||||
| | [From detector udp header] |
|
||||
+--------------+----------------------------------------------+
|
||||
| version | Detector header version. At 2 |
|
||||
| | [From detector udp header] |
|
||||
+--------------+----------------------------------------------+
|
||||
| flipRows | 1 if rows should be flipped. |
|
||||
| | Usually for Eiger bottom. |
|
||||
+--------------+----------------------------------------------+
|
||||
| quad | 1 if its an Eiger quad. |
|
||||
+--------------+----------------------------------------------+
|
||||
| addJsonHeader| Optional custom parameters that is required |
|
||||
| | for processing code. |
|
||||
+--------------+----------------------------------------------+
|
||||
|
Binary file not shown.
BIN
libs/pybind11/v2.13.6.tar.gz
Normal file
BIN
libs/pybind11/v2.13.6.tar.gz
Normal file
Binary file not shown.
@ -3,3 +3,12 @@ slsDetectorPackage/7.0.1_rh7 stable cmake/3.15.5 zeromq/4.3.4 Qt/5.12.10
|
||||
slsDetectorPackage/7.0.1_rh8 stable cmake/3.15.5 zeromq/4.3.4 Qt/5.12.10
|
||||
slsDetectorPackage/7.0.2_rh7 stable cmake/3.15.5 zeromq/4.3.4 Qt/5.12.10
|
||||
slsDetectorPackage/7.0.2_rh8 stable cmake/3.15.5 zeromq/4.3.4 Qt/5.12.10
|
||||
slsDetectorPackage/7.0.3_rh7 stable cmake/3.15.5 zeromq/4.3.4 Qt/5.12.10
|
||||
slsDetectorPackage/7.0.3_rh8 stable cmake/3.15.5 zeromq/4.3.4 Qt/5.12.10
|
||||
slsDetectorPackage/8.0.0_rh7 stable cmake/3.15.5 Qt/5.12.10
|
||||
slsDetectorPackage/8.0.0_rh8 stable cmake/3.15.5 Qt/5.12.10
|
||||
slsDetectorPackage/8.0.1_rh7 stable cmake/3.15.5 Qt/5.12.10
|
||||
slsDetectorPackage/8.0.1_rh8 stable cmake/3.15.5 Qt/5.12.10
|
||||
slsDetectorPackage/8.0.2_rh7 stable cmake/3.15.5 Qt/5.12.10
|
||||
slsDetectorPackage/8.0.2_rh8 stable cmake/3.15.5 Qt/5.12.10
|
||||
|
||||
|
35
pyctbgui/.github/workflows/build-and-test-inplace.yml
vendored
Normal file
35
pyctbgui/.github/workflows/build-and-test-inplace.yml
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
name: Build inplace, run tests and linting
|
||||
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: [ "3.10", "3.11"]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install ".[dev]"
|
||||
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi
|
||||
- name: Build C extension
|
||||
run: |
|
||||
make
|
||||
- name: Run tests using pytest
|
||||
run: |
|
||||
make test
|
||||
- name: check code formatting
|
||||
run: |
|
||||
make check_format
|
||||
- name: lint the code with ruff
|
||||
run: |
|
||||
make lint
|
133
pyctbgui/.gitignore
vendored
Normal file
133
pyctbgui/.gitignore
vendored
Normal file
@ -0,0 +1,133 @@
|
||||
nohup.out
|
||||
.idea/
|
||||
tests/.tmp
|
||||
run_*
|
||||
# Byte-compiled / optimized / DLL files
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
wheels/
|
||||
pip-wheel-metadata/
|
||||
share/python-wheels/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
MANIFEST
|
||||
|
||||
# PyInstaller
|
||||
# Usually these files are written by a python script from a template
|
||||
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
||||
*.manifest
|
||||
*.spec
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
htmlcov/
|
||||
.tox/
|
||||
.nox/
|
||||
.coverage
|
||||
.coverage.*
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
*.cover
|
||||
*.py,cover
|
||||
.hypothesis/
|
||||
.pytest_cache/
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
*.pot
|
||||
|
||||
# Django stuff:
|
||||
*.log
|
||||
local_settings.py
|
||||
db.sqlite3
|
||||
db.sqlite3-journal
|
||||
|
||||
# Flask stuff:
|
||||
instance/
|
||||
.webassets-cache
|
||||
|
||||
# Scrapy stuff:
|
||||
.scrapy
|
||||
|
||||
# Sphinx documentation
|
||||
docs/_build/
|
||||
|
||||
# PyBuilder
|
||||
target/
|
||||
|
||||
# Jupyter Notebook
|
||||
.ipynb_checkpoints
|
||||
|
||||
# IPython
|
||||
profile_default/
|
||||
ipython_config.py
|
||||
|
||||
# pyenv
|
||||
.python-version
|
||||
|
||||
# pipenv
|
||||
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
||||
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
||||
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
||||
# install all needed dependencies.
|
||||
#Pipfile.lock
|
||||
|
||||
# PEP 582; used by e.g. github.com/David-OConnor/pyflow
|
||||
__pypackages__/
|
||||
|
||||
# Celery stuff
|
||||
celerybeat-schedule
|
||||
celerybeat.pid
|
||||
|
||||
# SageMath parsed files
|
||||
*.sage.py
|
||||
|
||||
# Environments
|
||||
.env
|
||||
.venv
|
||||
env/
|
||||
venv/
|
||||
ENV/
|
||||
env.bak/
|
||||
venv.bak/
|
||||
|
||||
# Spyder project settings
|
||||
.spyderproject
|
||||
.spyproject
|
||||
|
||||
# Rope project settings
|
||||
.ropeproject
|
||||
|
||||
# mkdocs documentation
|
||||
/site
|
||||
|
||||
# mypy
|
||||
.mypy_cache/
|
||||
.dmypy.json
|
||||
dmypy.json
|
||||
|
||||
# Pyre type checker
|
||||
.pyre/
|
18
pyctbgui/.pre-commit-config.yaml
Normal file
18
pyctbgui/.pre-commit-config.yaml
Normal file
@ -0,0 +1,18 @@
|
||||
# See https://pre-commit.com for more information
|
||||
# See https://pre-commit.com/hooks.html for more hooks
|
||||
repos:
|
||||
- repo: https://github.com/google/yapf
|
||||
rev: v0.40.1
|
||||
hooks:
|
||||
- id: yapf
|
||||
name: yapf
|
||||
language: python
|
||||
entry: yapf
|
||||
args: [-i,--style,pyproject.toml]
|
||||
types: [python]
|
||||
|
||||
- repo: https://github.com/astral-sh/ruff-pre-commit
|
||||
# Ruff version.
|
||||
rev: v0.0.285
|
||||
hooks:
|
||||
- id: ruff
|
11
pyctbgui/CtbGui
Executable file
11
pyctbgui/CtbGui
Executable file
@ -0,0 +1,11 @@
|
||||
#!/usr/bin/env python3
|
||||
from PyQt5 import QtWidgets
|
||||
import sys
|
||||
|
||||
from pyctbgui.ui import MainWindow
|
||||
|
||||
if __name__ == "__main__":
|
||||
app = QtWidgets.QApplication(sys.argv)
|
||||
main = MainWindow()
|
||||
main.show()
|
||||
app.exec_()
|
2
pyctbgui/MANIFEST.in
Normal file
2
pyctbgui/MANIFEST.in
Normal file
@ -0,0 +1,2 @@
|
||||
include pyctbgui/ui/*.ui
|
||||
recursive-include src *.c *.h
|
39
pyctbgui/Makefile
Normal file
39
pyctbgui/Makefile
Normal file
@ -0,0 +1,39 @@
|
||||
# TODO! Add support for making the pkg?
|
||||
# Which tests should we have?
|
||||
|
||||
default: ext
|
||||
|
||||
ext: ## [DEFAULT] build c extension in place
|
||||
rm -rf build/ pyctbgui/_decoder.cpython*
|
||||
python setup.py build_ext --inplace
|
||||
|
||||
clean: ## Remove the build folder and the shared library
|
||||
rm -rf build/ pyctbgui/_decoder.cpython*
|
||||
|
||||
test: ## Run unit tests using pytest
|
||||
python -m pytest -v tests/unit
|
||||
|
||||
test_gui: ## Run E2E tests using pytest
|
||||
python -m pytest -v tests/gui
|
||||
|
||||
setup_gui_test: ## Setup the environment for the E2E tests
|
||||
ctbDetectorServer_virtual > /tmp/simulator.log 2>&1 &
|
||||
slsReceiver > /tmp/slsReceiver.log 2>&1 &
|
||||
sleep 3
|
||||
sls_detector_put config tests/gui/data/simulator.config
|
||||
|
||||
killall: ## Kill all the processes started by setup_gui_test
|
||||
killall slsReceiver ctbDetectorServer_virtual
|
||||
|
||||
|
||||
lint: ## run ruff linter to check formatting errors
|
||||
@ruff check tests pyctbgui *.py && echo "Ruff checks passed ✅"
|
||||
|
||||
format: ## format code inplace using style in pyproject.toml
|
||||
yapf --style pyproject.toml -m -r -i tests pyctbgui *.py
|
||||
|
||||
check_format: ## Check if source is formatted properly
|
||||
yapf --style pyproject.toml -r -d tests pyctbgui *.py
|
||||
|
||||
help: # from compiler explorer
|
||||
@grep -E '^[0-9a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}'
|
31
pyctbgui/README.md
Normal file
31
pyctbgui/README.md
Normal file
@ -0,0 +1,31 @@
|
||||
# New Chip Test Board Gui using Python
|
||||
Prototype for a new python based GUI for the Chip Test Board
|
||||
|
||||
|
||||
## Getting started
|
||||
|
||||
```bash
|
||||
git clone https://github.com/slsdetectorgroup/pyctbgui.git
|
||||
cd pyctbgui
|
||||
make #compiles the c extension inplace
|
||||
./CtbGui
|
||||
```
|
||||
|
||||
|
||||
## Display help for the Makefile
|
||||
|
||||
```
|
||||
$ make help
|
||||
check_format Check if source is formatted properly
|
||||
clean Remove the build folder and the shared library
|
||||
ext [DEFAULT] build c extension in place
|
||||
format format code inplace using style in pyproject.toml
|
||||
lint run ruff linter to check formatting errors
|
||||
test Run unit tests using pytest
|
||||
```
|
||||
|
||||
|
||||
## setup pre-commit hooks
|
||||
```
|
||||
pre-commit install
|
||||
```
|
73
pyctbgui/client.py
Normal file
73
pyctbgui/client.py
Normal file
@ -0,0 +1,73 @@
|
||||
import json
|
||||
import zmq
|
||||
import numpy as np
|
||||
|
||||
from slsdet import Detector
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
det = Detector()
|
||||
|
||||
zmqIp = det.zmqip
|
||||
zmqport = det.zmqport
|
||||
zmq_stream = det.rx_zmqstream
|
||||
|
||||
|
||||
def zmq_receiver():
|
||||
context = zmq.Context()
|
||||
socket = context.socket(zmq.SUB)
|
||||
socket.connect(f"tcp://{zmqIp}:{zmqport}")
|
||||
socket.subscribe("")
|
||||
|
||||
while True:
|
||||
msg = socket.recv_multipart()
|
||||
if len(msg) == 2:
|
||||
header, data = msg
|
||||
jsonHeader = json.loads(header)
|
||||
print(jsonHeader)
|
||||
print(f'Data size: {len(data)}')
|
||||
data_array = np.array(np.frombuffer(data, dtype=np.uint16))
|
||||
break
|
||||
return data_array
|
||||
|
||||
|
||||
def analog(data_array):
|
||||
adc_numbers = [
|
||||
9, 8, 11, 10, 13, 12, 15, 14, 1, 0, 3, 2, 5, 4, 7, 6, 23, 22, 21, 20, 19, 18, 17, 16, 31, 30, 29, 28, 27, 26,
|
||||
25, 24
|
||||
]
|
||||
|
||||
n_pixels_per_sc = 5000
|
||||
|
||||
sc_width = 25
|
||||
analog_frame = np.zeros((400, 400))
|
||||
order_sc = np.zeros((400, 400))
|
||||
|
||||
for n_pixel in range(n_pixels_per_sc):
|
||||
#these_dbits = int(digital_data[n_pixel])
|
||||
|
||||
for i_sc, adc_nr in enumerate(adc_numbers):
|
||||
# ANALOG
|
||||
col = ((adc_nr % 16) * sc_width) + (n_pixel % sc_width)
|
||||
if i_sc < 16:
|
||||
row = 199 - int(n_pixel / sc_width)
|
||||
else:
|
||||
row = 200 + int(n_pixel / sc_width)
|
||||
|
||||
index_min = n_pixel * 32 + i_sc
|
||||
|
||||
pixel_value = data_array[index_min]
|
||||
analog_frame[row, col] = pixel_value
|
||||
order_sc[row, col] = i_sc
|
||||
return analog_frame
|
||||
|
||||
|
||||
fig, ax = plt.subplots()
|
||||
data = analog(data_array=zmq_receiver())
|
||||
im = ax.imshow(data)
|
||||
ax.invert_yaxis()
|
||||
fig.colorbar(im)
|
||||
plt.show()
|
||||
# pg.image(data, title="test")
|
||||
|
||||
# if __name__ == '__main__':
|
||||
# pg.QtWidgets.QApplication.exec_()
|
2
pyctbgui/pyctbgui/__init__.py
Normal file
2
pyctbgui/pyctbgui/__init__.py
Normal file
@ -0,0 +1,2 @@
|
||||
from .utils.defines import Defines as defs
|
||||
from .utils import bit_utils, alias_utility
|
401
pyctbgui/pyctbgui/services/ADC.py
Normal file
401
pyctbgui/pyctbgui/services/ADC.py
Normal file
@ -0,0 +1,401 @@
|
||||
import logging
|
||||
import typing
|
||||
from functools import partial
|
||||
from pathlib import Path
|
||||
|
||||
import numpy as np
|
||||
from PyQt5 import QtWidgets, uic
|
||||
import pyqtgraph as pg
|
||||
from pyqtgraph import LegendItem
|
||||
|
||||
from pyctbgui.utils import decoder
|
||||
from pyctbgui.utils.bit_utils import bit_is_set, manipulate_bit
|
||||
from pyctbgui.utils.defines import Defines
|
||||
import pyctbgui.utils.pixelmap as pm
|
||||
from pyctbgui.utils.recordOrApplyPedestal import recordOrApplyPedestal
|
||||
|
||||
if typing.TYPE_CHECKING:
|
||||
from pyctbgui.services import AcquisitionTab, PlotTab
|
||||
|
||||
|
||||
class AdcTab(QtWidgets.QWidget):
|
||||
|
||||
def __init__(self, parent, *args, **kwargs):
|
||||
super().__init__(parent, *args, **kwargs)
|
||||
uic.loadUi(Path(__file__).parent.parent / 'ui' / "adc.ui", parent)
|
||||
self.view = parent
|
||||
self.mainWindow = None
|
||||
self.det = None
|
||||
self.plotTab: PlotTab | None = None
|
||||
self.acquisitionTab: AcquisitionTab | None = None
|
||||
self.legend: LegendItem | None = None
|
||||
self.logger = logging.getLogger('AdcTab')
|
||||
|
||||
def setup_ui(self):
|
||||
self.plotTab = self.mainWindow.plotTab
|
||||
self.acquisitionTab = self.mainWindow.acquisitionTab
|
||||
for i in range(Defines.adc.count):
|
||||
self.setADCButtonColor(i, self.plotTab.getRandomColor())
|
||||
self.initializeAllAnalogPlots()
|
||||
|
||||
self.legend = self.mainWindow.plotAnalogWaveform.getPlotItem().legend
|
||||
self.legend.clear()
|
||||
# subscribe to toggle legend
|
||||
self.plotTab.subscribeToggleLegend(self.updateLegend)
|
||||
|
||||
def initializeAllAnalogPlots(self):
|
||||
self.mainWindow.plotAnalogWaveform = pg.plot()
|
||||
self.mainWindow.plotAnalogWaveform.addLegend(colCount=Defines.colCount)
|
||||
self.mainWindow.verticalLayoutPlot.addWidget(self.mainWindow.plotAnalogWaveform, 1)
|
||||
self.mainWindow.analogPlots = {}
|
||||
waveform = np.zeros(1000)
|
||||
for i in range(Defines.adc.count):
|
||||
pen = pg.mkPen(color=self.getADCButtonColor(i), width=1)
|
||||
legendName = getattr(self.view, f"labelADC{i}").text()
|
||||
self.mainWindow.analogPlots[i] = self.mainWindow.plotAnalogWaveform.plot(waveform,
|
||||
pen=pen,
|
||||
name=legendName)
|
||||
self.mainWindow.analogPlots[i].hide()
|
||||
|
||||
self.mainWindow.plotAnalogImage = pg.ImageView()
|
||||
self.mainWindow.nAnalogRows = 0
|
||||
self.mainWindow.nAnalogCols = 0
|
||||
self.mainWindow.analog_frame = np.zeros((self.mainWindow.nAnalogRows, self.mainWindow.nAnalogCols))
|
||||
self.mainWindow.plotAnalogImage.getView().invertY(False)
|
||||
self.mainWindow.plotAnalogImage.setImage(self.mainWindow.analog_frame)
|
||||
self.mainWindow.verticalLayoutPlot.addWidget(self.mainWindow.plotAnalogImage, 2)
|
||||
|
||||
def connect_ui(self):
|
||||
for i in range(Defines.adc.count):
|
||||
getattr(self.view, f"checkBoxADC{i}Inv").stateChanged.connect(partial(self.setADCInv, i))
|
||||
getattr(self.view, f"checkBoxADC{i}En").stateChanged.connect(partial(self.setADCEnable, i))
|
||||
getattr(self.view, f"checkBoxADC{i}Plot").stateChanged.connect(partial(self.setADCEnablePlot, i))
|
||||
getattr(self.view, f"pushButtonADC{i}").clicked.connect(partial(self.selectADCColor, i))
|
||||
self.view.checkBoxADC0_15En.stateChanged.connect(partial(self.setADCEnableRange, 0, Defines.adc.half))
|
||||
self.view.checkBoxADC16_31En.stateChanged.connect(
|
||||
partial(self.setADCEnableRange, Defines.adc.half, Defines.adc.count))
|
||||
self.view.checkBoxADC0_15Plot.stateChanged.connect(partial(self.setADCEnablePlotRange, 0, Defines.adc.half))
|
||||
self.view.checkBoxADC16_31Plot.stateChanged.connect(
|
||||
partial(self.setADCEnablePlotRange, Defines.adc.half, Defines.adc.count))
|
||||
self.view.checkBoxADC0_15Inv.stateChanged.connect(partial(self.setADCInvRange, 0, Defines.adc.half))
|
||||
self.view.checkBoxADC16_31Inv.stateChanged.connect(
|
||||
partial(self.setADCInvRange, Defines.adc.half, Defines.adc.count))
|
||||
self.view.lineEditADCInversion.editingFinished.connect(self.setADCInvReg)
|
||||
self.view.lineEditADCEnable.editingFinished.connect(self.setADCEnableReg)
|
||||
|
||||
def refresh(self):
|
||||
self.updateADCNames()
|
||||
self.updateADCInv()
|
||||
self.updateADCEnable()
|
||||
|
||||
# ADCs Tab functions
|
||||
|
||||
def getEnabledPlots(self):
|
||||
"""
|
||||
return plots that are shown (checkBoxADC#Plot is checked)
|
||||
"""
|
||||
enabledPlots = []
|
||||
self.legend.clear()
|
||||
for i in range(Defines.adc.count):
|
||||
if getattr(self.view, f'checkBoxADC{i}Plot').isChecked():
|
||||
plotName = getattr(self.view, f"labelADC{i}").text()
|
||||
enabledPlots.append((self.mainWindow.analogPlots[i], plotName))
|
||||
return enabledPlots
|
||||
|
||||
def updateLegend(self):
|
||||
"""
|
||||
update the legend for the ADC waveform plot
|
||||
should be called after checking or unchecking plot checkbox
|
||||
"""
|
||||
if not self.mainWindow.showLegend:
|
||||
self.legend.clear()
|
||||
else:
|
||||
for plot, name in self.getEnabledPlots():
|
||||
self.legend.addItem(plot, name)
|
||||
|
||||
def updateADCNames(self):
|
||||
"""
|
||||
get adc names from detector and update them in the UI
|
||||
"""
|
||||
for i, adc_name in enumerate(self.det.getAdcNames()):
|
||||
getattr(self.view, f"labelADC{i}").setText(adc_name)
|
||||
|
||||
def processWaveformData(self, data: bytes, aSamples: int) -> dict[str, np.ndarray]:
|
||||
"""
|
||||
view function
|
||||
plots processed waveform data
|
||||
@param data: raw waveform data
|
||||
@param aSamples: analog samples
|
||||
@return: waveform dict returned to handle it for saving the output
|
||||
"""
|
||||
|
||||
waveforms = {}
|
||||
analog_array = self._processWaveformData(data, aSamples, self.mainWindow.nADCEnabled)
|
||||
idx = 0
|
||||
for i in range(Defines.adc.count):
|
||||
checkBoxPlot = getattr(self.view, f"checkBoxADC{i}Plot")
|
||||
checkBoxEn = getattr(self.view, f"checkBoxADC{i}En")
|
||||
|
||||
if checkBoxEn.isChecked() and checkBoxPlot.isChecked():
|
||||
waveform = analog_array[:, idx]
|
||||
idx += 1
|
||||
self.mainWindow.analogPlots[i].setData(waveform)
|
||||
plotName = getattr(self.view, f"labelADC{i}").text()
|
||||
waveforms[plotName] = waveform
|
||||
return waveforms
|
||||
|
||||
@recordOrApplyPedestal
|
||||
def _processWaveformData(self, data: bytes, aSamples: int, nADCEnabled: int) -> np.ndarray:
|
||||
"""
|
||||
model function
|
||||
processes raw waveform data
|
||||
@param data: raw waveform data
|
||||
@param aSamples: analog samples
|
||||
@param nADCEnabled: number of enabled ADCs
|
||||
@return: processed waveform data
|
||||
"""
|
||||
analog_array = np.array(np.frombuffer(data, dtype=np.uint16, count=nADCEnabled * aSamples))
|
||||
return analog_array.reshape(-1, nADCEnabled)
|
||||
|
||||
def processImageData(self, data, aSamples):
|
||||
"""
|
||||
process the raw receiver data for analog image
|
||||
data: raw analog image
|
||||
aSamples: analog samples
|
||||
"""
|
||||
# get zoom state
|
||||
viewBox = self.mainWindow.plotAnalogImage.getView()
|
||||
state = viewBox.getState()
|
||||
try:
|
||||
self.mainWindow.analog_frame = self._processImageData(data, aSamples, self.mainWindow.nADCEnabled)
|
||||
self.plotTab.ignoreHistogramSignal = True
|
||||
self.mainWindow.plotAnalogImage.setImage(self.mainWindow.analog_frame.T)
|
||||
except Exception:
|
||||
self.logger.exception('Exception Caught')
|
||||
self.mainWindow.statusbar.setStyleSheet("color:red")
|
||||
message = f'Warning: Invalid size for Analog Image. Expected' \
|
||||
f' {self.mainWindow.nAnalogRows * self.mainWindow.nAnalogCols} ' \
|
||||
f'size, got {self.mainWindow.analog_frame.size} instead.'
|
||||
self.acquisitionTab.updateCurrentFrame('Invalid Image')
|
||||
|
||||
self.mainWindow.statusbar.showMessage(message)
|
||||
print(message)
|
||||
|
||||
self.plotTab.setFrameLimits(self.mainWindow.analog_frame)
|
||||
|
||||
# keep the zoomed in state (not 1st image)
|
||||
if self.mainWindow.firstAnalogImage:
|
||||
self.mainWindow.firstAnalogImage = False
|
||||
else:
|
||||
viewBox.setState(state)
|
||||
return self.mainWindow.analog_frame.T
|
||||
|
||||
@recordOrApplyPedestal
|
||||
def _processImageData(self, data, aSamples, nADCEnabled):
|
||||
analog_array = np.array(np.frombuffer(data, dtype=np.uint16, count=nADCEnabled * aSamples))
|
||||
return decoder.decode(analog_array, pm.moench04_analog())
|
||||
|
||||
def getADCEnableReg(self):
|
||||
retval = self.det.adcenable
|
||||
if self.det.tengiga:
|
||||
retval = self.det.adcenable10g
|
||||
self.view.lineEditADCEnable.editingFinished.disconnect()
|
||||
self.view.lineEditADCEnable.setText("0x{:08x}".format(retval))
|
||||
self.view.lineEditADCEnable.editingFinished.connect(self.setADCEnableReg)
|
||||
return retval
|
||||
|
||||
def setADCEnableReg(self):
|
||||
self.view.lineEditADCEnable.editingFinished.disconnect()
|
||||
try:
|
||||
mask = int(self.mainWindow.lineEditADCEnable.text(), 16)
|
||||
if self.det.tengiga:
|
||||
self.det.adcenable10g = mask
|
||||
else:
|
||||
self.det.adcenable = mask
|
||||
except Exception as e:
|
||||
QtWidgets.QMessageBox.warning(self.mainWindow, "ADC Enable Fail", str(e), QtWidgets.QMessageBox.Ok)
|
||||
pass
|
||||
# TODO: handling double event exceptions
|
||||
self.view.lineEditADCEnable.editingFinished.connect(self.setADCEnableReg)
|
||||
self.updateADCEnable()
|
||||
|
||||
def getADCEnable(self, i, mask):
|
||||
checkBox = getattr(self.view, f"checkBoxADC{i}En")
|
||||
checkBox.stateChanged.disconnect()
|
||||
checkBox.setChecked(bit_is_set(mask, i))
|
||||
checkBox.stateChanged.connect(partial(self.setADCEnable, i))
|
||||
|
||||
def updateADCEnable(self):
|
||||
retval = self.getADCEnableReg()
|
||||
self.mainWindow.nADCEnabled = bin(retval).count('1')
|
||||
for i in range(Defines.adc.count):
|
||||
self.getADCEnable(i, retval)
|
||||
self.getADCEnablePlot(i)
|
||||
self.getADCEnableColor(i)
|
||||
self.plotTab.addSelectedAnalogPlots(i)
|
||||
self.getADCEnableRange(retval)
|
||||
self.getADCEnablePlotRange()
|
||||
|
||||
def setADCEnable(self, i):
|
||||
checkBox = getattr(self.view, f"checkBoxADC{i}En")
|
||||
try:
|
||||
if self.det.tengiga:
|
||||
enableMask = manipulate_bit(checkBox.isChecked(), self.det.adcenable10g, i)
|
||||
self.det.adcenable10g = enableMask
|
||||
else:
|
||||
enableMask = manipulate_bit(checkBox.isChecked(), self.det.adcenable, i)
|
||||
self.det.adcenable = enableMask
|
||||
except Exception as e:
|
||||
QtWidgets.QMessageBox.warning(self.mainWindow, "ADC Enable Fail", str(e), QtWidgets.QMessageBox.Ok)
|
||||
|
||||
self.updateADCEnable()
|
||||
|
||||
def getADCEnableRange(self, mask):
|
||||
self.view.checkBoxADC0_15En.stateChanged.disconnect()
|
||||
self.view.checkBoxADC16_31En.stateChanged.disconnect()
|
||||
self.view.checkBoxADC0_15En.setChecked((mask & Defines.adc.BIT0_15_MASK) == Defines.adc.BIT0_15_MASK)
|
||||
self.view.checkBoxADC16_31En.setChecked((mask & Defines.adc.BIT16_31_MASK) == Defines.adc.BIT16_31_MASK)
|
||||
self.view.checkBoxADC0_15En.stateChanged.connect(partial(self.setADCEnableRange, 0, Defines.adc.half))
|
||||
self.view.checkBoxADC16_31En.stateChanged.connect(
|
||||
partial(self.setADCEnableRange, Defines.adc.half, Defines.adc.count))
|
||||
|
||||
def setADCEnableRange(self, start_nr, end_nr):
|
||||
mask = self.getADCEnableReg()
|
||||
checkBox = getattr(self.view, f"checkBoxADC{start_nr}_{end_nr - 1}En")
|
||||
for i in range(start_nr, end_nr):
|
||||
mask = manipulate_bit(checkBox.isChecked(), mask, i)
|
||||
try:
|
||||
if self.det.tengiga:
|
||||
self.det.adcenable10g = mask
|
||||
else:
|
||||
self.det.adcenable = mask
|
||||
except Exception as e:
|
||||
QtWidgets.QMessageBox.warning(self.mainWindow, "ADC Enable Fail", str(e), QtWidgets.QMessageBox.Ok)
|
||||
pass
|
||||
self.updateADCEnable()
|
||||
|
||||
def getADCEnablePlot(self, i):
|
||||
checkBox = getattr(self.view, f"checkBoxADC{i}En")
|
||||
checkBoxPlot = getattr(self.view, f"checkBoxADC{i}Plot")
|
||||
checkBoxPlot.setEnabled(checkBox.isChecked())
|
||||
|
||||
def setADCEnablePlot(self, i):
|
||||
pushButton = getattr(self.view, f"pushButtonADC{i}")
|
||||
checkBox = getattr(self.view, f"checkBoxADC{i}Plot")
|
||||
pushButton.setEnabled(checkBox.isChecked())
|
||||
|
||||
self.getADCEnablePlotRange()
|
||||
self.plotTab.addSelectedAnalogPlots(i)
|
||||
self.updateLegend()
|
||||
|
||||
def getADCEnablePlotRange(self):
|
||||
self.view.checkBoxADC0_15Plot.stateChanged.disconnect()
|
||||
self.view.checkBoxADC16_31Plot.stateChanged.disconnect()
|
||||
self.view.checkBoxADC0_15Plot.setEnabled(
|
||||
all(getattr(self.view, f"checkBoxADC{i}Plot").isEnabled() for i in range(Defines.adc.half)))
|
||||
self.view.checkBoxADC16_31Plot.setEnabled(
|
||||
all(
|
||||
getattr(self.view, f"checkBoxADC{i}Plot").isEnabled()
|
||||
for i in range(Defines.adc.half, Defines.adc.count)))
|
||||
self.view.checkBoxADC0_15Plot.setChecked(
|
||||
all(getattr(self.view, f"checkBoxADC{i}Plot").isChecked() for i in range(Defines.adc.half)))
|
||||
self.view.checkBoxADC16_31Plot.setChecked(
|
||||
all(
|
||||
getattr(self.view, f"checkBoxADC{i}Plot").isChecked()
|
||||
for i in range(Defines.adc.half, Defines.adc.count)))
|
||||
self.view.checkBoxADC0_15Plot.stateChanged.connect(partial(self.setADCEnablePlotRange, 0, Defines.adc.half))
|
||||
self.view.checkBoxADC16_31Plot.stateChanged.connect(
|
||||
partial(self.setADCEnablePlotRange, Defines.adc.half, Defines.adc.count))
|
||||
|
||||
def setADCEnablePlotRange(self, start_nr, end_nr):
|
||||
checkBox = getattr(self.view, f"checkBoxADC{start_nr}_{end_nr - 1}Plot")
|
||||
enable = checkBox.isChecked()
|
||||
for i in range(start_nr, end_nr):
|
||||
checkBox = getattr(self.view, f"checkBoxADC{i}Plot")
|
||||
checkBox.setChecked(enable)
|
||||
self.plotTab.addAllSelectedAnalogPlots()
|
||||
|
||||
def getADCEnableColor(self, i):
|
||||
checkBox = getattr(self.view, f"checkBoxADC{i}Plot")
|
||||
pushButton = getattr(self.view, f"pushButtonADC{i}")
|
||||
pushButton.setEnabled(checkBox.isEnabled() and checkBox.isChecked())
|
||||
|
||||
def selectADCColor(self, i):
|
||||
pushButton = getattr(self.view, f"pushButtonADC{i}")
|
||||
self.plotTab.showPalette(pushButton)
|
||||
pen = pg.mkPen(color=self.getADCButtonColor(i), width=1)
|
||||
self.mainWindow.analogPlots[i].setPen(pen)
|
||||
|
||||
def getADCButtonColor(self, i):
|
||||
pushButton = getattr(self.view, f"pushButtonADC{i}")
|
||||
return self.plotTab.getActiveColor(pushButton)
|
||||
|
||||
def setADCButtonColor(self, i, color):
|
||||
pushButton = getattr(self.view, f"pushButtonADC{i}")
|
||||
return self.plotTab.setActiveColor(pushButton, color)
|
||||
|
||||
def getADCInvReg(self):
|
||||
retval = self.det.adcinvert
|
||||
self.view.lineEditADCInversion.editingFinished.disconnect()
|
||||
self.view.lineEditADCInversion.setText("0x{:08x}".format(retval))
|
||||
self.view.lineEditADCInversion.editingFinished.connect(self.setADCInvReg)
|
||||
return retval
|
||||
|
||||
def setADCInvReg(self):
|
||||
self.view.lineEditADCInversion.editingFinished.disconnect()
|
||||
try:
|
||||
self.det.adcinvert = int(self.mainWindow.lineEditADCInversion.text(), 16)
|
||||
except Exception as e:
|
||||
QtWidgets.QMessageBox.warning(self.mainWindow, "ADC Inversion Fail", str(e), QtWidgets.QMessageBox.Ok)
|
||||
pass
|
||||
# TODO: handling double event exceptions
|
||||
self.view.lineEditADCInversion.editingFinished.connect(self.setADCInvReg)
|
||||
self.updateADCInv()
|
||||
|
||||
def getADCInv(self, i, inv):
|
||||
checkBox = getattr(self.view, f"checkBoxADC{i}Inv")
|
||||
checkBox.stateChanged.disconnect()
|
||||
checkBox.setChecked(bit_is_set(inv, i))
|
||||
checkBox.stateChanged.connect(partial(self.setADCInv, i))
|
||||
|
||||
def updateADCInv(self):
|
||||
retval = self.getADCInvReg()
|
||||
for i in range(Defines.adc.count):
|
||||
self.getADCInv(i, retval)
|
||||
self.getADCInvRange(retval)
|
||||
|
||||
def setADCInv(self, i):
|
||||
out = self.det.adcinvert
|
||||
checkBox = getattr(self.view, f"checkBoxADC{i}Inv")
|
||||
mask = manipulate_bit(checkBox.isChecked(), out, i)
|
||||
self.det.adcinvert = mask
|
||||
|
||||
retval = self.getADCInvReg()
|
||||
self.getADCInv(i, retval)
|
||||
self.getADCInvRange(retval)
|
||||
|
||||
def getADCInvRange(self, inv):
|
||||
self.view.checkBoxADC0_15Inv.stateChanged.disconnect()
|
||||
self.view.checkBoxADC16_31Inv.stateChanged.disconnect()
|
||||
self.view.checkBoxADC0_15Inv.setChecked((inv & Defines.adc.BIT0_15_MASK) == Defines.adc.BIT0_15_MASK)
|
||||
self.view.checkBoxADC16_31Inv.setChecked((inv & Defines.adc.BIT16_31_MASK) == Defines.adc.BIT16_31_MASK)
|
||||
self.view.checkBoxADC0_15Inv.stateChanged.connect(partial(self.setADCInvRange, 0, Defines.adc.half))
|
||||
self.view.checkBoxADC16_31Inv.stateChanged.connect(
|
||||
partial(self.setADCInvRange, Defines.adc.half, Defines.adc.count))
|
||||
|
||||
def setADCInvRange(self, start_nr, end_nr):
|
||||
out = self.det.adcinvert
|
||||
checkBox = getattr(self.view, f"checkBoxADC{start_nr}_{end_nr - 1}Inv")
|
||||
mask = getattr(Defines.adc, f"BIT{start_nr}_{end_nr - 1}_MASK")
|
||||
if checkBox.isChecked():
|
||||
self.det.adcinvert = out | mask
|
||||
else:
|
||||
self.det.adcinvert = out & ~mask
|
||||
|
||||
self.updateADCInv()
|
||||
|
||||
def saveParameters(self) -> list[str]:
|
||||
return [
|
||||
f"adcenable {self.view.lineEditADCEnable.text()}",
|
||||
f"adcinvert {self.view.lineEditADCInversion.text()}",
|
||||
]
|
719
pyctbgui/pyctbgui/services/Acquisition.py
Normal file
719
pyctbgui/pyctbgui/services/Acquisition.py
Normal file
@ -0,0 +1,719 @@
|
||||
import json
|
||||
import typing
|
||||
from pathlib import Path
|
||||
import numpy as np
|
||||
import time
|
||||
import zmq
|
||||
from PyQt5 import QtWidgets, uic
|
||||
import logging
|
||||
|
||||
from slsdet import readoutMode, runStatus
|
||||
from pyctbgui.utils.defines import Defines
|
||||
from pyctbgui.utils.numpyWriter.npy_writer import NumpyFileManager
|
||||
from pyctbgui.utils.numpyWriter.npz_writer import NpzFileWriter
|
||||
|
||||
if typing.TYPE_CHECKING:
|
||||
# only used for type hinting. To avoid circular dependencies these
|
||||
# won't be imported in runtime
|
||||
from pyctbgui.services import SignalsTab, TransceiverTab, AdcTab, PlotTab
|
||||
|
||||
|
||||
class AcquisitionTab(QtWidgets.QWidget):
|
||||
|
||||
def __init__(self, parent):
|
||||
self.__isWaveform = None
|
||||
super().__init__(parent)
|
||||
self.currentMeasurement = None
|
||||
self.dsamples = None
|
||||
self.stoppedFlag = None
|
||||
self.asamples = None
|
||||
self.tsamples = None
|
||||
uic.loadUi(Path(__file__).parent.parent / 'ui' / "acquisition.ui", parent)
|
||||
self.view = parent
|
||||
self.mainWindow = None
|
||||
self.det = None
|
||||
self.signalsTab: SignalsTab = None
|
||||
self.transceiverTab: TransceiverTab = None
|
||||
self.adcTab: AdcTab = None
|
||||
self.plotTab: PlotTab = None
|
||||
self.writeNumpy: bool = False
|
||||
self.outputDir: Path = Path('/')
|
||||
self.outputFileNamePrefix: str = ''
|
||||
self.numpyFileManagers: dict[str, NumpyFileManager] = {}
|
||||
|
||||
self.logger = logging.getLogger('AcquisitionTab')
|
||||
|
||||
def setup_ui(self):
|
||||
self.signalsTab = self.mainWindow.signalsTab
|
||||
self.transceiverTab = self.mainWindow.transceiverTab
|
||||
self.adcTab = self.mainWindow.adcTab
|
||||
self.plotTab = self.mainWindow.plotTab
|
||||
self.toggleStartButton(False)
|
||||
|
||||
def connect_ui(self):
|
||||
# For Acquistions Tab
|
||||
self.view.comboBoxROMode.currentIndexChanged.connect(self.setReadOut)
|
||||
self.view.spinBoxRunF.editingFinished.connect(self.setRunFrequency)
|
||||
self.view.spinBoxTransceiver.editingFinished.connect(self.setTransceiver)
|
||||
self.view.spinBoxAnalog.editingFinished.connect(self.setAnalog)
|
||||
self.view.spinBoxDigital.editingFinished.connect(self.setDigital)
|
||||
self.view.spinBoxADCF.editingFinished.connect(self.setADCFrequency)
|
||||
self.view.spinBoxADCPhase.editingFinished.connect(self.setADCPhase)
|
||||
self.view.spinBoxADCPipeline.editingFinished.connect(self.setADCPipeline)
|
||||
self.view.spinBoxDBITF.editingFinished.connect(self.setDBITFrequency)
|
||||
self.view.spinBoxDBITPhase.editingFinished.connect(self.setDBITPhase)
|
||||
self.view.spinBoxDBITPipeline.editingFinished.connect(self.setDBITPipeline)
|
||||
|
||||
self.view.checkBoxFileWriteRaw.stateChanged.connect(self.setFileWrite)
|
||||
self.view.checkBoxFileWriteNumpy.stateChanged.connect(self.setFileWriteNumpy)
|
||||
self.view.lineEditFileName.editingFinished.connect(self.setFileName)
|
||||
self.view.lineEditFilePath.editingFinished.connect(self.setFilePath)
|
||||
self.view.pushButtonFilePath.clicked.connect(self.browseFilePath)
|
||||
self.view.spinBoxAcquisitionIndex.editingFinished.connect(self.setAccquisitionIndex)
|
||||
self.view.spinBoxFrames.editingFinished.connect(self.setFrames)
|
||||
self.view.spinBoxPeriod.editingFinished.connect(self.setPeriod)
|
||||
self.view.comboBoxPeriod.currentIndexChanged.connect(self.setPeriod)
|
||||
self.view.spinBoxTriggers.editingFinished.connect(self.setTriggers)
|
||||
|
||||
def refresh(self):
|
||||
self.getReadout()
|
||||
self.getRunFrequency()
|
||||
self.getTransceiver()
|
||||
self.getAnalog()
|
||||
self.getDigital()
|
||||
self.getADCFrequency()
|
||||
self.getADCPhase()
|
||||
self.getADCPipeline()
|
||||
self.getDBITFrequency()
|
||||
self.getDBITPhase()
|
||||
self.getDBITPipeline()
|
||||
self.getFileWrite()
|
||||
self.getFileName()
|
||||
self.getFilePath()
|
||||
self.getAccquisitionIndex()
|
||||
self.getFrames()
|
||||
self.getTriggers()
|
||||
self.getPeriod()
|
||||
self.updateDetectorStatus(self.det.status)
|
||||
|
||||
# Acquisition Tab functions
|
||||
|
||||
def getReadout(self):
|
||||
self.view.comboBoxROMode.currentIndexChanged.disconnect()
|
||||
self.view.spinBoxAnalog.editingFinished.disconnect()
|
||||
self.view.spinBoxDigital.editingFinished.disconnect()
|
||||
self.view.spinBoxTransceiver.editingFinished.disconnect()
|
||||
|
||||
self.mainWindow.romode = self.det.romode
|
||||
self.view.comboBoxROMode.setCurrentIndex(self.mainWindow.romode.value)
|
||||
match self.mainWindow.romode:
|
||||
case readoutMode.ANALOG_ONLY:
|
||||
self.view.spinBoxAnalog.setEnabled(True)
|
||||
self.view.labelAnalog.setEnabled(True)
|
||||
self.view.spinBoxDigital.setDisabled(True)
|
||||
self.view.labelDigital.setDisabled(True)
|
||||
self.view.labelTransceiver.setDisabled(True)
|
||||
self.view.spinBoxTransceiver.setDisabled(True)
|
||||
case readoutMode.DIGITAL_ONLY:
|
||||
self.view.spinBoxAnalog.setDisabled(True)
|
||||
self.view.labelAnalog.setDisabled(True)
|
||||
self.view.spinBoxDigital.setEnabled(True)
|
||||
self.view.labelDigital.setEnabled(True)
|
||||
self.view.labelTransceiver.setDisabled(True)
|
||||
self.view.spinBoxTransceiver.setDisabled(True)
|
||||
case readoutMode.ANALOG_AND_DIGITAL:
|
||||
self.view.spinBoxAnalog.setEnabled(True)
|
||||
self.view.labelAnalog.setEnabled(True)
|
||||
self.view.spinBoxDigital.setEnabled(True)
|
||||
self.view.labelDigital.setEnabled(True)
|
||||
self.view.labelTransceiver.setDisabled(True)
|
||||
self.view.spinBoxTransceiver.setDisabled(True)
|
||||
case readoutMode.TRANSCEIVER_ONLY:
|
||||
self.view.spinBoxAnalog.setDisabled(True)
|
||||
self.view.labelAnalog.setDisabled(True)
|
||||
self.view.spinBoxDigital.setDisabled(True)
|
||||
self.view.labelDigital.setDisabled(True)
|
||||
self.view.labelTransceiver.setEnabled(True)
|
||||
self.view.spinBoxTransceiver.setEnabled(True)
|
||||
case _:
|
||||
self.view.spinBoxAnalog.setDisabled(True)
|
||||
self.view.labelAnalog.setDisabled(True)
|
||||
self.view.spinBoxDigital.setEnabled(True)
|
||||
self.view.labelDigital.setEnabled(True)
|
||||
self.view.labelTransceiver.setEnabled(True)
|
||||
self.view.spinBoxTransceiver.setEnabled(True)
|
||||
|
||||
self.view.comboBoxROMode.currentIndexChanged.connect(self.setReadOut)
|
||||
self.view.spinBoxAnalog.editingFinished.connect(self.setAnalog)
|
||||
self.view.spinBoxDigital.editingFinished.connect(self.setDigital)
|
||||
self.view.spinBoxTransceiver.editingFinished.connect(self.setTransceiver)
|
||||
self.getAnalog()
|
||||
self.getDigital()
|
||||
self.plotTab.showPlot()
|
||||
|
||||
def plotReferesh(self):
|
||||
self.read_zmq()
|
||||
|
||||
def setReadOut(self):
|
||||
self.view.comboBoxROMode.currentIndexChanged.disconnect()
|
||||
try:
|
||||
if self.view.comboBoxROMode.currentIndex() == 0:
|
||||
self.det.romode = readoutMode.ANALOG_ONLY
|
||||
elif self.view.comboBoxROMode.currentIndex() == 1:
|
||||
self.det.romode = readoutMode.DIGITAL_ONLY
|
||||
elif self.view.comboBoxROMode.currentIndex() == 2:
|
||||
self.det.romode = readoutMode.ANALOG_AND_DIGITAL
|
||||
elif self.view.comboBoxROMode.currentIndex() == 3:
|
||||
self.det.romode = readoutMode.TRANSCEIVER_ONLY
|
||||
else:
|
||||
self.det.romode = readoutMode.DIGITAL_AND_TRANSCEIVER
|
||||
except Exception as e:
|
||||
QtWidgets.QMessageBox.warning(self.mainWindow, "Readout Mode Fail", str(e), QtWidgets.QMessageBox.Ok)
|
||||
# TODO: handling double event exceptions
|
||||
self.view.comboBoxROMode.currentIndexChanged.connect(self.setReadOut)
|
||||
self.getReadout()
|
||||
|
||||
def getRunFrequency(self):
|
||||
self.view.spinBoxRunF.editingFinished.disconnect()
|
||||
self.view.spinBoxRunF.setValue(self.det.runclk)
|
||||
self.view.spinBoxRunF.editingFinished.connect(self.setRunFrequency)
|
||||
|
||||
def setRunFrequency(self):
|
||||
self.view.spinBoxRunF.editingFinished.disconnect()
|
||||
try:
|
||||
self.det.runclk = self.view.spinBoxRunF.value()
|
||||
except Exception as e:
|
||||
QtWidgets.QMessageBox.warning(self.mainWindow, "Run Frequency Fail", str(e), QtWidgets.QMessageBox.Ok)
|
||||
# TODO: handling double event exceptions
|
||||
self.view.spinBoxRunF.editingFinished.connect(self.setRunFrequency)
|
||||
self.getRunFrequency()
|
||||
|
||||
def getTransceiver(self):
|
||||
self.view.spinBoxTransceiver.editingFinished.disconnect()
|
||||
self.tsamples = self.det.tsamples
|
||||
self.view.spinBoxTransceiver.setValue(self.tsamples)
|
||||
self.view.spinBoxTransceiver.editingFinished.connect(self.setTransceiver)
|
||||
|
||||
def setTransceiver(self):
|
||||
self.view.spinBoxTransceiver.editingFinished.disconnect()
|
||||
try:
|
||||
self.det.tsamples = self.view.spinBoxTransceiver.value()
|
||||
except Exception as e:
|
||||
QtWidgets.QMessageBox.warning(self.mainWindow, "Transceiver Samples Fail", str(e),
|
||||
QtWidgets.QMessageBox.Ok)
|
||||
# TODO: handling double event exceptions
|
||||
self.view.spinBoxTransceiver.editingFinished.connect(self.setTransceiver)
|
||||
self.getTransceiver()
|
||||
|
||||
def getAnalog(self):
|
||||
self.view.spinBoxAnalog.editingFinished.disconnect()
|
||||
self.asamples = self.det.asamples
|
||||
self.view.spinBoxAnalog.setValue(self.asamples)
|
||||
self.view.spinBoxAnalog.editingFinished.connect(self.setAnalog)
|
||||
|
||||
def setAnalog(self):
|
||||
self.view.spinBoxAnalog.editingFinished.disconnect()
|
||||
try:
|
||||
self.det.asamples = self.view.spinBoxAnalog.value()
|
||||
except Exception as e:
|
||||
QtWidgets.QMessageBox.warning(self.mainWindow, "Digital Samples Fail", str(e), QtWidgets.QMessageBox.Ok)
|
||||
# TODO: handling double event exceptions
|
||||
self.view.spinBoxAnalog.editingFinished.connect(self.setAnalog)
|
||||
self.getAnalog()
|
||||
|
||||
def getDigital(self):
|
||||
self.view.spinBoxDigital.editingFinished.disconnect()
|
||||
self.dsamples = self.det.dsamples
|
||||
self.view.spinBoxDigital.setValue(self.dsamples)
|
||||
self.view.spinBoxDigital.editingFinished.connect(self.setDigital)
|
||||
|
||||
def setDigital(self):
|
||||
self.view.spinBoxDigital.editingFinished.disconnect()
|
||||
try:
|
||||
self.det.dsamples = self.view.spinBoxDigital.value()
|
||||
except Exception as e:
|
||||
QtWidgets.QMessageBox.warning(self.mainWindow, "Digital Samples Fail", str(e), QtWidgets.QMessageBox.Ok)
|
||||
# TODO: handling double event exceptions
|
||||
self.view.spinBoxDigital.editingFinished.connect(self.setDigital)
|
||||
self.getDigital()
|
||||
|
||||
def getADCFrequency(self):
|
||||
self.view.spinBoxADCF.editingFinished.disconnect()
|
||||
self.view.spinBoxADCF.setValue(self.det.adcclk)
|
||||
self.view.spinBoxADCF.editingFinished.connect(self.setADCFrequency)
|
||||
|
||||
def setADCFrequency(self):
|
||||
self.view.spinBoxADCF.editingFinished.disconnect()
|
||||
try:
|
||||
self.det.adcclk = self.view.spinBoxADCF.value()
|
||||
except Exception as e:
|
||||
QtWidgets.QMessageBox.warning(self.mainWindow, "ADC Frequency Fail", str(e), QtWidgets.QMessageBox.Ok)
|
||||
# TODO: handling double event exceptions
|
||||
self.view.spinBoxADCF.editingFinished.connect(self.setADCFrequency)
|
||||
self.getADCFrequency()
|
||||
|
||||
def getADCPhase(self):
|
||||
self.view.spinBoxADCPhase.editingFinished.disconnect()
|
||||
self.view.spinBoxADCPhase.setValue(self.det.adcphase)
|
||||
self.view.spinBoxADCPhase.editingFinished.connect(self.setADCPhase)
|
||||
|
||||
def setADCPhase(self):
|
||||
self.view.spinBoxADCPhase.editingFinished.disconnect()
|
||||
try:
|
||||
self.det.adcphase = self.view.spinBoxADCPhase.value()
|
||||
except Exception as e:
|
||||
QtWidgets.QMessageBox.warning(self.mainWindow, "ADC Phase Fail", str(e), QtWidgets.QMessageBox.Ok)
|
||||
# TODO: handling double event exceptions
|
||||
self.view.spinBoxADCPhase.editingFinished.connect(self.setADCPhase)
|
||||
self.getADCPhase()
|
||||
|
||||
def getADCPipeline(self):
|
||||
self.view.spinBoxADCPipeline.editingFinished.disconnect()
|
||||
self.view.spinBoxADCPipeline.setValue(self.det.adcpipeline)
|
||||
self.view.spinBoxADCPipeline.editingFinished.connect(self.setADCPipeline)
|
||||
|
||||
def setADCPipeline(self):
|
||||
self.view.spinBoxADCPipeline.editingFinished.disconnect()
|
||||
try:
|
||||
self.det.adcpipeline = self.view.spinBoxADCPipeline.value()
|
||||
except Exception as e:
|
||||
QtWidgets.QMessageBox.warning(self.mainWindow, "ADC Pipeline Fail", str(e), QtWidgets.QMessageBox.Ok)
|
||||
# TODO: handling double event exceptions
|
||||
self.view.spinBoxADCPipeline.editingFinished.connect(self.setADCPipeline)
|
||||
self.getADCPipeline()
|
||||
|
||||
def getDBITFrequency(self):
|
||||
self.view.spinBoxDBITF.editingFinished.disconnect()
|
||||
self.view.spinBoxDBITF.setValue(self.det.dbitclk)
|
||||
self.view.spinBoxDBITF.editingFinished.connect(self.setDBITFrequency)
|
||||
|
||||
def setDBITFrequency(self):
|
||||
self.view.spinBoxDBITF.editingFinished.disconnect()
|
||||
try:
|
||||
self.det.dbitclk = self.view.spinBoxDBITF.value()
|
||||
except Exception as e:
|
||||
QtWidgets.QMessageBox.warning(self.mainWindow, "DBit Frequency Fail", str(e), QtWidgets.QMessageBox.Ok)
|
||||
# TODO: handling double event exceptions
|
||||
self.view.spinBoxDBITF.editingFinished.connect(self.setDBITFrequency)
|
||||
self.getDBITFrequency()
|
||||
|
||||
def getDBITPhase(self):
|
||||
self.view.spinBoxDBITPhase.editingFinished.disconnect()
|
||||
self.view.spinBoxDBITPhase.setValue(self.det.dbitphase)
|
||||
self.view.spinBoxDBITPhase.editingFinished.connect(self.setDBITPhase)
|
||||
|
||||
def setDBITPhase(self):
|
||||
self.view.spinBoxDBITPhase.editingFinished.disconnect()
|
||||
try:
|
||||
self.det.dbitphase = self.view.spinBoxDBITPhase.value()
|
||||
except Exception as e:
|
||||
QtWidgets.QMessageBox.warning(self.mainWindow, "DBit Phase Fail", str(e), QtWidgets.QMessageBox.Ok)
|
||||
# TODO: handling double event exceptions
|
||||
self.view.spinBoxDBITPhase.editingFinished.connect(self.setDBITPhase)
|
||||
self.getDBITPhase()
|
||||
|
||||
def getDBITPipeline(self):
|
||||
self.view.spinBoxDBITPipeline.editingFinished.disconnect()
|
||||
self.view.spinBoxDBITPipeline.setValue(self.det.dbitpipeline)
|
||||
self.view.spinBoxDBITPipeline.editingFinished.connect(self.setDBITPipeline)
|
||||
|
||||
def setDBITPipeline(self):
|
||||
self.view.spinBoxDBITPipeline.editingFinished.disconnect()
|
||||
try:
|
||||
self.det.dbitpipeline = self.view.spinBoxDBITPipeline.value()
|
||||
except Exception as e:
|
||||
QtWidgets.QMessageBox.warning(self.mainWindow, "DBit Pipeline Fail", str(e), QtWidgets.QMessageBox.Ok)
|
||||
# TODO: handling double event exceptions
|
||||
self.view.spinBoxDBITPipeline.editingFinished.connect(self.setDBITPipeline)
|
||||
self.getDBITPipeline()
|
||||
|
||||
def getFileWrite(self):
|
||||
self.view.checkBoxFileWriteRaw.stateChanged.disconnect()
|
||||
self.view.checkBoxFileWriteRaw.setChecked(self.det.fwrite)
|
||||
self.view.checkBoxFileWriteRaw.stateChanged.connect(self.setFileWrite)
|
||||
|
||||
def setFileWrite(self):
|
||||
self.det.fwrite = self.view.checkBoxFileWriteRaw.isChecked()
|
||||
self.getFileWrite()
|
||||
|
||||
def setFileWriteNumpy(self):
|
||||
"""
|
||||
slot for saving the data in numpy (.npy) format
|
||||
"""
|
||||
self.writeNumpy = not self.writeNumpy
|
||||
|
||||
def getFileName(self):
|
||||
"""
|
||||
set the lineEditFilePath input widget to the filename value from the detector
|
||||
"""
|
||||
|
||||
self.view.lineEditFileName.editingFinished.disconnect()
|
||||
fileName = self.det.fname
|
||||
self.view.lineEditFileName.setText(fileName)
|
||||
self.outputFileNamePrefix = fileName
|
||||
self.view.lineEditFileName.editingFinished.connect(self.setFileName)
|
||||
|
||||
def setFileName(self):
|
||||
"""
|
||||
slot for setting the filename from the widget to the detector
|
||||
"""
|
||||
self.det.fname = self.view.lineEditFileName.text()
|
||||
self.getFileName()
|
||||
|
||||
def getFilePath(self):
|
||||
"""
|
||||
set the lineEditFilePath input widget to the path value from the detector
|
||||
"""
|
||||
self.view.lineEditFilePath.editingFinished.disconnect()
|
||||
path = self.det.fpath
|
||||
self.view.lineEditFilePath.setText(str(path))
|
||||
self.view.lineEditFilePath.editingFinished.connect(self.setFilePath)
|
||||
self.outputDir = path
|
||||
|
||||
def setFilePath(self):
|
||||
"""
|
||||
slot to set the directory of the output for the detector
|
||||
"""
|
||||
self.det.fpath = Path(self.view.lineEditFilePath.text())
|
||||
self.getFilePath()
|
||||
|
||||
def saveNumpyFile(self, data: np.ndarray | dict[str, np.ndarray], jsonHeader):
|
||||
"""
|
||||
save the acquisition data (waveform or image) in the specified path
|
||||
save waveform in multiple .npy files
|
||||
save image as npy file format
|
||||
@note: frame number can be up to 100,000 so the data arrays cannot be fully loaded to memory
|
||||
"""
|
||||
if not self.writeNumpy:
|
||||
return
|
||||
if self.outputDir == Path('/'):
|
||||
self.outputDir = Path('./')
|
||||
if self.outputFileNamePrefix == '':
|
||||
self.outputFileNamePrefix = 'run'
|
||||
|
||||
for device in data:
|
||||
if device not in self.numpyFileManagers:
|
||||
tmpPath = self.outputDir / f'{self.outputFileNamePrefix}_{device}_{jsonHeader["fileIndex"]}.npy'
|
||||
self.numpyFileManagers[device] = NumpyFileManager(tmpPath, 'w', data[device].shape, data[device].dtype)
|
||||
self.numpyFileManagers[device].writeOneFrame(data[device])
|
||||
|
||||
if 'progress' in jsonHeader and jsonHeader['progress'] >= 100:
|
||||
# close opened files after saving the last frame
|
||||
self.closeOpenedNumpyFiles(jsonHeader)
|
||||
|
||||
def closeOpenedNumpyFiles(self, jsonHeader):
|
||||
"""
|
||||
create npz file for waveform plots and close opened numpy files to persist their data
|
||||
"""
|
||||
if not self.writeNumpy:
|
||||
return
|
||||
if len(self.numpyFileManagers) == 0:
|
||||
return
|
||||
oneFile: bool = len(self.numpyFileManagers) == 1
|
||||
|
||||
filepaths = [npw.file.name for device, npw in self.numpyFileManagers.items()]
|
||||
filenames = list(self.numpyFileManagers.keys())
|
||||
ext = 'npy' if oneFile else 'npz'
|
||||
newPath = self.outputDir / f'{self.outputFileNamePrefix}_{jsonHeader["fileIndex"]}.{ext}'
|
||||
|
||||
if not oneFile:
|
||||
# if there is multiple .npy files group them in an .npz file
|
||||
self.numpyFileManagers.clear()
|
||||
NpzFileWriter.zipNpyFiles(newPath, filepaths, filenames, deleteOriginals=True, compressed=False)
|
||||
else:
|
||||
# rename files from "run_ADC0_0.npy" to "run_0.npy" if it is a single .npy file
|
||||
oldPath = self.outputDir / f'{self.outputFileNamePrefix}_' \
|
||||
f'{self.numpyFileManagers.popitem()[0]}_{jsonHeader["fileIndex"]}.{ext}'
|
||||
Path.rename(oldPath, newPath)
|
||||
|
||||
self.logger.info(f'Saving numpy data in {newPath} Finished')
|
||||
|
||||
def browseFilePath(self):
|
||||
response = QtWidgets.QFileDialog.getExistingDirectory(parent=self.mainWindow,
|
||||
caption="Select Path to Save Output File",
|
||||
directory=str(Path.cwd()),
|
||||
options=(QtWidgets.QFileDialog.ShowDirsOnly
|
||||
| QtWidgets.QFileDialog.DontResolveSymlinks)
|
||||
# filter='README (*.md *.ui)'
|
||||
)
|
||||
if response:
|
||||
self.view.lineEditFilePath.setText(response)
|
||||
self.setFilePath()
|
||||
|
||||
def getAccquisitionIndex(self):
|
||||
self.view.spinBoxAcquisitionIndex.editingFinished.disconnect()
|
||||
self.view.spinBoxAcquisitionIndex.setValue(self.det.findex)
|
||||
self.view.spinBoxAcquisitionIndex.editingFinished.connect(self.setAccquisitionIndex)
|
||||
|
||||
def setAccquisitionIndex(self):
|
||||
self.det.findex = self.view.spinBoxAcquisitionIndex.value()
|
||||
self.getAccquisitionIndex()
|
||||
|
||||
def getFrames(self):
|
||||
self.view.spinBoxFrames.editingFinished.disconnect()
|
||||
self.view.spinBoxFrames.setValue(self.det.frames)
|
||||
self.view.spinBoxFrames.editingFinished.connect(self.setFrames)
|
||||
|
||||
def setFrames(self):
|
||||
self.det.frames = self.view.spinBoxFrames.value()
|
||||
self.getFrames()
|
||||
|
||||
def getPeriod(self):
|
||||
self.view.spinBoxPeriod.editingFinished.disconnect()
|
||||
self.view.comboBoxPeriod.currentIndexChanged.disconnect()
|
||||
|
||||
# Converting to right time unit for period
|
||||
tPeriod = self.det.period
|
||||
if tPeriod < 100e-9:
|
||||
self.view.comboBoxPeriod.setCurrentIndex(3)
|
||||
self.view.spinBoxPeriod.setValue(tPeriod / 1e-9)
|
||||
elif tPeriod < 100e-6:
|
||||
self.view.comboBoxPeriod.setCurrentIndex(2)
|
||||
self.view.spinBoxPeriod.setValue(tPeriod / 1e-6)
|
||||
elif tPeriod < 100e-3:
|
||||
self.view.comboBoxPeriod.setCurrentIndex(1)
|
||||
self.view.spinBoxPeriod.setValue(tPeriod / 1e-3)
|
||||
else:
|
||||
self.view.comboBoxPeriod.setCurrentIndex(0)
|
||||
self.view.spinBoxPeriod.setValue(tPeriod)
|
||||
|
||||
self.view.spinBoxPeriod.editingFinished.connect(self.setPeriod)
|
||||
self.view.comboBoxPeriod.currentIndexChanged.connect(self.setPeriod)
|
||||
|
||||
def setPeriod(self):
|
||||
if self.view.comboBoxPeriod.currentIndex() == 0:
|
||||
self.det.period = self.view.spinBoxPeriod.value()
|
||||
elif self.view.comboBoxPeriod.currentIndex() == 1:
|
||||
self.det.period = self.view.spinBoxPeriod.value() * (1e-3)
|
||||
elif self.view.comboBoxPeriod.currentIndex() == 2:
|
||||
self.det.period = self.view.spinBoxPeriod.value() * (1e-6)
|
||||
else:
|
||||
self.det.period = self.view.spinBoxPeriod.value() * (1e-9)
|
||||
|
||||
self.getPeriod()
|
||||
|
||||
def getTriggers(self):
|
||||
self.view.spinBoxTriggers.editingFinished.disconnect()
|
||||
self.view.spinBoxTriggers.setValue(self.det.triggers)
|
||||
self.view.spinBoxTriggers.editingFinished.connect(self.setTriggers)
|
||||
|
||||
def setTriggers(self):
|
||||
self.det.triggers = self.view.spinBoxTriggers.value()
|
||||
self.getTriggers()
|
||||
|
||||
def updateDetectorStatus(self, status):
|
||||
self.mainWindow.labelDetectorStatus.setText(status.name)
|
||||
|
||||
def updateCurrentMeasurement(self):
|
||||
self.mainWindow.labelCurrentMeasurement.setText(str(self.currentMeasurement))
|
||||
# print(f"Meausrement {self.currentMeasurement}")
|
||||
|
||||
def updateCurrentFrame(self, val):
|
||||
self.mainWindow.labelFrameNumber.setText(str(val))
|
||||
|
||||
def updateAcquiredFrames(self, val):
|
||||
self.mainWindow.labelAcquiredFrames.setText(str(val))
|
||||
|
||||
def toggleAcquire(self):
|
||||
if self.mainWindow.pushButtonStart.isChecked():
|
||||
self.plotTab.showPatternViewer(False)
|
||||
self.acquire()
|
||||
else:
|
||||
self.stopAcquisition()
|
||||
|
||||
def toggleStartButton(self, started):
|
||||
if started:
|
||||
self.mainWindow.pushButtonStart.setChecked(True)
|
||||
self.mainWindow.pushButtonStart.setText('Stop')
|
||||
else:
|
||||
self.mainWindow.pushButtonStart.setChecked(False)
|
||||
self.mainWindow.pushButtonStart.setText('Start')
|
||||
|
||||
def stopAcquisition(self):
|
||||
self.det.stop()
|
||||
self.stoppedFlag = True
|
||||
|
||||
def checkBeforeAcquire(self):
|
||||
if self.plotTab.view.radioButtonImage.isChecked():
|
||||
# matterhorn image
|
||||
if self.plotTab.view.comboBoxPlot.currentText() == "Matterhorn":
|
||||
if self.mainWindow.romode not in [readoutMode.TRANSCEIVER_ONLY, readoutMode.DIGITAL_AND_TRANSCEIVER]:
|
||||
QtWidgets.QMessageBox.warning(self.mainWindow, "Plot type",
|
||||
"To read Matterhorn image, please enable transceiver readout mode",
|
||||
QtWidgets.QMessageBox.Ok)
|
||||
return False
|
||||
if self.transceiverTab.getTransceiverEnableReg() != Defines.Matterhorn.tranceiverEnable:
|
||||
QtWidgets.QMessageBox.warning(
|
||||
self.mainWindow, "Plot type", "To read Matterhorn image, please set transceiver enable to " +
|
||||
str(Defines.Matterhorn.tranceiverEnable), QtWidgets.QMessageBox.Ok)
|
||||
return False
|
||||
# moench04 image
|
||||
elif self.plotTab.view.comboBoxPlot.currentText() == "Moench04":
|
||||
if self.mainWindow.romode not in [readoutMode.ANALOG_ONLY, readoutMode.ANALOG_AND_DIGITAL]:
|
||||
QtWidgets.QMessageBox.warning(self.mainWindow, "Plot type",
|
||||
"To read Moench 04 image, please enable analog readout mode",
|
||||
QtWidgets.QMessageBox.Ok)
|
||||
return False
|
||||
if self.mainWindow.nADCEnabled != 32:
|
||||
QtWidgets.QMessageBox.warning(self.mainWindow, "Plot type",
|
||||
"To read Moench 04 image, please enable all 32 adcs",
|
||||
QtWidgets.QMessageBox.Ok)
|
||||
return False
|
||||
return True
|
||||
|
||||
def acquire(self):
|
||||
if not self.checkBeforeAcquire():
|
||||
self.toggleStartButton(False)
|
||||
return
|
||||
|
||||
self.stoppedFlag = False
|
||||
self.toggleStartButton(True)
|
||||
self.currentMeasurement = 0
|
||||
|
||||
# ensure zmq streaming is enabled
|
||||
if self.det.rx_zmqstream == 0:
|
||||
self.det.rx_zmqstream = 1
|
||||
|
||||
# some functions that must be updated for local values
|
||||
self.getTransceiver()
|
||||
self.getAnalog()
|
||||
self.getDigital()
|
||||
self.getReadout()
|
||||
self.signalsTab.getDBitOffset()
|
||||
self.adcTab.getADCEnableReg()
|
||||
self.signalsTab.updateDigitalBitEnable()
|
||||
self.transceiverTab.getTransceiverEnableReg()
|
||||
|
||||
self.startMeasurement()
|
||||
|
||||
def startMeasurement(self):
|
||||
try:
|
||||
self.updateCurrentMeasurement()
|
||||
self.updateCurrentFrame(0)
|
||||
self.updateAcquiredFrames(0)
|
||||
self.mainWindow.progressBar.setValue(0)
|
||||
|
||||
self.det.rx_start()
|
||||
self.det.start()
|
||||
time.sleep(Defines.Time_Wait_For_Packets_ms)
|
||||
self.checkEndofAcquisition()
|
||||
except Exception as e:
|
||||
QtWidgets.QMessageBox.warning(self.mainWindow, "Acquire Fail", str(e), QtWidgets.QMessageBox.Ok)
|
||||
self.checkEndofAcquisition()
|
||||
|
||||
def checkEndofAcquisition(self):
|
||||
caught = self.det.rx_framescaught[0]
|
||||
self.updateAcquiredFrames(caught)
|
||||
status = self.det.getDetectorStatus()[0]
|
||||
self.updateDetectorStatus(status)
|
||||
measurementDone = False
|
||||
# print(f'status:{status}')
|
||||
match status:
|
||||
case runStatus.RUNNING:
|
||||
pass
|
||||
case runStatus.WAITING:
|
||||
pass
|
||||
case runStatus.TRANSMITTING:
|
||||
pass
|
||||
case _:
|
||||
measurementDone = True
|
||||
|
||||
# check for 500ms for no packets
|
||||
# needs more time for 1g streaming out done
|
||||
if measurementDone:
|
||||
time.sleep(Defines.Time_Wait_For_Packets_ms)
|
||||
if self.det.rx_framescaught[0] != caught:
|
||||
measurementDone = False
|
||||
|
||||
numMeasurments = self.view.spinBoxMeasurements.value()
|
||||
if measurementDone:
|
||||
|
||||
if self.det.rx_status == runStatus.RUNNING:
|
||||
self.det.rx_stop()
|
||||
if self.view.checkBoxFileWriteRaw.isChecked() or self.view.checkBoxFileWriteNumpy.isChecked():
|
||||
self.view.spinBoxAcquisitionIndex.stepUp()
|
||||
self.setAccquisitionIndex()
|
||||
# next measurement
|
||||
self.currentMeasurement += 1
|
||||
if self.currentMeasurement < numMeasurments and not self.stoppedFlag:
|
||||
self.startMeasurement()
|
||||
else:
|
||||
self.mainWindow.statusTimer.stop()
|
||||
self.toggleStartButton(False)
|
||||
else:
|
||||
self.mainWindow.statusTimer.start(Defines.Time_Status_Refresh_ms)
|
||||
|
||||
# For other functios
|
||||
# Reading data from zmq and decoding it
|
||||
def read_zmq(self):
|
||||
# print("in readzmq")
|
||||
try:
|
||||
msg = self.socket.recv_multipart(flags=zmq.NOBLOCK)
|
||||
if len(msg) != 2:
|
||||
if len(msg) != 1:
|
||||
print(f'len(msg) = {len(msg)}')
|
||||
return
|
||||
header, data = msg
|
||||
jsonHeader = json.loads(header)
|
||||
self.mainWindow.progressBar.setValue(int(jsonHeader['progress']))
|
||||
self.updateCurrentFrame(jsonHeader['frameIndex'])
|
||||
|
||||
# waveform
|
||||
waveforms = {}
|
||||
if self.plotTab.view.radioButtonWaveform.isChecked():
|
||||
# analog
|
||||
if self.mainWindow.romode.value in [0, 2]:
|
||||
waveforms |= self.adcTab.processWaveformData(data, self.asamples)
|
||||
# digital
|
||||
if self.mainWindow.romode.value in [1, 2, 4]:
|
||||
waveforms |= self.signalsTab.processWaveformData(data, self.asamples, self.dsamples)
|
||||
# transceiver
|
||||
if self.mainWindow.romode.value in [3, 4]:
|
||||
waveforms |= self.transceiverTab.processWaveformData(data, self.dsamples)
|
||||
# image
|
||||
else:
|
||||
# analog
|
||||
if self.mainWindow.romode.value in [0, 2]:
|
||||
waveforms['analog_image'] = self.adcTab.processImageData(data, self.asamples)
|
||||
# transceiver
|
||||
if self.mainWindow.romode.value in [3, 4]:
|
||||
waveforms['tx_image'] = self.transceiverTab.processImageData(data, self.dsamples)
|
||||
|
||||
self.saveNumpyFile(waveforms, jsonHeader)
|
||||
except zmq.ZMQError:
|
||||
pass
|
||||
except Exception:
|
||||
self.logger.exception("Exception caught")
|
||||
|
||||
def setup_zmq(self):
|
||||
self.det.rx_zmqstream = 1
|
||||
self.zmqIp = self.det.zmqip
|
||||
self.zmqport = self.det.zmqport
|
||||
self.zmq_stream = self.det.rx_zmqstream
|
||||
|
||||
self.context = zmq.Context()
|
||||
self.socket = self.context.socket(zmq.SUB)
|
||||
self.socket.connect(f"tcp://{self.zmqIp}:{self.zmqport}")
|
||||
self.socket.subscribe("")
|
||||
|
||||
def saveParameters(self) -> list[str]:
|
||||
return [
|
||||
f'romode {self.view.comboBoxROMode.currentText().lower()}',
|
||||
f'runclk {self.view.spinBoxRunF.value()}',
|
||||
f'adcclk {self.view.spinBoxADCF.value()}',
|
||||
f'adcphase {self.view.spinBoxADCPhase.value()}',
|
||||
f'adcpipeline {self.view.spinBoxADCPipeline.value()}',
|
||||
f'dbitclk {self.view.spinBoxDBITF.value()}',
|
||||
f'dbitphase {self.view.spinBoxDBITPhase.value()}',
|
||||
f'dbitpipeline {self.view.spinBoxDBITPipeline.value()}',
|
||||
f'fwrite {int(self.view.checkBoxFileWriteRaw.isChecked())}',
|
||||
f'fname {self.view.lineEditFileName.text()}',
|
||||
f'fpath {self.view.lineEditFilePath.text()}',
|
||||
f'findex {self.view.spinBoxAcquisitionIndex.value()}',
|
||||
f'frames {self.view.spinBoxFrames.value()}',
|
||||
f'triggers {self.view.spinBoxTriggers.value()}',
|
||||
f'period {self.view.spinBoxPeriod.value()} {self.view.comboBoxPeriod.currentText().lower()}',
|
||||
f'asamples {self.view.spinBoxAnalog.value()}',
|
||||
f'dsamples {self.view.spinBoxDigital.value()}',
|
||||
f'tsamples {self.view.spinBoxTransceiver.value()}',
|
||||
]
|
170
pyctbgui/pyctbgui/services/DACs.py
Normal file
170
pyctbgui/pyctbgui/services/DACs.py
Normal file
@ -0,0 +1,170 @@
|
||||
from functools import partial
|
||||
from pathlib import Path
|
||||
|
||||
from PyQt5 import QtWidgets, uic
|
||||
from pyctbgui.utils.defines import Defines
|
||||
|
||||
from slsdet import dacIndex
|
||||
|
||||
|
||||
class DacTab(QtWidgets.QWidget):
|
||||
|
||||
def __init__(self, parent):
|
||||
super().__init__(parent)
|
||||
uic.loadUi(Path(__file__).parent.parent / 'ui' / "Dacs.ui", parent)
|
||||
self.view = parent
|
||||
|
||||
def setup_ui(self):
|
||||
for i in range(Defines.dac.count):
|
||||
dac = getattr(dacIndex, f"DAC_{i}")
|
||||
getattr(self.view, f"spinBoxDAC{i}").setValue(self.det.getDAC(dac)[0])
|
||||
|
||||
if self.det.highvoltage == 0:
|
||||
self.view.spinBoxHighVoltage.setDisabled(True)
|
||||
self.view.checkBoxHighVoltage.setChecked(False)
|
||||
|
||||
def connect_ui(self):
|
||||
n_dacs = len(self.det.daclist)
|
||||
for i in range(n_dacs):
|
||||
getattr(self.view, f"spinBoxDAC{i}").editingFinished.connect(partial(self.setDAC, i))
|
||||
getattr(self.view, f"checkBoxDAC{i}").stateChanged.connect(partial(self.setDACTristate, i))
|
||||
getattr(self.view, f"checkBoxDAC{i}mV").stateChanged.connect(partial(self.getDAC, i))
|
||||
|
||||
self.view.comboBoxADCVpp.currentIndexChanged.connect(self.setADCVpp)
|
||||
self.view.spinBoxHighVoltage.editingFinished.connect(self.setHighVoltage)
|
||||
self.view.checkBoxHighVoltage.stateChanged.connect(self.setHighVoltage)
|
||||
|
||||
def refresh(self):
|
||||
self.updateDACNames()
|
||||
for i in range(Defines.dac.count):
|
||||
self.getDACTristate(i)
|
||||
self.getDAC(i)
|
||||
|
||||
self.getADCVpp()
|
||||
self.getHighVoltage()
|
||||
|
||||
def updateDACNames(self):
|
||||
for i, name in enumerate(self.det.getDacNames()):
|
||||
getattr(self.view, f"checkBoxDAC{i}").setText(name)
|
||||
|
||||
def getDACTristate(self, i):
|
||||
checkBox = getattr(self.view, f"checkBoxDAC{i}")
|
||||
dac = getattr(dacIndex, f"DAC_{i}")
|
||||
checkBox.stateChanged.disconnect()
|
||||
if (self.det.getDAC(dac)[0]) == -100:
|
||||
checkBox.setChecked(False)
|
||||
else:
|
||||
checkBox.setChecked(True)
|
||||
checkBox.stateChanged.connect(partial(self.setDACTristate, i))
|
||||
|
||||
def setDACTristate(self, i):
|
||||
checkBox = getattr(self.view, f"checkBoxDAC{i}")
|
||||
if not checkBox.isChecked():
|
||||
self.setDAC(i)
|
||||
self.getDAC(i)
|
||||
|
||||
def getDAC(self, i):
|
||||
checkBox = getattr(self.view, f"checkBoxDAC{i}")
|
||||
checkBoxmV = getattr(self.view, f"checkBoxDAC{i}mV")
|
||||
spinBox = getattr(self.view, f"spinBoxDAC{i}")
|
||||
label = getattr(self.view, f"labelDAC{i}")
|
||||
dac = getattr(dacIndex, f"DAC_{i}")
|
||||
|
||||
checkBox.stateChanged.disconnect()
|
||||
checkBoxmV.stateChanged.disconnect()
|
||||
spinBox.editingFinished.disconnect()
|
||||
|
||||
# do not uncheck automatically
|
||||
if self.det.getDAC(dac)[0] != -100:
|
||||
checkBox.setChecked(True)
|
||||
|
||||
if checkBox.isChecked():
|
||||
spinBox.setEnabled(True)
|
||||
checkBoxmV.setEnabled(True)
|
||||
else:
|
||||
spinBox.setDisabled(True)
|
||||
checkBoxmV.setDisabled(True)
|
||||
|
||||
in_mv = checkBoxmV.isChecked() and checkBox.isChecked()
|
||||
dacValue = self.det.getDAC(dac, in_mv)[0]
|
||||
unit = "mV" if in_mv else ""
|
||||
label.setText(f"{dacValue} {unit}")
|
||||
spinBox.setValue(dacValue)
|
||||
|
||||
checkBox.stateChanged.connect(partial(self.setDACTristate, i))
|
||||
checkBoxmV.stateChanged.connect(partial(self.getDAC, i))
|
||||
spinBox.editingFinished.connect(partial(self.setDAC, i))
|
||||
|
||||
def setDAC(self, i):
|
||||
checkBoxDac = getattr(self.view, f"checkBoxDAC{i}")
|
||||
checkBoxmV = getattr(self.view, f"checkBoxDAC{i}mV")
|
||||
spinBox = getattr(self.view, f"spinBoxDAC{i}")
|
||||
dac = getattr(dacIndex, f"DAC_{i}")
|
||||
|
||||
value = -100
|
||||
if checkBoxDac.isChecked():
|
||||
value = spinBox.value()
|
||||
in_mV = checkBoxDac.isChecked() and checkBoxmV.isChecked()
|
||||
self.det.setDAC(dac, value, in_mV)
|
||||
self.getDAC(i)
|
||||
|
||||
def getADCVpp(self):
|
||||
retval = self.det.adcvpp
|
||||
self.view.labelADCVpp.setText(f'Mode: {str(retval)}')
|
||||
|
||||
self.view.comboBoxADCVpp.currentIndexChanged.disconnect()
|
||||
self.view.comboBoxADCVpp.setCurrentIndex(retval)
|
||||
self.view.comboBoxADCVpp.currentIndexChanged.connect(self.setADCVpp)
|
||||
|
||||
def setADCVpp(self):
|
||||
self.det.adcvpp = self.view.comboBoxADCVpp.currentIndex()
|
||||
self.getADCVpp()
|
||||
|
||||
def getHighVoltage(self):
|
||||
retval = self.det.highvoltage
|
||||
self.view.labelHighVoltage.setText(str(retval))
|
||||
|
||||
self.view.spinBoxHighVoltage.editingFinished.disconnect()
|
||||
self.view.checkBoxHighVoltage.stateChanged.disconnect()
|
||||
|
||||
self.view.spinBoxHighVoltage.setValue(retval)
|
||||
if retval:
|
||||
self.view.checkBoxHighVoltage.setChecked(True)
|
||||
if self.view.checkBoxHighVoltage.isChecked():
|
||||
self.view.spinBoxHighVoltage.setEnabled(True)
|
||||
|
||||
self.view.spinBoxHighVoltage.editingFinished.connect(self.setHighVoltage)
|
||||
self.view.checkBoxHighVoltage.stateChanged.connect(self.setHighVoltage)
|
||||
|
||||
def setHighVoltage(self):
|
||||
value = 0
|
||||
if self.view.checkBoxHighVoltage.isChecked():
|
||||
value = self.view.spinBoxHighVoltage.value()
|
||||
try:
|
||||
self.det.highvoltage = value
|
||||
except Exception as e:
|
||||
QtWidgets.QMessageBox.warning(self.mainWindow, "High Voltage Fail", str(e), QtWidgets.QMessageBox.Ok)
|
||||
pass
|
||||
self.getHighVoltage()
|
||||
|
||||
def saveParameters(self) -> list:
|
||||
"""
|
||||
save parameters for the current tab
|
||||
@return: list of commands
|
||||
"""
|
||||
commands = []
|
||||
for i in range(Defines.dac.count):
|
||||
# if checkbox disabled put -100 in dac units
|
||||
enabled = getattr(self.view, f"checkBoxDAC{i}").isChecked()
|
||||
if not enabled:
|
||||
commands.append(f"dac {i} -100")
|
||||
# else put the value in dac or mV units
|
||||
else:
|
||||
value = getattr(self.view, f"spinBoxDAC{i}").value()
|
||||
inMV = getattr(self.view, f"checkBoxDAC{i}mV").isChecked()
|
||||
unit = " mV" if inMV else ""
|
||||
commands.append(f"dac {i} {value}{unit}")
|
||||
|
||||
commands.append(f"adcvpp {self.view.comboBoxADCVpp.currentText()} mV")
|
||||
commands.append(f"highvoltage {self.view.spinBoxHighVoltage.value()}")
|
||||
return commands
|
456
pyctbgui/pyctbgui/services/Pattern.py
Normal file
456
pyctbgui/pyctbgui/services/Pattern.py
Normal file
@ -0,0 +1,456 @@
|
||||
import os
|
||||
from functools import partial
|
||||
from pathlib import Path
|
||||
|
||||
from PyQt5 import QtWidgets, uic
|
||||
import matplotlib.pyplot as plt
|
||||
from matplotlib.backends.backend_qt5agg import FigureCanvasQTAgg as FigureCanvas
|
||||
from matplotlib.backends.backend_qt5agg import NavigationToolbar2QT as NavigationToolbar
|
||||
|
||||
from pyctbgui.utils.defines import Defines
|
||||
from pyctbgui.utils.plotPattern import PlotPattern
|
||||
|
||||
|
||||
class PatternTab(QtWidgets.QWidget):
|
||||
|
||||
def __init__(self, parent):
|
||||
super().__init__(parent)
|
||||
uic.loadUi(Path(__file__).parent.parent / 'ui' / "pattern.ui", parent)
|
||||
self.view = parent
|
||||
self.mainWindow = None
|
||||
self.det = None
|
||||
self.plotTab = None
|
||||
|
||||
def setup_ui(self):
|
||||
# Pattern Tab
|
||||
self.plotTab = self.mainWindow.plotTab
|
||||
|
||||
for i in range(len(Defines.Colors)):
|
||||
self.view.comboBoxPatColor.addItem(Defines.Colors[i])
|
||||
self.view.comboBoxPatWaitColor.addItem(Defines.Colors[i])
|
||||
self.view.comboBoxPatLoopColor.addItem(Defines.Colors[i])
|
||||
for i in range(len(Defines.LineStyles)):
|
||||
self.view.comboBoxPatWaitLineStyle.addItem(Defines.LineStyles[i])
|
||||
self.view.comboBoxPatLoopLineStyle.addItem(Defines.LineStyles[i])
|
||||
self.updateDefaultPatViewerParameters()
|
||||
self.view.comboBoxPatColorSelect.setCurrentIndex(0)
|
||||
self.view.comboBoxPatWait.setCurrentIndex(0)
|
||||
self.view.comboBoxPatLoop.setCurrentIndex(0)
|
||||
self.view.spinBoxPatClockSpacing.setValue(self.clock_vertical_lines_spacing)
|
||||
self.view.checkBoxPatShowClockNumber.setChecked(self.show_clocks_number)
|
||||
self.view.doubleSpinBoxLineWidth.setValue(self.line_width)
|
||||
self.view.lineEditPatternFile.setText(self.det.patfname[0])
|
||||
# rest gets updated after connecting to slots
|
||||
# pattern viewer plot area
|
||||
self.figure, self.ax = plt.subplots()
|
||||
self.canvas = FigureCanvas(self.figure)
|
||||
self.toolbar = NavigationToolbar(self.canvas, self.view)
|
||||
self.mainWindow.gridLayoutPatternViewer.addWidget(self.toolbar)
|
||||
self.mainWindow.gridLayoutPatternViewer.addWidget(self.canvas)
|
||||
self.figure.clear()
|
||||
|
||||
def connect_ui(self):
|
||||
# For Pattern Tab
|
||||
self.view.lineEditStartAddress.editingFinished.connect(self.setPatLimitAddress)
|
||||
self.view.lineEditStopAddress.editingFinished.connect(self.setPatLimitAddress)
|
||||
for i in range(Defines.pattern.loops_count):
|
||||
getattr(self.view,
|
||||
f"lineEditLoop{i}Start").editingFinished.connect(partial(self.setPatLoopStartStopAddress, i))
|
||||
getattr(self.view,
|
||||
f"lineEditLoop{i}Stop").editingFinished.connect(partial(self.setPatLoopStartStopAddress, i))
|
||||
getattr(self.view, f"lineEditLoop{i}Wait").editingFinished.connect(partial(self.setPatLoopWaitAddress, i))
|
||||
getattr(self.view,
|
||||
f"spinBoxLoop{i}Repetition").editingFinished.connect(partial(self.setPatLoopRepetition, i))
|
||||
getattr(self.view, f"spinBoxLoop{i}WaitTime").editingFinished.connect(partial(self.setPatLoopWaitTime, i))
|
||||
self.view.pushButtonCompiler.clicked.connect(self.setCompiler)
|
||||
self.view.pushButtonUncompiled.clicked.connect(self.setUncompiledPatternFile)
|
||||
self.view.pushButtonPatternFile.clicked.connect(self.setPatternFile)
|
||||
self.view.pushButtonLoadPattern.clicked.connect(self.loadPattern)
|
||||
|
||||
self.view.comboBoxPatColorSelect.currentIndexChanged.connect(self.getPatViewerColors)
|
||||
self.view.comboBoxPatWait.currentIndexChanged.connect(self.getPatViewerWaitParameters)
|
||||
self.view.comboBoxPatLoop.currentIndexChanged.connect(self.getPatViewerLoopParameters)
|
||||
|
||||
self.view.comboBoxPatColor.currentIndexChanged.connect(self.updatePatViewerParameters)
|
||||
self.view.comboBoxPatWaitColor.currentIndexChanged.connect(self.updatePatViewerParameters)
|
||||
self.view.comboBoxPatLoopColor.currentIndexChanged.connect(self.updatePatViewerParameters)
|
||||
self.view.comboBoxPatWaitLineStyle.currentIndexChanged.connect(self.updatePatViewerParameters)
|
||||
self.view.comboBoxPatLoopLineStyle.currentIndexChanged.connect(self.updatePatViewerParameters)
|
||||
self.view.doubleSpinBoxWaitAlpha.editingFinished.connect(self.updatePatViewerParameters)
|
||||
self.view.doubleSpinBoxLoopAlpha.editingFinished.connect(self.updatePatViewerParameters)
|
||||
self.view.doubleSpinBoxWaitAlphaRect.editingFinished.connect(self.updatePatViewerParameters)
|
||||
self.view.doubleSpinBoxLoopAlphaRect.editingFinished.connect(self.updatePatViewerParameters)
|
||||
self.view.spinBoxPatClockSpacing.editingFinished.connect(self.updatePatViewerParameters)
|
||||
self.view.checkBoxPatShowClockNumber.stateChanged.connect(self.updatePatViewerParameters)
|
||||
self.view.doubleSpinBoxLineWidth.editingFinished.connect(self.updatePatViewerParameters)
|
||||
self.view.pushButtonViewPattern.clicked.connect(self.viewPattern)
|
||||
|
||||
def refresh(self):
|
||||
self.getPatLimitAddress()
|
||||
for i in range(Defines.pattern.loops_count):
|
||||
self.getPatLoopStartStopAddress(i)
|
||||
self.getPatLoopWaitAddress(i)
|
||||
self.getPatLoopRepetition(i)
|
||||
self.getPatLoopWaitTime(i)
|
||||
|
||||
# Pattern Tab functions
|
||||
|
||||
def getPatLimitAddress(self):
|
||||
retval = self.det.patlimits
|
||||
self.view.lineEditStartAddress.editingFinished.disconnect()
|
||||
self.view.lineEditStopAddress.editingFinished.disconnect()
|
||||
self.view.lineEditStartAddress.setText("0x{:04x}".format(retval[0]))
|
||||
self.view.lineEditStopAddress.setText("0x{:04x}".format(retval[1]))
|
||||
self.view.lineEditStartAddress.editingFinished.connect(self.setPatLimitAddress)
|
||||
self.view.lineEditStopAddress.editingFinished.connect(self.setPatLimitAddress)
|
||||
|
||||
def setPatLimitAddress(self):
|
||||
self.view.lineEditStartAddress.editingFinished.disconnect()
|
||||
self.view.lineEditStopAddress.editingFinished.disconnect()
|
||||
try:
|
||||
start = int(self.view.lineEditStartAddress.text(), 16)
|
||||
stop = int(self.view.lineEditStopAddress.text(), 16)
|
||||
self.det.patlimits = [start, stop]
|
||||
except Exception as e:
|
||||
QtWidgets.QMessageBox.warning(self.mainWindow, "Pattern Limit Address Fail", str(e),
|
||||
QtWidgets.QMessageBox.Ok)
|
||||
pass
|
||||
# TODO: handling double event exceptions
|
||||
self.view.lineEditStartAddress.editingFinished.connect(self.setPatLimitAddress)
|
||||
self.view.lineEditStopAddress.editingFinished.connect(self.setPatLimitAddress)
|
||||
self.getPatLimitAddress()
|
||||
|
||||
def getPatLoopStartStopAddress(self, level):
|
||||
retval = self.det.patloop[level]
|
||||
lineEditStart = getattr(self.view, f"lineEditLoop{level}Start")
|
||||
lineEditStop = getattr(self.view, f"lineEditLoop{level}Stop")
|
||||
lineEditStart.editingFinished.disconnect()
|
||||
lineEditStop.editingFinished.disconnect()
|
||||
lineEditStart.setText("0x{:04x}".format(retval[0]))
|
||||
lineEditStop.setText("0x{:04x}".format(retval[1]))
|
||||
lineEditStart.editingFinished.connect(partial(self.setPatLoopStartStopAddress, level))
|
||||
lineEditStop.editingFinished.connect(partial(self.setPatLoopStartStopAddress, level))
|
||||
|
||||
def setPatLoopStartStopAddress(self, level):
|
||||
lineEditStart = getattr(self.view, f"lineEditLoop{level}Start")
|
||||
lineEditStop = getattr(self.view, f"lineEditLoop{level}Stop")
|
||||
lineEditStart.editingFinished.disconnect()
|
||||
lineEditStop.editingFinished.disconnect()
|
||||
try:
|
||||
start = int(lineEditStart.text(), 16)
|
||||
stop = int(lineEditStop.text(), 16)
|
||||
self.det.patloop[level] = [start, stop]
|
||||
except Exception as e:
|
||||
QtWidgets.QMessageBox.warning(self.mainWindow, "Pattern Loop Start Stop Address Fail", str(e),
|
||||
QtWidgets.QMessageBox.Ok)
|
||||
pass
|
||||
# TODO: handling double event exceptions
|
||||
lineEditStart.editingFinished.connect(partial(self.setPatLoopStartStopAddress, level))
|
||||
lineEditStop.editingFinished.connect(partial(self.setPatLoopStartStopAddress, level))
|
||||
self.getPatLoopStartStopAddress(level)
|
||||
|
||||
def getPatLoopWaitAddress(self, level):
|
||||
retval = self.det.patwait[level]
|
||||
lineEdit = getattr(self.view, f"lineEditLoop{level}Wait")
|
||||
lineEdit.editingFinished.disconnect()
|
||||
lineEdit.setText("0x{:04x}".format(retval))
|
||||
lineEdit.editingFinished.connect(partial(self.setPatLoopWaitAddress, level))
|
||||
|
||||
def setPatLoopWaitAddress(self, level):
|
||||
lineEdit = getattr(self.view, f"lineEditLoop{level}Wait")
|
||||
lineEdit.editingFinished.disconnect()
|
||||
try:
|
||||
addr = int(lineEdit.text(), 16)
|
||||
self.det.patwait[level] = addr
|
||||
except Exception as e:
|
||||
QtWidgets.QMessageBox.warning(self.mainWindow, "Pattern Wait Address Fail", str(e),
|
||||
QtWidgets.QMessageBox.Ok)
|
||||
pass
|
||||
# TODO: handling double event exceptions
|
||||
lineEdit.editingFinished.connect(partial(self.setPatLoopWaitAddress, level))
|
||||
self.getPatLoopWaitAddress(level)
|
||||
|
||||
def getPatLoopRepetition(self, level):
|
||||
retval = self.det.patnloop[level]
|
||||
spinBox = getattr(self.view, f"spinBoxLoop{level}Repetition")
|
||||
spinBox.editingFinished.disconnect()
|
||||
spinBox.setValue(retval)
|
||||
spinBox.editingFinished.connect(partial(self.setPatLoopRepetition, level))
|
||||
|
||||
def setPatLoopRepetition(self, level):
|
||||
spinBox = getattr(self.view, f"spinBoxLoop{level}Repetition")
|
||||
self.det.patnloop[level] = spinBox.value()
|
||||
self.getPatLoopRepetition(level)
|
||||
|
||||
def getPatLoopWaitTime(self, level):
|
||||
retval = self.det.patwaittime[level]
|
||||
spinBox = getattr(self.view, f"spinBoxLoop{level}WaitTime")
|
||||
spinBox.editingFinished.disconnect()
|
||||
spinBox.setValue(retval)
|
||||
spinBox.editingFinished.connect(partial(self.setPatLoopWaitTime, level))
|
||||
|
||||
def setPatLoopWaitTime(self, level):
|
||||
spinBox = getattr(self.view, f"spinBoxLoop{level}WaitTime")
|
||||
self.det.patwaittime[level] = spinBox.value()
|
||||
self.getPatLoopWaitTime(level)
|
||||
|
||||
def setCompiler(self):
|
||||
response = QtWidgets.QFileDialog.getOpenFileName(
|
||||
parent=self.mainWindow,
|
||||
caption="Select a compiler file",
|
||||
directory=str(Path.cwd()),
|
||||
# filter='README (*.md *.ui)'
|
||||
)
|
||||
if response[0]:
|
||||
self.view.lineEditCompiler.setText(response[0])
|
||||
|
||||
def setUncompiledPatternFile(self):
|
||||
filt = 'Pattern code(*.py *.c)'
|
||||
folder = Path(self.det.patfname[0]).parent
|
||||
if not folder:
|
||||
folder = Path.cwd()
|
||||
response = QtWidgets.QFileDialog.getOpenFileName(parent=self.mainWindow,
|
||||
caption="Select an uncompiled pattern file",
|
||||
directory=str(folder),
|
||||
filter=filt)
|
||||
if response[0]:
|
||||
self.view.lineEditUncompiled.setText(response[0])
|
||||
|
||||
def setPatternFile(self):
|
||||
filt = 'Pattern file(*.pyat *.pat)'
|
||||
folder = Path(self.det.patfname[0]).parent
|
||||
if not folder:
|
||||
folder = Path.cwd()
|
||||
response = QtWidgets.QFileDialog.getOpenFileName(parent=self.mainWindow,
|
||||
caption="Select a compiled pattern file",
|
||||
directory=str(folder),
|
||||
filter=filt)
|
||||
if response[0]:
|
||||
self.view.lineEditPatternFile.setText(response[0])
|
||||
|
||||
def compilePattern(self):
|
||||
compilerFile = self.view.lineEditCompiler.text()
|
||||
if not compilerFile:
|
||||
QtWidgets.QMessageBox.warning(self.mainWindow, "Compile Fail", "No compiler selected. Please select one.",
|
||||
QtWidgets.QMessageBox.Ok)
|
||||
return ""
|
||||
|
||||
pattern_file = self.view.lineEditUncompiled.text()
|
||||
|
||||
# if old compile file exists, backup and remove to ensure old copy not loaded
|
||||
oldFile = Path(pattern_file + 'at')
|
||||
if oldFile.is_file():
|
||||
print("Moving old compiled pattern file to _bck")
|
||||
exit_status = os.system('mv ' + str(oldFile) + ' ' + str(oldFile) + '_bkup')
|
||||
if exit_status != 0:
|
||||
retval = QtWidgets.QMessageBox.question(
|
||||
self.mainWindow, "Backup Fail",
|
||||
"Could not make a backup of old compiled code. Proceed anyway to compile and overwrite?",
|
||||
QtWidgets.QMessageBox.Yes, QtWidgets.QMessageBox.No)
|
||||
if retval == QtWidgets.QMessageBox.No:
|
||||
return ""
|
||||
|
||||
compileCommand = compilerFile + ' ' + pattern_file
|
||||
print(compileCommand)
|
||||
print("Compiling pattern code to .pat file")
|
||||
exit_status = os.system(compileCommand)
|
||||
if exit_status != 0:
|
||||
QtWidgets.QMessageBox.warning(self.mainWindow, "Compile Fail", "Could not compile pattern.",
|
||||
QtWidgets.QMessageBox.Ok)
|
||||
return ""
|
||||
pattern_file += 'at'
|
||||
|
||||
return pattern_file
|
||||
|
||||
def getCompiledPatFname(self):
|
||||
if self.view.checkBoxCompile.isChecked():
|
||||
pattern_file = self.compilePattern()
|
||||
# pat name from pattern field
|
||||
else:
|
||||
pattern_file = self.view.lineEditPatternFile.text()
|
||||
if not pattern_file:
|
||||
QtWidgets.QMessageBox.warning(self.mainWindow, "Pattern Fail",
|
||||
"No pattern file selected. Please select one.", QtWidgets.QMessageBox.Ok)
|
||||
return ""
|
||||
return pattern_file
|
||||
|
||||
def loadPattern(self):
|
||||
pattern_file = self.getCompiledPatFname()
|
||||
if not pattern_file:
|
||||
return
|
||||
# load pattern
|
||||
self.det.pattern = pattern_file
|
||||
self.view.lineEditPatternFile.setText(self.det.patfname[0])
|
||||
|
||||
def getPatViewerColors(self):
|
||||
colorLevel = self.view.comboBoxPatColorSelect.currentIndex()
|
||||
color = self.colors_plot[colorLevel]
|
||||
self.view.comboBoxPatColor.currentIndexChanged.disconnect()
|
||||
self.view.comboBoxPatColor.setCurrentIndex(Defines.Colors.index(color))
|
||||
self.view.comboBoxPatColor.currentIndexChanged.connect(self.updatePatViewerParameters)
|
||||
|
||||
def getPatViewerWaitParameters(self):
|
||||
waitLevel = self.view.comboBoxPatWait.currentIndex()
|
||||
color = self.colors_wait[waitLevel]
|
||||
line_style = self.linestyles_wait[waitLevel]
|
||||
alpha = self.alpha_wait[waitLevel]
|
||||
alpha_rect = self.alpha_wait_rect[waitLevel]
|
||||
|
||||
self.view.comboBoxPatWaitColor.currentIndexChanged.disconnect()
|
||||
self.view.comboBoxPatWaitLineStyle.currentIndexChanged.disconnect()
|
||||
self.view.doubleSpinBoxWaitAlpha.editingFinished.disconnect()
|
||||
self.view.doubleSpinBoxWaitAlphaRect.editingFinished.disconnect()
|
||||
|
||||
self.view.comboBoxPatWaitColor.setCurrentIndex(Defines.Colors.index(color))
|
||||
self.view.comboBoxPatWaitLineStyle.setCurrentIndex(Defines.LineStyles.index(line_style))
|
||||
self.view.doubleSpinBoxWaitAlpha.setValue(alpha)
|
||||
self.view.doubleSpinBoxWaitAlphaRect.setValue(alpha_rect)
|
||||
|
||||
self.view.comboBoxPatWaitColor.currentIndexChanged.connect(self.updatePatViewerParameters)
|
||||
self.view.comboBoxPatWaitLineStyle.currentIndexChanged.connect(self.updatePatViewerParameters)
|
||||
self.view.doubleSpinBoxWaitAlpha.editingFinished.connect(self.updatePatViewerParameters)
|
||||
self.view.doubleSpinBoxWaitAlphaRect.editingFinished.connect(self.updatePatViewerParameters)
|
||||
|
||||
def getPatViewerLoopParameters(self):
|
||||
loopLevel = self.view.comboBoxPatLoop.currentIndex()
|
||||
color = self.colors_loop[loopLevel]
|
||||
line_style = self.linestyles_loop[loopLevel]
|
||||
alpha = self.alpha_loop[loopLevel]
|
||||
alpha_rect = self.alpha_loop_rect[loopLevel]
|
||||
|
||||
self.view.comboBoxPatLoopColor.currentIndexChanged.disconnect()
|
||||
self.view.comboBoxPatLoopLineStyle.currentIndexChanged.disconnect()
|
||||
self.view.doubleSpinBoxLoopAlpha.editingFinished.disconnect()
|
||||
self.view.doubleSpinBoxLoopAlphaRect.editingFinished.disconnect()
|
||||
|
||||
self.view.comboBoxPatLoopColor.setCurrentIndex(Defines.Colors.index(color))
|
||||
self.view.comboBoxPatLoopLineStyle.setCurrentIndex(Defines.LineStyles.index(line_style))
|
||||
self.view.doubleSpinBoxLoopAlpha.setValue(alpha)
|
||||
self.view.doubleSpinBoxLoopAlphaRect.setValue(alpha_rect)
|
||||
|
||||
self.view.comboBoxPatLoopColor.currentIndexChanged.connect(self.updatePatViewerParameters)
|
||||
self.view.comboBoxPatLoopLineStyle.currentIndexChanged.connect(self.updatePatViewerParameters)
|
||||
self.view.doubleSpinBoxLoopAlpha.editingFinished.connect(self.updatePatViewerParameters)
|
||||
self.view.doubleSpinBoxLoopAlphaRect.editingFinished.connect(self.updatePatViewerParameters)
|
||||
|
||||
# only at start up
|
||||
def updateDefaultPatViewerParameters(self):
|
||||
self.colors_plot = Defines.Colors_plot.copy()
|
||||
self.colors_wait = Defines.Colors_wait.copy()
|
||||
self.linestyles_wait = Defines.Linestyles_wait.copy()
|
||||
self.alpha_wait = Defines.Alpha_wait.copy()
|
||||
self.alpha_wait_rect = Defines.Alpha_wait_rect.copy()
|
||||
self.colors_loop = Defines.Colors_loop.copy()
|
||||
self.linestyles_loop = Defines.Linestyles_loop.copy()
|
||||
self.alpha_loop = Defines.Alpha_loop.copy()
|
||||
self.alpha_loop_rect = Defines.Alpha_loop_rect.copy()
|
||||
self.clock_vertical_lines_spacing = Defines.Clock_vertical_lines_spacing
|
||||
self.show_clocks_number = Defines.Show_clocks_number
|
||||
self.line_width = Defines.Line_width
|
||||
|
||||
# print('default')
|
||||
# self.printPatViewerParameters()
|
||||
|
||||
def updatePatViewerParameters(self):
|
||||
colorLevel = self.view.comboBoxPatColorSelect.currentIndex()
|
||||
color = self.view.comboBoxPatColor.currentIndex()
|
||||
# self.colors_plot[colorLevel] = f'tab:{Defines.Colors[color].lower()}'
|
||||
self.colors_plot[colorLevel] = Defines.Colors[color]
|
||||
|
||||
waitLevel = self.view.comboBoxPatWait.currentIndex()
|
||||
color = self.view.comboBoxPatWaitColor.currentIndex()
|
||||
line_style = self.view.comboBoxPatWaitLineStyle.currentIndex()
|
||||
alpha = self.view.doubleSpinBoxWaitAlpha.value()
|
||||
alpha_rect = self.view.doubleSpinBoxWaitAlphaRect.value()
|
||||
|
||||
self.colors_wait[waitLevel] = Defines.Colors[color]
|
||||
self.linestyles_wait[waitLevel] = Defines.LineStyles[line_style]
|
||||
self.alpha_wait[waitLevel] = alpha
|
||||
self.alpha_wait_rect[waitLevel] = alpha_rect
|
||||
|
||||
loopLevel = self.view.comboBoxPatLoop.currentIndex()
|
||||
color = self.view.comboBoxPatLoopColor.currentIndex()
|
||||
line_style = self.view.comboBoxPatLoopLineStyle.currentIndex()
|
||||
alpha = self.view.doubleSpinBoxLoopAlpha.value()
|
||||
alpha_rect = self.view.doubleSpinBoxLoopAlphaRect.value()
|
||||
|
||||
self.colors_loop[loopLevel] = Defines.Colors[color]
|
||||
self.linestyles_loop[loopLevel] = Defines.LineStyles[line_style]
|
||||
self.alpha_loop[loopLevel] = alpha
|
||||
self.alpha_loop_rect[loopLevel] = alpha_rect
|
||||
|
||||
self.clock_vertical_lines_spacing = self.view.spinBoxPatClockSpacing.value()
|
||||
self.show_clocks_number = self.view.checkBoxPatShowClockNumber.isChecked()
|
||||
self.line_width = self.view.doubleSpinBoxLineWidth.value()
|
||||
|
||||
# for debugging
|
||||
# self.printPatViewerParameters()
|
||||
|
||||
def printPatViewerParameters(self):
|
||||
print('Pattern Viewer Parameters:')
|
||||
print(f'\tcolor1: {self.colors_plot[0]}, color2: {self.colors_plot[1]}')
|
||||
print(f"\twait color: {self.colors_wait}")
|
||||
print(f"\twait linestyles: {self.linestyles_wait}")
|
||||
print(f"\twait alpha: {self.alpha_wait}")
|
||||
print(f"\twait alpha rect: {self.alpha_wait_rect}")
|
||||
print(f"\tloop color: {self.colors_loop}")
|
||||
print(f"\tloop linestyles: {self.linestyles_loop}")
|
||||
print(f"\tloop alpha: {self.alpha_loop}")
|
||||
print(f"\tloop alpha rect: {self.alpha_loop_rect}")
|
||||
print(f'\tclock vertical lines spacing: {self.clock_vertical_lines_spacing}')
|
||||
print(f'\tshow clocks number: {self.show_clocks_number}')
|
||||
print(f'\tline width: {self.line_width}')
|
||||
print('\n')
|
||||
|
||||
def viewPattern(self):
|
||||
self.plotTab.showPatternViewer(True)
|
||||
pattern_file = self.getCompiledPatFname()
|
||||
if not pattern_file:
|
||||
return
|
||||
|
||||
signalNames = self.det.getSignalNames()
|
||||
p = PlotPattern(
|
||||
pattern_file,
|
||||
signalNames,
|
||||
self.colors_plot,
|
||||
self.colors_wait,
|
||||
self.linestyles_wait,
|
||||
self.alpha_wait,
|
||||
self.alpha_wait_rect,
|
||||
self.colors_loop,
|
||||
self.linestyles_loop,
|
||||
self.alpha_loop,
|
||||
self.alpha_loop_rect,
|
||||
self.clock_vertical_lines_spacing,
|
||||
self.show_clocks_number,
|
||||
self.line_width,
|
||||
)
|
||||
|
||||
plt.close(self.figure)
|
||||
self.mainWindow.gridLayoutPatternViewer.removeWidget(self.canvas)
|
||||
self.canvas.close()
|
||||
self.mainWindow.gridLayoutPatternViewer.removeWidget(self.toolbar)
|
||||
self.toolbar.close()
|
||||
|
||||
try:
|
||||
self.figure = p.patternPlot()
|
||||
self.canvas = FigureCanvas(self.figure)
|
||||
self.toolbar = NavigationToolbar(self.canvas, self.view)
|
||||
self.mainWindow.gridLayoutPatternViewer.addWidget(self.toolbar)
|
||||
self.mainWindow.gridLayoutPatternViewer.addWidget(self.canvas)
|
||||
except Exception as e:
|
||||
QtWidgets.QMessageBox.warning(self.mainWindow, "Pattern Viewer Fail", str(e), QtWidgets.QMessageBox.Ok)
|
||||
pass
|
||||
|
||||
def saveParameters(self) -> list[str]:
|
||||
commands = []
|
||||
for i in range(Defines.pattern.loops_count):
|
||||
commands.append(f"patnloop {i} {getattr(self.view, f'spinBoxLoop{i}Repetition').text()}")
|
||||
commands.append(f"patloop {i} {getattr(self.view, f'lineEditLoop{i}Start').text()}, "
|
||||
f"{getattr(self.view, f'lineEditLoop{i}Stop').text()}")
|
||||
|
||||
commands.append(f"patwait {i} {getattr(self.view, f'lineEditLoop{i}Wait').text()}")
|
||||
commands.append(f"patwaittime {i} {getattr(self.view, f'spinBoxLoop{i}WaitTime').text()}")
|
||||
commands.append(f"patlimits {self.view.lineEditStartAddress.text()}, {self.view.lineEditStopAddress.text()}")
|
||||
# commands.append(f"patfname {self.view.lineEditPatternFile.text()}")
|
||||
return commands
|
519
pyctbgui/pyctbgui/services/Plot.py
Normal file
519
pyctbgui/pyctbgui/services/Plot.py
Normal file
@ -0,0 +1,519 @@
|
||||
import logging
|
||||
from functools import partial
|
||||
import random
|
||||
from pathlib import Path
|
||||
|
||||
import numpy as np
|
||||
from PyQt5 import QtWidgets, QtGui, uic
|
||||
|
||||
import pyqtgraph as pg
|
||||
from pyctbgui.utils import recordOrApplyPedestal
|
||||
from pyqtgraph import PlotWidget
|
||||
|
||||
from pyctbgui.utils.defines import Defines
|
||||
|
||||
|
||||
class PlotTab(QtWidgets.QWidget):
|
||||
|
||||
def __init__(self, parent):
|
||||
super().__init__(parent)
|
||||
self.frame_min: float = 0.0
|
||||
self.frame_max: float = 0.0
|
||||
uic.loadUi(Path(__file__).parent.parent / 'ui' / "plot.ui", parent)
|
||||
self.view = parent
|
||||
self.mainWindow = None
|
||||
self.det = None
|
||||
self.signalsTab = None
|
||||
self.transceiverTab = None
|
||||
self.acquisitionTab = None
|
||||
self.adcTab = None
|
||||
self.cmin: float = 0.0
|
||||
self.cmax: float = 0.0
|
||||
self.colorRangeMode: Defines.colorRange = Defines.colorRange.all
|
||||
self.ignoreHistogramSignal: bool = False
|
||||
self.imagePlots: list[PlotWidget] = []
|
||||
# list of callback functions to notify tabs when we should hide their legend
|
||||
# follows the observer design pattern
|
||||
self.hideLegendObservers = []
|
||||
self.pedestalRecord: bool = False
|
||||
self.pedestalApply: bool = True
|
||||
self.__acqFrames = None
|
||||
self.logger = logging.getLogger('PlotTab')
|
||||
|
||||
def setup_ui(self):
|
||||
self.signalsTab = self.mainWindow.signalsTab
|
||||
self.transceiverTab = self.mainWindow.transceiverTab
|
||||
self.acquisitionTab = self.mainWindow.acquisitionTab
|
||||
self.adcTab = self.mainWindow.adcTab
|
||||
self.initializeColorMaps()
|
||||
|
||||
self.imagePlots = (
|
||||
self.mainWindow.plotAnalogImage,
|
||||
self.mainWindow.plotDigitalImage,
|
||||
self.mainWindow.plotTransceiverImage,
|
||||
)
|
||||
|
||||
def connect_ui(self):
|
||||
self.view.radioButtonNoPlot.clicked.connect(self.plotOptions)
|
||||
self.view.radioButtonWaveform.clicked.connect(self.plotOptions)
|
||||
self.view.radioButtonDistribution.clicked.connect(self.plotOptions)
|
||||
self.view.radioButtonImage.clicked.connect(self.plotOptions)
|
||||
self.view.comboBoxPlot.currentIndexChanged.connect(self.setPixelMap)
|
||||
self.view.comboBoxColorMap.currentIndexChanged.connect(self.setColorMap)
|
||||
self.view.comboBoxZMQHWM.currentIndexChanged.connect(self.setZMQHWM)
|
||||
self.view.spinBoxSerialOffset.editingFinished.connect(self.setSerialOffset)
|
||||
self.view.spinBoxNCount.editingFinished.connect(self.setNCounter)
|
||||
self.view.spinBoxDynamicRange.editingFinished.connect(self.setDynamicRange)
|
||||
self.view.spinBoxImageX.editingFinished.connect(self.setImageX)
|
||||
self.view.spinBoxImageY.editingFinished.connect(self.setImageY)
|
||||
|
||||
self.view.radioButtonPedestalRecord.toggled.connect(self.togglePedestalRecord)
|
||||
self.view.radioButtonPedestalApply.toggled.connect(self.togglePedestalApply)
|
||||
self.view.pushButtonPedestalReset.clicked.connect(self.resetPedestal)
|
||||
self.view.pushButtonSavePedestal.clicked.connect(self.savePedestal)
|
||||
self.view.pushButtonLoadPedestal.clicked.connect(self.loadPedestal)
|
||||
|
||||
self.view.checkBoxRaw.stateChanged.connect(self.setRawData)
|
||||
self.view.spinBoxRawMin.editingFinished.connect(self.setRawData)
|
||||
self.view.spinBoxRawMax.editingFinished.connect(self.setRawData)
|
||||
self.view.checkBoxPedestal.stateChanged.connect(self.setPedestalSubtract)
|
||||
self.view.spinBoxPedestalMin.editingFinished.connect(self.setPedestalSubtract)
|
||||
self.view.spinBoxPedestalMax.editingFinished.connect(self.setPedestalSubtract)
|
||||
self.view.spinBoxFit.editingFinished.connect(self.setFitADC)
|
||||
self.view.spinBoxPlot.editingFinished.connect(self.setPlotBit)
|
||||
self.view.pushButtonReferesh.clicked.connect(self.acquisitionTab.refresh)
|
||||
# color range widgets
|
||||
self.view.cminSpinBox.editingFinished.connect(self.setCmin)
|
||||
self.view.cmaxSpinBox.editingFinished.connect(self.setCmax)
|
||||
self.view.radioButtonAutomatic.clicked.connect(partial(self.setColorRangeMode, Defines.colorRange.all))
|
||||
self.view.radioButtonFixed.clicked.connect(partial(self.setColorRangeMode, Defines.colorRange.fixed))
|
||||
self.view.radioButtonCenter.clicked.connect(partial(self.setColorRangeMode, Defines.colorRange.center))
|
||||
|
||||
for plot in self.imagePlots:
|
||||
plot.scene.sigMouseMoved.connect(partial(self.showPlotValues, plot))
|
||||
plot.getHistogramWidget().item.sigLevelChangeFinished.connect(partial(self.handleHistogramChange, plot))
|
||||
|
||||
self.view.checkBoxShowLegend.stateChanged.connect(self.toggleLegend)
|
||||
|
||||
def refresh(self):
|
||||
self.getZMQHWM()
|
||||
|
||||
def initializeColorMaps(self):
|
||||
self.view.comboBoxColorMap.addItems(Defines.Color_map)
|
||||
self.view.comboBoxColorMap.setCurrentIndex(Defines.Color_map.index(Defines.Default_Color_Map))
|
||||
self.setColorMap()
|
||||
|
||||
def savePedestal(self):
|
||||
"""
|
||||
slot function to save pedestal values
|
||||
"""
|
||||
response = QtWidgets.QFileDialog.getSaveFileName(self.view, "Save Pedestal", str(self.det.fpath))
|
||||
recordOrApplyPedestal.savePedestal(Path(response[0]))
|
||||
self.logger.info(f'saved Pedestal in {response[0]}')
|
||||
|
||||
def loadPedestal(self):
|
||||
"""
|
||||
slot function to load pedestal values
|
||||
"""
|
||||
response = QtWidgets.QFileDialog.getOpenFileName(self.view, "Load Pedestal", str(self.det.fpath))
|
||||
if response[0] == '':
|
||||
return
|
||||
recordOrApplyPedestal.reset(self)
|
||||
try:
|
||||
recordOrApplyPedestal.loadPedestal(Path(response[0]))
|
||||
except (IsADirectoryError, ValueError, EOFError):
|
||||
QtWidgets.QMessageBox.warning(
|
||||
self.view,
|
||||
"Loading Pedestal Failed",
|
||||
"Loading Pedestal failed make sure the file is in the valid .npy format",
|
||||
QtWidgets.QMessageBox.Ok,
|
||||
)
|
||||
self.logger.exception("Exception when loading pedestal")
|
||||
else:
|
||||
self.logger.info(f'loaded Pedestal from {response[0]}')
|
||||
self.updateLabelPedestalFrames(True)
|
||||
|
||||
def togglePedestalRecord(self):
|
||||
"""
|
||||
slot function for pedestal record radio button
|
||||
toggle pedestal record variable and disables the frames spinboxes in acquisition tab or plot tab depenging on
|
||||
the mode
|
||||
"""
|
||||
self.pedestalRecord = not self.pedestalRecord
|
||||
|
||||
def togglePedestalApply(self):
|
||||
"""
|
||||
slot function for pedestal apply radio button
|
||||
"""
|
||||
self.pedestalApply = not self.pedestalApply
|
||||
|
||||
def resetPedestal(self):
|
||||
"""
|
||||
slot function for resetting the pedestal
|
||||
"""
|
||||
recordOrApplyPedestal.reset(self)
|
||||
|
||||
def updateLabelPedestalFrames(self, loadedPedestal=False):
|
||||
"""
|
||||
updates labelPedestalFrames to the length of savedFrames
|
||||
"""
|
||||
if loadedPedestal:
|
||||
self.view.labelPedestalFrames.setText('using loaded pedestal file')
|
||||
else:
|
||||
self.view.labelPedestalFrames.setText(f'recorded frames: {recordOrApplyPedestal.getFramesCount()}')
|
||||
|
||||
def subscribeToggleLegend(self, fn_cbk):
|
||||
"""
|
||||
subscribe to the event of toggling the hide legend checkbox by subscribing
|
||||
with a callback function
|
||||
"""
|
||||
self.hideLegendObservers.append(fn_cbk)
|
||||
|
||||
def toggleLegend(self):
|
||||
"""
|
||||
notify subscribers for the showLegend checkbox event by executing their callbacks
|
||||
"""
|
||||
self.mainWindow.showLegend = not self.mainWindow.showLegend
|
||||
for notify_function in self.hideLegendObservers:
|
||||
notify_function()
|
||||
|
||||
def setCmin(self, value=None):
|
||||
"""
|
||||
slot for setting cmin from cminSpinBox
|
||||
also used as a normal function
|
||||
"""
|
||||
if value is None:
|
||||
self.cmin = self.view.cminSpinBox.value()
|
||||
else:
|
||||
self.cmin = value
|
||||
self.updateColorRangeUI()
|
||||
|
||||
def setCmax(self, value=None):
|
||||
"""
|
||||
slot for setting cmax from cmaxSpinBox
|
||||
also used as a normal function
|
||||
"""
|
||||
if value is None:
|
||||
self.cmax = self.view.cmaxSpinBox.value()
|
||||
else:
|
||||
self.cmax = value
|
||||
self.updateColorRangeUI()
|
||||
|
||||
def setColorRangeMode(self, mode):
|
||||
"""
|
||||
slot for setting the color range mode (all,fixed,3-97%)
|
||||
"""
|
||||
self.colorRangeMode = mode
|
||||
|
||||
# disable or enable cmin/cmax spinboxes
|
||||
enableSpinBoxes = mode == Defines.colorRange.fixed
|
||||
self.view.cminSpinBox.setEnabled(enableSpinBoxes)
|
||||
self.view.cmaxSpinBox.setEnabled(enableSpinBoxes)
|
||||
self.updateColorRange()
|
||||
self.updateColorRangeUI()
|
||||
|
||||
def handleHistogramChange(self, plot):
|
||||
"""
|
||||
slot called after changing the color bar
|
||||
This is called even when pyqtgraph sets the image without any user intervention
|
||||
the class attribute ignore_histogram_signal is set to False before setting the image
|
||||
so that we can distinguish between the signal originates from pyqt or from the user
|
||||
"""
|
||||
if not self.ignoreHistogramSignal:
|
||||
self.cmin, self.cmax = plot.getHistogramWidget().item.getLevels()
|
||||
self.setCmin(self.cmin)
|
||||
self.setCmax(self.cmax)
|
||||
|
||||
self.ignoreHistogramSignal = False
|
||||
# self.setColorRangeMode(Defines.colorRange.fixed)
|
||||
|
||||
def setFrameLimits(self, frame):
|
||||
"""
|
||||
function called from AcquisitionTab::read_zmq to get the maximum and minimum
|
||||
values of the decoded frame and save them in frame_min/frame_max
|
||||
"""
|
||||
self.frame_min = np.min(frame)
|
||||
self.frame_max = np.max(frame)
|
||||
self.updateColorRange()
|
||||
|
||||
def updateColorRange(self):
|
||||
"""
|
||||
for mode:
|
||||
- all: sets cmin and cmax to the maximums/minimum values of the frame
|
||||
- 3-97%: limits cmax and cmin so that we ignore 3% from each end of the whole range
|
||||
- fixed: this function does not change cmin and cmax
|
||||
"""
|
||||
|
||||
if self.colorRangeMode == Defines.colorRange.all:
|
||||
self.cmin = self.frame_min
|
||||
self.cmax = self.frame_max
|
||||
elif self.colorRangeMode == Defines.colorRange.center:
|
||||
self.cmin = self.frame_min + 0.03 * (self.frame_max - self.frame_min)
|
||||
self.cmax = self.frame_max - 0.03 * (self.frame_max - self.frame_min)
|
||||
|
||||
self.updateColorRangeUI()
|
||||
|
||||
def updateColorRangeUI(self):
|
||||
"""
|
||||
updates UI views should be called after every change to cmin or cmax
|
||||
"""
|
||||
for plot in self.imagePlots:
|
||||
plot.getHistogramWidget().item.setLevels(min=self.cmin, max=self.cmax)
|
||||
self.view.cminSpinBox.setValue(self.cmin)
|
||||
self.view.cmaxSpinBox.setValue(self.cmax)
|
||||
|
||||
def setColorMap(self):
|
||||
cm = pg.colormap.getFromMatplotlib(self.view.comboBoxColorMap.currentText())
|
||||
# print(f'color map:{self.comboBoxColorMap.currentText()}')
|
||||
self.mainWindow.plotAnalogImage.setColorMap(cm)
|
||||
self.mainWindow.plotDigitalImage.setColorMap(cm)
|
||||
self.mainWindow.plotTransceiverImage.setColorMap(cm)
|
||||
|
||||
def getZMQHWM(self):
|
||||
|
||||
self.view.comboBoxZMQHWM.currentIndexChanged.disconnect()
|
||||
|
||||
rx_zmq_hwm = self.det.getRxZmqHwm()[0]
|
||||
# ensure same value in client zmq
|
||||
self.det.setClientZmqHwm(rx_zmq_hwm)
|
||||
|
||||
# high readout, low HWM
|
||||
if -1 < rx_zmq_hwm < 25:
|
||||
self.view.comboBoxZMQHWM.setCurrentIndex(1)
|
||||
# low readout, high HWM
|
||||
else:
|
||||
self.view.comboBoxZMQHWM.setCurrentIndex(0)
|
||||
self.view.comboBoxZMQHWM.currentIndexChanged.connect(self.setZMQHWM)
|
||||
|
||||
def setZMQHWM(self):
|
||||
val = self.view.comboBoxZMQHWM.currentIndex()
|
||||
# low readout, high HWM
|
||||
if val == 0:
|
||||
self.det.setRxZmqHwm(Defines.Zmq_hwm_low_speed)
|
||||
self.det.setClientZmqHwm(Defines.Zmq_hwm_low_speed)
|
||||
# high readout, low HWM
|
||||
else:
|
||||
self.det.setRxZmqHwm(Defines.Zmq_hwm_high_speed)
|
||||
self.det.setClientZmqHwm(Defines.Zmq_hwm_high_speed)
|
||||
|
||||
self.getZMQHWM()
|
||||
|
||||
def addSelectedAnalogPlots(self, i):
|
||||
enable = getattr(self.adcTab.view, f"checkBoxADC{i}Plot").isChecked()
|
||||
if enable:
|
||||
self.mainWindow.analogPlots[i].show()
|
||||
if not enable:
|
||||
self.mainWindow.analogPlots[i].hide()
|
||||
|
||||
def addAllSelectedAnalogPlots(self):
|
||||
for i in range(Defines.adc.count):
|
||||
self.addSelectedAnalogPlots(i)
|
||||
|
||||
def removeAllAnalogPlots(self):
|
||||
for i in range(Defines.adc.count):
|
||||
self.mainWindow.analogPlots[i].hide()
|
||||
|
||||
cm = pg.colormap.get('CET-L9') # prepare a linear color map
|
||||
self.mainWindow.plotDigitalImage.setColorMap(cm)
|
||||
|
||||
def addSelectedDigitalPlots(self, i):
|
||||
enable = getattr(self.signalsTab.view, f"checkBoxBIT{i}Plot").isChecked()
|
||||
if enable:
|
||||
self.mainWindow.digitalPlots[i].show()
|
||||
if not enable:
|
||||
self.mainWindow.digitalPlots[i].hide()
|
||||
|
||||
def addAllSelectedDigitalPlots(self):
|
||||
for i in range(Defines.signals.count):
|
||||
self.addSelectedDigitalPlots(i)
|
||||
|
||||
def removeAllDigitalPlots(self):
|
||||
for i in range(Defines.signals.count):
|
||||
self.mainWindow.digitalPlots[i].hide()
|
||||
|
||||
def addSelectedTransceiverPlots(self, i):
|
||||
enable = getattr(self.transceiverTab.view, f"checkBoxTransceiver{i}Plot").isChecked()
|
||||
if enable:
|
||||
self.mainWindow.transceiverPlots[i].show()
|
||||
if not enable:
|
||||
self.mainWindow.transceiverPlots[i].hide()
|
||||
|
||||
def addAllSelectedTransceiverPlots(self):
|
||||
for i in range(Defines.transceiver.count):
|
||||
self.addSelectedTransceiverPlots(i)
|
||||
|
||||
def removeAllTransceiverPlots(self):
|
||||
for i in range(Defines.transceiver.count):
|
||||
self.mainWindow.transceiverPlots[i].hide()
|
||||
|
||||
def showPlot(self):
|
||||
self.mainWindow.plotAnalogWaveform.hide()
|
||||
self.mainWindow.plotDigitalWaveform.hide()
|
||||
self.mainWindow.plotTransceiverWaveform.hide()
|
||||
self.mainWindow.plotAnalogImage.hide()
|
||||
self.mainWindow.plotDigitalImage.hide()
|
||||
self.mainWindow.plotTransceiverImage.hide()
|
||||
self.view.labelDigitalWaveformOption.setDisabled(True)
|
||||
self.view.radioButtonOverlay.setDisabled(True)
|
||||
self.view.radioButtonStripe.setDisabled(True)
|
||||
|
||||
if self.mainWindow.romode.value in [0, 2]:
|
||||
if self.view.radioButtonWaveform.isChecked():
|
||||
self.mainWindow.plotAnalogWaveform.show()
|
||||
elif self.view.radioButtonImage.isChecked():
|
||||
self.mainWindow.plotAnalogImage.show()
|
||||
if self.mainWindow.romode.value in [1, 2, 4]:
|
||||
if self.view.radioButtonWaveform.isChecked():
|
||||
self.mainWindow.plotDigitalWaveform.show()
|
||||
elif self.view.radioButtonImage.isChecked():
|
||||
self.mainWindow.plotDigitalImage.show()
|
||||
self.view.labelDigitalWaveformOption.setEnabled(True)
|
||||
self.view.radioButtonOverlay.setEnabled(True)
|
||||
self.view.radioButtonStripe.setEnabled(True)
|
||||
|
||||
if self.mainWindow.romode.value in [3, 4]:
|
||||
if self.view.radioButtonWaveform.isChecked():
|
||||
self.mainWindow.plotTransceiverWaveform.show()
|
||||
elif self.view.radioButtonImage.isChecked():
|
||||
self.mainWindow.plotTransceiverImage.show()
|
||||
|
||||
def plotOptions(self):
|
||||
|
||||
self.mainWindow.framePatternViewer.hide()
|
||||
self.showPlot()
|
||||
|
||||
# disable plotting
|
||||
self.mainWindow.read_timer.stop()
|
||||
|
||||
if self.view.radioButtonWaveform.isChecked():
|
||||
self.mainWindow.plotAnalogWaveform.setLabel(
|
||||
'left', "<span style=\"color:black;font-size:14px\">Output [ADC]</span>")
|
||||
self.mainWindow.plotAnalogWaveform.setLabel(
|
||||
'bottom', "<span style=\"color:black;font-size:14px\">Analog Sample [#]</span>")
|
||||
self.mainWindow.plotDigitalWaveform.setLabel(
|
||||
'left', "<span style=\"color:black;font-size:14px\">Digital Bit</span>")
|
||||
self.mainWindow.plotDigitalWaveform.setLabel(
|
||||
'bottom', "<span style=\"color:black;font-size:14px\">Digital Sample [#]</span>")
|
||||
self.mainWindow.plotTransceiverWaveform.setLabel(
|
||||
'left', "<span style=\"color:black;font-size:14px\">Transceiver Bit</span>")
|
||||
self.mainWindow.plotTransceiverWaveform.setLabel(
|
||||
'bottom', "<span style=\"color:black;font-size:14px\">Transceiver Sample [#]</span>")
|
||||
|
||||
self.view.stackedWidgetPlotType.setCurrentIndex(0)
|
||||
|
||||
elif self.view.radioButtonImage.isChecked():
|
||||
self.view.stackedWidgetPlotType.setCurrentIndex(2)
|
||||
self.setPixelMap()
|
||||
|
||||
if self.view.radioButtonNoPlot.isChecked():
|
||||
self.view.labelPlotOptions.hide()
|
||||
self.view.stackedWidgetPlotType.hide()
|
||||
# enable plotting
|
||||
else:
|
||||
self.view.labelPlotOptions.show()
|
||||
self.view.stackedWidgetPlotType.show()
|
||||
self.mainWindow.read_timer.start(Defines.Time_Plot_Refresh_ms)
|
||||
|
||||
def setPixelMap(self):
|
||||
if self.view.comboBoxPlot.currentText() == "Matterhorn":
|
||||
self.mainWindow.nTransceiverRows = Defines.Matterhorn.nRows
|
||||
self.mainWindow.nTransceiverCols = Defines.Matterhorn.nCols
|
||||
elif self.view.comboBoxPlot.currentText() == "Moench04":
|
||||
self.mainWindow.nAnalogRows = Defines.Moench04.nRows
|
||||
self.mainWindow.nAnalogCols = Defines.Moench04.nCols
|
||||
|
||||
def showPatternViewer(self, enable):
|
||||
if enable:
|
||||
self.mainWindow.framePatternViewer.show()
|
||||
self.mainWindow.framePlot.hide()
|
||||
elif self.mainWindow.framePatternViewer.isVisible():
|
||||
self.mainWindow.framePatternViewer.hide()
|
||||
self.mainWindow.framePlot.show()
|
||||
self.showPlot()
|
||||
|
||||
def setSerialOffset(self):
|
||||
print("plot options - Not implemented yet")
|
||||
# TODO:
|
||||
|
||||
def setNCounter(self):
|
||||
print("plot options - Not implemented yet")
|
||||
# TODO:
|
||||
|
||||
def setDynamicRange(self):
|
||||
print("plot options - Not implemented yet")
|
||||
# TODO:
|
||||
|
||||
def setImageX(self):
|
||||
print("plot options - Not implemented yet")
|
||||
# TODO:
|
||||
|
||||
def setImageY(self):
|
||||
print("plot options - Not implemented yet")
|
||||
# TODO:
|
||||
|
||||
def setRawData(self):
|
||||
print("plot options - Not implemented yet")
|
||||
# TODO: raw data, min, max
|
||||
|
||||
def setPedestalSubtract(self):
|
||||
print("plot options - Not implemented yet")
|
||||
# TODO: pedestal, min, max
|
||||
|
||||
def setFitADC(self):
|
||||
print("plot options - Not implemented yet")
|
||||
# TODO:
|
||||
|
||||
def setPlotBit(self):
|
||||
print("plot options - Not implemented yet")
|
||||
# TODO:
|
||||
|
||||
def getRandomColor(self):
|
||||
'''
|
||||
Returns a random color range (except white) in format string eg. "#aabbcc"
|
||||
'''
|
||||
randomColor = random.randrange(0, 0xffffaa, 0xaa)
|
||||
return "#{:06x}".format(randomColor)
|
||||
|
||||
def getActiveColor(self, button):
|
||||
return button.palette().color(QtGui.QPalette.Window)
|
||||
|
||||
def setActiveColor(self, button, str_color):
|
||||
button.setStyleSheet(":enabled {background-color: %s" % str_color + "} :disabled {background-color: grey}")
|
||||
|
||||
def showPalette(self, button):
|
||||
color = QtWidgets.QColorDialog.getColor()
|
||||
if color.isValid():
|
||||
self.setActiveColor(button, color.name())
|
||||
# get the RGB Values
|
||||
# print(color.getRgb())
|
||||
|
||||
def showPlotValues(self, sender, pos):
|
||||
x = sender.getImageItem().mapFromScene(pos).x()
|
||||
y = sender.getImageItem().mapFromScene(pos).y()
|
||||
val = 0
|
||||
nMaxY = self.mainWindow.nAnalogRows
|
||||
nMaxX = self.mainWindow.nAnalogCols
|
||||
frame = self.mainWindow.analog_frame
|
||||
if sender == self.mainWindow.plotDigitalImage:
|
||||
nMaxY = self.mainWindow.nDigitalRows
|
||||
nMaxX = self.mainWindow.nDigitalCols
|
||||
frame = self.mainWindow.digital_frame
|
||||
elif sender == self.mainWindow.plotTransceiverImage:
|
||||
nMaxY = self.mainWindow.nTransceiverRows
|
||||
nMaxX = self.mainWindow.nTransceiverCols
|
||||
frame = self.mainWindow.transceiver_frame
|
||||
if 0 <= x < nMaxX and 0 <= y < nMaxY and not np.array_equal(frame, []):
|
||||
val = frame[int(x), int(y)]
|
||||
message = f'[{x:.2f}, {y:.2f}] = {val:.2f}'
|
||||
sender.setToolTip(message)
|
||||
# print(message)
|
||||
else:
|
||||
sender.setToolTip('')
|
||||
|
||||
def saveParameters(self):
|
||||
commands = []
|
||||
if self.view.comboBoxZMQHWM.currentIndex() == 0:
|
||||
commands.append(f"zmqhwm {Defines.Zmq_hwm_low_speed}")
|
||||
else:
|
||||
commands.append(f"zmqhwm {Defines.Zmq_hwm_high_speed}")
|
||||
return commands
|
123
pyctbgui/pyctbgui/services/PowerSupplies.py
Normal file
123
pyctbgui/pyctbgui/services/PowerSupplies.py
Normal file
@ -0,0 +1,123 @@
|
||||
from functools import partial
|
||||
from pathlib import Path
|
||||
|
||||
from PyQt5 import QtWidgets, uic
|
||||
from pyctbgui.utils.defines import Defines
|
||||
|
||||
from slsdet import dacIndex
|
||||
|
||||
|
||||
class PowerSuppliesTab(QtWidgets.QWidget):
|
||||
|
||||
def __init__(self, parent):
|
||||
super().__init__(parent)
|
||||
uic.loadUi(Path(__file__).parent.parent / 'ui' / "powerSupplies.ui", parent)
|
||||
self.view = parent
|
||||
|
||||
def refresh(self):
|
||||
self.updateVoltageNames()
|
||||
for i in Defines.powerSupplies:
|
||||
self.getVoltage(i)
|
||||
self.getCurrent(i)
|
||||
|
||||
def connect_ui(self):
|
||||
for i in Defines.powerSupplies:
|
||||
spinBox = getattr(self.view, f"spinBoxV{i}")
|
||||
checkBox = getattr(self.view, f"checkBoxV{i}")
|
||||
spinBox.editingFinished.connect(partial(self.setVoltage, i))
|
||||
checkBox.stateChanged.connect(partial(self.setVoltage, i))
|
||||
self.view.pushButtonPowerOff.clicked.connect(self.powerOff)
|
||||
|
||||
def setup_ui(self):
|
||||
for i in Defines.powerSupplies:
|
||||
dac = getattr(dacIndex, f"V_POWER_{i}")
|
||||
spinBox = getattr(self.view, f"spinBoxV{i}")
|
||||
checkBox = getattr(self.view, f"checkBoxV{i}")
|
||||
retval = self.det.getPower(dac)[0]
|
||||
spinBox.setValue(retval)
|
||||
if retval == 0:
|
||||
checkBox.setChecked(False)
|
||||
spinBox.setDisabled(True)
|
||||
|
||||
def updateVoltageNames(self):
|
||||
retval = self.det.getPowerNames()
|
||||
getattr(self.view, "checkBoxVA").setText(retval[0])
|
||||
getattr(self.view, "checkBoxVB").setText(retval[1])
|
||||
getattr(self.view, "checkBoxVC").setText(retval[2])
|
||||
getattr(self.view, "checkBoxVD").setText(retval[3])
|
||||
getattr(self.view, "checkBoxVIO").setText(retval[4])
|
||||
|
||||
def getVoltage(self, i):
|
||||
spinBox = getattr(self.view, f"spinBoxV{i}")
|
||||
checkBox = getattr(self.view, f"checkBoxV{i}")
|
||||
voltageIndex = getattr(dacIndex, f"V_POWER_{i}")
|
||||
label = getattr(self.view, f"labelV{i}")
|
||||
|
||||
spinBox.editingFinished.disconnect()
|
||||
checkBox.stateChanged.disconnect()
|
||||
|
||||
retval = self.det.getMeasuredPower(voltageIndex)[0]
|
||||
# spinBox.setValue(retval)
|
||||
if retval > 1:
|
||||
checkBox.setChecked(True)
|
||||
if checkBox.isChecked():
|
||||
spinBox.setEnabled(True)
|
||||
else:
|
||||
spinBox.setDisabled(True)
|
||||
label.setText(f'{str(retval)} mV')
|
||||
|
||||
spinBox.editingFinished.connect(partial(self.setVoltage, i))
|
||||
checkBox.stateChanged.connect(partial(self.setVoltage, i))
|
||||
|
||||
self.getVChip()
|
||||
|
||||
# TODO: handle multiple events when pressing enter (twice)
|
||||
|
||||
def setVoltage(self, i):
|
||||
checkBox = getattr(self.view, f"checkBoxV{i}")
|
||||
spinBox = getattr(self.view, f"spinBoxV{i}")
|
||||
voltageIndex = getattr(dacIndex, f"V_POWER_{i}")
|
||||
spinBox.editingFinished.disconnect()
|
||||
|
||||
value = 0
|
||||
if checkBox.isChecked():
|
||||
value = spinBox.value()
|
||||
try:
|
||||
self.det.setPower(voltageIndex, value)
|
||||
except Exception as e:
|
||||
QtWidgets.QMessageBox.warning(self.mainWindow, "Voltage Fail", str(e), QtWidgets.QMessageBox.Ok)
|
||||
pass
|
||||
|
||||
# TODO: (properly) disconnecting and connecting to handle multiple events (out of focus and pressing enter).
|
||||
spinBox.editingFinished.connect(partial(self.setVoltage, i))
|
||||
self.getVoltage(i)
|
||||
self.getCurrent(i)
|
||||
|
||||
def getCurrent(self, i):
|
||||
label = getattr(self.view, f"labelI{i}")
|
||||
currentIndex = getattr(dacIndex, f"I_POWER_{i}")
|
||||
retval = self.det.getMeasuredCurrent(currentIndex)[0]
|
||||
label.setText(f'{str(retval)} mA')
|
||||
|
||||
def getVChip(self):
|
||||
self.view.spinBoxVChip.setValue(self.det.getPower(dacIndex.V_POWER_CHIP)[0])
|
||||
|
||||
def powerOff(self):
|
||||
for i in Defines.powerSupplies:
|
||||
# set all voltages to 0
|
||||
checkBox = getattr(self.view, f"checkBoxV{i}")
|
||||
checkBox.stateChanged.disconnect()
|
||||
checkBox.setChecked(False)
|
||||
checkBox.stateChanged.connect(partial(self.setVoltage, i))
|
||||
self.setVoltage(i)
|
||||
|
||||
def saveParameters(self) -> list:
|
||||
commands = []
|
||||
for i in Defines.powerSupplies:
|
||||
enabled = getattr(self.view, f"checkBoxV{i}").isChecked()
|
||||
if enabled:
|
||||
value = getattr(self.view, f"spinBoxV{i}").value()
|
||||
commands.append(f"v_{i.lower()} {value}")
|
||||
else:
|
||||
commands.append(f"v_{i.lower()} 0")
|
||||
return commands
|
373
pyctbgui/pyctbgui/services/Signals.py
Normal file
373
pyctbgui/pyctbgui/services/Signals.py
Normal file
@ -0,0 +1,373 @@
|
||||
from functools import partial
|
||||
from pathlib import Path
|
||||
|
||||
import numpy as np
|
||||
from PyQt5 import QtWidgets, uic
|
||||
import pyqtgraph as pg
|
||||
from pyqtgraph import LegendItem
|
||||
|
||||
from pyctbgui.utils.bit_utils import bit_is_set, manipulate_bit
|
||||
from pyctbgui.utils.defines import Defines
|
||||
from pyctbgui.utils.recordOrApplyPedestal import recordOrApplyPedestal
|
||||
|
||||
|
||||
class SignalsTab(QtWidgets.QWidget):
|
||||
|
||||
def __init__(self, parent):
|
||||
super().__init__(parent)
|
||||
uic.loadUi(Path(__file__).parent.parent / 'ui' / "signals.ui", parent)
|
||||
self.view = parent
|
||||
self.mainWindow = None
|
||||
self.det = None
|
||||
self.plotTab = None
|
||||
self.legend: LegendItem | None = None
|
||||
self.rx_dbitoffset = None
|
||||
self.rx_dbitlist = None
|
||||
|
||||
def refresh(self):
|
||||
self.updateSignalNames()
|
||||
self.updateDigitalBitEnable()
|
||||
self.updateIOOut()
|
||||
self.getDBitOffset()
|
||||
|
||||
def connect_ui(self):
|
||||
for i in range(Defines.signals.count):
|
||||
getattr(self.view, f"checkBoxBIT{i}DB").stateChanged.connect(partial(self.setDigitalBitEnable, i))
|
||||
getattr(self.view, f"checkBoxBIT{i}Out").stateChanged.connect(partial(self.setIOOut, i))
|
||||
getattr(self.view, f"checkBoxBIT{i}Plot").stateChanged.connect(partial(self.setEnableBitPlot, i))
|
||||
getattr(self.view, f"pushButtonBIT{i}").clicked.connect(partial(self.selectBitColor, i))
|
||||
self.view.checkBoxBIT0_31DB.stateChanged.connect(
|
||||
partial(self.setDigitalBitEnableRange, 0, Defines.signals.half))
|
||||
self.view.checkBoxBIT32_63DB.stateChanged.connect(
|
||||
partial(self.setDigitalBitEnableRange, Defines.signals.half, Defines.signals.count))
|
||||
self.view.checkBoxBIT0_31Plot.stateChanged.connect(partial(self.setEnableBitPlotRange, 0,
|
||||
Defines.signals.half))
|
||||
self.view.checkBoxBIT32_63Plot.stateChanged.connect(
|
||||
partial(self.setEnableBitPlotRange, Defines.signals.half, Defines.signals.count))
|
||||
self.view.checkBoxBIT0_31Out.stateChanged.connect(partial(self.setIOOutRange, 0, Defines.signals.half))
|
||||
self.view.checkBoxBIT32_63Out.stateChanged.connect(
|
||||
partial(self.setIOOutRange, Defines.signals.half, Defines.signals.count))
|
||||
self.view.lineEditPatIOCtrl.editingFinished.connect(self.setIOOutReg)
|
||||
self.view.spinBoxDBitOffset.editingFinished.connect(self.setDbitOffset)
|
||||
|
||||
def setup_ui(self):
|
||||
self.plotTab = self.mainWindow.plotTab
|
||||
|
||||
for i in range(Defines.signals.count):
|
||||
self.setDBitButtonColor(i, self.plotTab.getRandomColor())
|
||||
|
||||
self.initializeAllDigitalPlots()
|
||||
|
||||
self.legend = self.mainWindow.plotDigitalWaveform.getPlotItem().legend
|
||||
self.legend.clear()
|
||||
# subscribe to toggle legend
|
||||
self.plotTab.subscribeToggleLegend(self.updateLegend)
|
||||
|
||||
def getEnabledPlots(self):
|
||||
"""
|
||||
return plots that are shown (checkBoxTransceiver{i}Plot is checked)
|
||||
"""
|
||||
enabledPlots = []
|
||||
self.legend.clear()
|
||||
for i in range(Defines.signals.count):
|
||||
if getattr(self.view, f'checkBoxBIT{i}Plot').isChecked():
|
||||
plotName = getattr(self.view, f"labelBIT{i}").text()
|
||||
enabledPlots.append((self.mainWindow.digitalPlots[i], plotName))
|
||||
return enabledPlots
|
||||
|
||||
def updateLegend(self):
|
||||
"""
|
||||
update the legend for the signals waveform plot
|
||||
should be called after checking or unchecking plot checkbox
|
||||
"""
|
||||
if not self.mainWindow.showLegend:
|
||||
self.legend.clear()
|
||||
else:
|
||||
for plot, name in self.getEnabledPlots():
|
||||
self.legend.addItem(plot, name)
|
||||
|
||||
@recordOrApplyPedestal
|
||||
def _processWaveformData(self, data, aSamples, dSamples, rx_dbitlist, isPlottedArray, rx_dbitoffset, romode,
|
||||
nADCEnabled):
|
||||
"""
|
||||
transform raw waveform data into a processed numpy array
|
||||
@param data: raw waveform data
|
||||
"""
|
||||
dbitoffset = rx_dbitoffset
|
||||
if romode == 2:
|
||||
dbitoffset += nADCEnabled * 2 * aSamples
|
||||
digital_array = np.array(np.frombuffer(data, offset=dbitoffset, dtype=np.uint8))
|
||||
nbitsPerDBit = dSamples
|
||||
if nbitsPerDBit % 8 != 0:
|
||||
nbitsPerDBit += (8 - (dSamples % 8))
|
||||
offset = 0
|
||||
arr = []
|
||||
for i in rx_dbitlist:
|
||||
# where numbits * numsamples is not a multiple of 8
|
||||
if offset % 8 != 0:
|
||||
offset += (8 - (offset % 8))
|
||||
if not isPlottedArray[i]:
|
||||
offset += nbitsPerDBit
|
||||
return None
|
||||
waveform = np.zeros(dSamples)
|
||||
for iSample in range(dSamples):
|
||||
# all samples for digital bit together from slsReceiver
|
||||
index = int(offset / 8)
|
||||
iBit = offset % 8
|
||||
bit = (digital_array[index] >> iBit) & 1
|
||||
waveform[iSample] = bit
|
||||
offset += 1
|
||||
arr.append(waveform)
|
||||
|
||||
return np.array(arr)
|
||||
|
||||
def processWaveformData(self, data, aSamples, dSamples):
|
||||
"""
|
||||
view function
|
||||
plots processed waveform data
|
||||
data: raw waveform data
|
||||
dsamples: digital samples
|
||||
asamples: analog samples
|
||||
"""
|
||||
waveforms = {}
|
||||
isPlottedArray = {i: getattr(self.view, f"checkBoxBIT{i}Plot").isChecked() for i in self.rx_dbitlist}
|
||||
|
||||
digital_array = self._processWaveformData(data, aSamples, dSamples, self.rx_dbitlist, isPlottedArray,
|
||||
self.rx_dbitoffset, self.mainWindow.romode.value,
|
||||
self.mainWindow.nADCEnabled)
|
||||
|
||||
irow = 0
|
||||
for idx, i in enumerate(self.rx_dbitlist):
|
||||
# bits enabled but not plotting
|
||||
waveform = digital_array[idx]
|
||||
if waveform is None:
|
||||
continue
|
||||
self.mainWindow.digitalPlots[i].setData(waveform)
|
||||
plotName = getattr(self.view, f"labelBIT{i}").text()
|
||||
waveforms[plotName] = waveform
|
||||
# TODO: left axis does not show 0 to 1, but keeps increasing
|
||||
if self.plotTab.view.radioButtonStripe.isChecked():
|
||||
self.mainWindow.digitalPlots[i].setY(irow * 2)
|
||||
irow += 1
|
||||
else:
|
||||
self.mainWindow.digitalPlots[i].setY(0)
|
||||
return waveforms
|
||||
|
||||
def initializeAllDigitalPlots(self):
|
||||
self.mainWindow.plotDigitalWaveform = pg.plot()
|
||||
self.mainWindow.plotDigitalWaveform.addLegend(colCount=Defines.colCount)
|
||||
self.mainWindow.verticalLayoutPlot.addWidget(self.mainWindow.plotDigitalWaveform, 3)
|
||||
self.mainWindow.digitalPlots = {}
|
||||
waveform = np.zeros(1000)
|
||||
for i in range(Defines.signals.count):
|
||||
pen = pg.mkPen(color=self.getDBitButtonColor(i), width=1)
|
||||
legendName = getattr(self.view, f"labelBIT{i}").text()
|
||||
self.mainWindow.digitalPlots[i] = self.mainWindow.plotDigitalWaveform.plot(waveform,
|
||||
pen=pen,
|
||||
name=legendName,
|
||||
stepMode="left")
|
||||
self.mainWindow.digitalPlots[i].hide()
|
||||
|
||||
self.mainWindow.plotDigitalImage = pg.ImageView()
|
||||
self.mainWindow.nDigitalRows = 0
|
||||
self.mainWindow.nDigitalCols = 0
|
||||
self.mainWindow.digital_frame = np.zeros((self.mainWindow.nDigitalRows, self.mainWindow.nDigitalCols))
|
||||
self.mainWindow.plotDigitalImage.setImage(self.mainWindow.digital_frame)
|
||||
self.mainWindow.verticalLayoutPlot.addWidget(self.mainWindow.plotDigitalImage, 4)
|
||||
|
||||
def updateSignalNames(self):
|
||||
for i, name in enumerate(self.det.getSignalNames()):
|
||||
getattr(self.view, f"labelBIT{i}").setText(name)
|
||||
|
||||
def getDigitalBitEnable(self, i, dbitList):
|
||||
checkBox = getattr(self.view, f"checkBoxBIT{i}DB")
|
||||
checkBox.stateChanged.disconnect()
|
||||
checkBox.setChecked(i in list(dbitList))
|
||||
checkBox.stateChanged.connect(partial(self.setDigitalBitEnable, i))
|
||||
|
||||
def updateDigitalBitEnable(self):
|
||||
retval = self.det.rx_dbitlist
|
||||
self.rx_dbitlist = list(retval)
|
||||
self.mainWindow.nDBitEnabled = len(list(retval))
|
||||
for i in range(Defines.signals.count):
|
||||
self.getDigitalBitEnable(i, retval)
|
||||
self.getEnableBitPlot(i)
|
||||
self.getEnableBitColor(i)
|
||||
self.plotTab.addSelectedDigitalPlots(i)
|
||||
self.getDigitalBitEnableRange(retval)
|
||||
self.getEnableBitPlotRange()
|
||||
|
||||
def setDigitalBitEnable(self, i):
|
||||
bitList = self.det.rx_dbitlist
|
||||
checkBox = getattr(self.view, f"checkBoxBIT{i}DB")
|
||||
if checkBox.isChecked():
|
||||
bitList.append(i)
|
||||
else:
|
||||
bitList.remove(i)
|
||||
self.det.rx_dbitlist = bitList
|
||||
|
||||
self.updateDigitalBitEnable()
|
||||
|
||||
def getDigitalBitEnableRange(self, dbitList):
|
||||
self.view.checkBoxBIT0_31DB.stateChanged.disconnect()
|
||||
self.view.checkBoxBIT32_63DB.stateChanged.disconnect()
|
||||
self.view.checkBoxBIT0_31DB.setChecked(all(x in list(dbitList) for x in range(Defines.signals.half)))
|
||||
self.view.checkBoxBIT32_63DB.setChecked(
|
||||
all(x in list(dbitList) for x in range(Defines.signals.half, Defines.signals.count)))
|
||||
self.view.checkBoxBIT0_31DB.stateChanged.connect(
|
||||
partial(self.setDigitalBitEnableRange, 0, Defines.signals.half))
|
||||
self.view.checkBoxBIT32_63DB.stateChanged.connect(
|
||||
partial(self.setDigitalBitEnableRange, Defines.signals.half, Defines.signals.count))
|
||||
|
||||
def setDigitalBitEnableRange(self, start_nr, end_nr):
|
||||
bitList = self.det.rx_dbitlist
|
||||
checkBox = getattr(self.view, f"checkBoxBIT{start_nr}_{end_nr - 1}DB")
|
||||
for i in range(start_nr, end_nr):
|
||||
if checkBox.isChecked():
|
||||
if i not in list(bitList):
|
||||
bitList.append(i)
|
||||
else:
|
||||
if i in list(bitList):
|
||||
bitList.remove(i)
|
||||
self.det.rx_dbitlist = bitList
|
||||
|
||||
self.updateDigitalBitEnable()
|
||||
|
||||
def getEnableBitPlot(self, i):
|
||||
checkBox = getattr(self.view, f"checkBoxBIT{i}DB")
|
||||
checkBoxPlot = getattr(self.view, f"checkBoxBIT{i}Plot")
|
||||
checkBoxPlot.setEnabled(checkBox.isChecked())
|
||||
|
||||
def setEnableBitPlot(self, i):
|
||||
pushButton = getattr(self.view, f"pushButtonBIT{i}")
|
||||
checkBox = getattr(self.view, f"checkBoxBIT{i}Plot")
|
||||
pushButton.setEnabled(checkBox.isChecked())
|
||||
|
||||
self.getEnableBitPlotRange()
|
||||
self.plotTab.addSelectedDigitalPlots(i)
|
||||
self.updateLegend()
|
||||
|
||||
def getEnableBitPlotRange(self):
|
||||
self.view.checkBoxBIT0_31Plot.stateChanged.disconnect()
|
||||
self.view.checkBoxBIT32_63Plot.stateChanged.disconnect()
|
||||
self.view.checkBoxBIT0_31Plot.setEnabled(
|
||||
all(getattr(self.view, f"checkBoxBIT{i}Plot").isEnabled() for i in range(Defines.signals.half)))
|
||||
self.view.checkBoxBIT32_63Plot.setEnabled(
|
||||
all(
|
||||
getattr(self.view, f"checkBoxBIT{i}Plot").isEnabled()
|
||||
for i in range(Defines.signals.half, Defines.signals.count)))
|
||||
self.view.checkBoxBIT0_31Plot.setChecked(
|
||||
all(getattr(self.view, f"checkBoxBIT{i}Plot").isChecked() for i in range(Defines.signals.half)))
|
||||
self.view.checkBoxBIT32_63Plot.setChecked(
|
||||
all(
|
||||
getattr(self.view, f"checkBoxBIT{i}Plot").isChecked()
|
||||
for i in range(Defines.signals.half, Defines.signals.count)))
|
||||
self.view.checkBoxBIT0_31Plot.stateChanged.connect(partial(self.setEnableBitPlotRange, 0,
|
||||
Defines.signals.half))
|
||||
self.view.checkBoxBIT32_63Plot.stateChanged.connect(
|
||||
partial(self.setEnableBitPlotRange, Defines.signals.half, Defines.signals.count))
|
||||
|
||||
def setEnableBitPlotRange(self, start_nr, end_nr):
|
||||
checkBox = getattr(self.view, f"checkBoxBIT{start_nr}_{end_nr - 1}Plot")
|
||||
enable = checkBox.isChecked()
|
||||
for i in range(start_nr, end_nr):
|
||||
checkBox = getattr(self.view, f"checkBoxBIT{i}Plot")
|
||||
checkBox.setChecked(enable)
|
||||
self.plotTab.addAllSelectedDigitalPlots()
|
||||
|
||||
def getEnableBitColor(self, i):
|
||||
checkBox = getattr(self.view, f"checkBoxBIT{i}Plot")
|
||||
pushButton = getattr(self.view, f"pushButtonBIT{i}")
|
||||
pushButton.setEnabled(checkBox.isEnabled() and checkBox.isChecked())
|
||||
|
||||
def selectBitColor(self, i):
|
||||
pushButton = getattr(self.view, f"pushButtonBIT{i}")
|
||||
self.plotTab.showPalette(pushButton)
|
||||
pen = pg.mkPen(color=self.getDBitButtonColor(i), width=1)
|
||||
self.mainWindow.digitalPlots[i].setPen(pen)
|
||||
|
||||
def getDBitButtonColor(self, i):
|
||||
pushButton = getattr(self.view, f"pushButtonBIT{i}")
|
||||
return self.plotTab.getActiveColor(pushButton)
|
||||
|
||||
def setDBitButtonColor(self, i, color):
|
||||
pushButton = getattr(self.view, f"pushButtonBIT{i}")
|
||||
return self.plotTab.setActiveColor(pushButton, color)
|
||||
|
||||
def getIOOutReg(self):
|
||||
retval = self.det.patioctrl
|
||||
self.view.lineEditPatIOCtrl.editingFinished.disconnect()
|
||||
self.view.lineEditPatIOCtrl.setText("0x{:016x}".format(retval))
|
||||
self.view.lineEditPatIOCtrl.editingFinished.connect(self.setIOOutReg)
|
||||
return retval
|
||||
|
||||
def setIOOutReg(self):
|
||||
self.view.lineEditPatIOCtrl.editingFinished.disconnect()
|
||||
try:
|
||||
self.det.patioctrl = int(self.view.lineEditPatIOCtrl.text(), 16)
|
||||
except Exception as e:
|
||||
QtWidgets.QMessageBox.warning(self.mainWindow, "IO Out Fail", str(e), QtWidgets.QMessageBox.Ok)
|
||||
pass
|
||||
# TODO: handling double event exceptions
|
||||
self.view.lineEditPatIOCtrl.editingFinished.connect(self.setIOOutReg)
|
||||
self.updateIOOut()
|
||||
|
||||
def updateCheckBoxIOOut(self, i, out):
|
||||
checkBox = getattr(self.view, f"checkBoxBIT{i}Out")
|
||||
checkBox.stateChanged.disconnect()
|
||||
checkBox.setChecked(bit_is_set(out, i))
|
||||
checkBox.stateChanged.connect(partial(self.setIOOut, i))
|
||||
|
||||
def updateIOOut(self):
|
||||
retval = self.getIOOutReg()
|
||||
for i in range(Defines.signals.count):
|
||||
self.updateCheckBoxIOOut(i, retval)
|
||||
self.getIOoutRange(retval)
|
||||
|
||||
def setIOOut(self, i):
|
||||
out = self.det.patioctrl
|
||||
checkBox = getattr(self.view, f"checkBoxBIT{i}Out")
|
||||
mask = manipulate_bit(checkBox.isChecked(), out, i)
|
||||
self.det.patioctrl = mask
|
||||
|
||||
retval = self.getIOOutReg()
|
||||
self.updateCheckBoxIOOut(i, retval)
|
||||
self.getIOoutRange(retval)
|
||||
|
||||
def getIOoutRange(self, out):
|
||||
self.view.checkBoxBIT0_31Out.stateChanged.disconnect()
|
||||
self.view.checkBoxBIT32_63Out.stateChanged.disconnect()
|
||||
self.view.checkBoxBIT0_31Out.setChecked((out & Defines.signals.BIT0_31_MASK) == Defines.signals.BIT0_31_MASK)
|
||||
self.view.checkBoxBIT32_63Out.setChecked((out
|
||||
& Defines.signals.BIT32_63_MASK) == Defines.signals.BIT32_63_MASK)
|
||||
self.view.checkBoxBIT0_31Out.stateChanged.connect(partial(self.setIOOutRange, 0, Defines.signals.half))
|
||||
self.view.checkBoxBIT32_63Out.stateChanged.connect(
|
||||
partial(self.setIOOutRange, Defines.signals.half, Defines.signals.count))
|
||||
|
||||
def setIOOutRange(self, start_nr, end_nr):
|
||||
out = self.det.patioctrl
|
||||
checkBox = getattr(self.view, f"checkBoxBIT{start_nr}_{end_nr - 1}Out")
|
||||
mask = getattr(Defines.signals, f"BIT{start_nr}_{end_nr - 1}_MASK")
|
||||
if checkBox.isChecked():
|
||||
self.det.patioctrl = out | mask
|
||||
else:
|
||||
self.det.patioctrl = out & ~mask
|
||||
self.updateIOOut()
|
||||
|
||||
def getDBitOffset(self):
|
||||
self.view.spinBoxDBitOffset.editingFinished.disconnect()
|
||||
self.rx_dbitoffset = self.det.rx_dbitoffset
|
||||
self.view.spinBoxDBitOffset.setValue(self.rx_dbitoffset)
|
||||
self.view.spinBoxDBitOffset.editingFinished.connect(self.setDbitOffset)
|
||||
|
||||
def setDbitOffset(self):
|
||||
self.det.rx_dbitoffset = self.view.spinBoxDBitOffset.value()
|
||||
|
||||
def saveParameters(self) -> list:
|
||||
commands = []
|
||||
dblist = [str(i) for i in range(Defines.signals.count) if getattr(self.view, f"checkBoxBIT{i}DB").isChecked()]
|
||||
if len(dblist) > 0:
|
||||
commands.append(f"rx_dbitlist {', '.join(dblist)}")
|
||||
commands.append(f"rx_dbitoffset {self.view.spinBoxDBitOffset.value()}")
|
||||
commands.append(f"patioctrl {self.view.lineEditPatIOCtrl.text()}")
|
||||
return commands
|
45
pyctbgui/pyctbgui/services/SlowADCs.py
Normal file
45
pyctbgui/pyctbgui/services/SlowADCs.py
Normal file
@ -0,0 +1,45 @@
|
||||
from functools import partial
|
||||
from pathlib import Path
|
||||
|
||||
from PyQt5 import uic, QtWidgets
|
||||
|
||||
from pyctbgui.utils.defines import Defines
|
||||
from slsdet import dacIndex
|
||||
|
||||
|
||||
class SlowAdcTab(QtWidgets.QWidget):
|
||||
|
||||
def __init__(self, parent):
|
||||
super().__init__(parent)
|
||||
uic.loadUi(Path(__file__).parent.parent / 'ui' / "slowAdcs.ui", parent)
|
||||
self.view = parent
|
||||
self.mainWindow = None
|
||||
self.det = None
|
||||
|
||||
def setup_ui(self):
|
||||
pass
|
||||
|
||||
def connect_ui(self):
|
||||
for i in range(Defines.slowAdc.count):
|
||||
getattr(self.view, f"pushButtonSlowAdc{i}").clicked.connect(partial(self.updateSlowAdc, i))
|
||||
self.view.pushButtonTemp.clicked.connect(self.updateTemperature)
|
||||
|
||||
def refresh(self):
|
||||
self.updateSlowAdcNames()
|
||||
for i in range(Defines.slowAdc.count):
|
||||
self.updateSlowAdc(i)
|
||||
self.updateTemperature()
|
||||
|
||||
def updateSlowAdcNames(self):
|
||||
for i, name in enumerate(self.mainWindow.det.getSlowADCNames()):
|
||||
getattr(self.view, f"labelSlowAdc{i}").setText(name)
|
||||
|
||||
def updateSlowAdc(self, i):
|
||||
slowADCIndex = getattr(dacIndex, f"SLOW_ADC{i}")
|
||||
label = getattr(self.view, f"labelSlowAdcValue{i}")
|
||||
slowadc = (self.det.getSlowADC(slowADCIndex))[0] / 1000
|
||||
label.setText(f'{slowadc:.2f} mV')
|
||||
|
||||
def updateTemperature(self):
|
||||
slowadc = self.det.getTemperature(dacIndex.SLOW_ADC_TEMP)
|
||||
self.view.labelTempValue.setText(f'{str(slowadc[0])} °C')
|
273
pyctbgui/pyctbgui/services/Transceiver.py
Normal file
273
pyctbgui/pyctbgui/services/Transceiver.py
Normal file
@ -0,0 +1,273 @@
|
||||
from functools import partial
|
||||
from pathlib import Path
|
||||
|
||||
import numpy as np
|
||||
from PyQt5 import QtWidgets, uic
|
||||
import pyqtgraph as pg
|
||||
from pyqtgraph import LegendItem
|
||||
|
||||
from pyctbgui.utils import decoder
|
||||
from pyctbgui.utils.defines import Defines
|
||||
|
||||
from pyctbgui.utils.bit_utils import bit_is_set, manipulate_bit
|
||||
import pyctbgui.utils.pixelmap as pm
|
||||
from pyctbgui.utils.recordOrApplyPedestal import recordOrApplyPedestal
|
||||
|
||||
|
||||
class TransceiverTab(QtWidgets.QWidget):
|
||||
|
||||
def __init__(self, parent):
|
||||
super().__init__(parent)
|
||||
uic.loadUi(Path(__file__).parent.parent / 'ui' / "transceiver.ui", parent)
|
||||
self.view = parent
|
||||
self.mainWindow = None
|
||||
self.det = None
|
||||
self.plotTab = None
|
||||
self.legend: LegendItem | None = None
|
||||
self.acquisitionTab = None
|
||||
|
||||
def setup_ui(self):
|
||||
self.plotTab = self.mainWindow.plotTab
|
||||
self.acquisitionTab = self.mainWindow.acquisitionTab
|
||||
for i in range(Defines.transceiver.count):
|
||||
self.setTransceiverButtonColor(i, self.plotTab.getRandomColor())
|
||||
self.initializeAllTransceiverPlots()
|
||||
|
||||
self.legend = self.mainWindow.plotTransceiverWaveform.getPlotItem().legend
|
||||
self.legend.clear()
|
||||
|
||||
# subscribe to toggle legend
|
||||
self.plotTab.subscribeToggleLegend(self.updateLegend)
|
||||
|
||||
def connect_ui(self):
|
||||
for i in range(Defines.transceiver.count):
|
||||
getattr(self.view, f"checkBoxTransceiver{i}").stateChanged.connect(partial(self.setTransceiverEnable, i))
|
||||
getattr(self.view,
|
||||
f"checkBoxTransceiver{i}Plot").stateChanged.connect(partial(self.setTransceiverEnablePlot, i))
|
||||
getattr(self.view, f"pushButtonTransceiver{i}").clicked.connect(partial(self.selectTransceiverColor, i))
|
||||
self.view.lineEditTransceiverMask.editingFinished.connect(self.setTransceiverEnableReg)
|
||||
|
||||
def refresh(self):
|
||||
self.updateTransceiverEnable()
|
||||
|
||||
def getEnabledPlots(self):
|
||||
"""
|
||||
return plots that are shown (checkBoxTransceiver{i}Plot is checked)
|
||||
"""
|
||||
enabledPlots = []
|
||||
self.legend.clear()
|
||||
for i in range(Defines.transceiver.count):
|
||||
if getattr(self.view, f'checkBoxTransceiver{i}Plot').isChecked():
|
||||
plotName = getattr(self.view, f"labelTransceiver{i}").text()
|
||||
enabledPlots.append((self.mainWindow.transceiverPlots[i], plotName))
|
||||
return enabledPlots
|
||||
|
||||
def updateLegend(self):
|
||||
"""
|
||||
update the legend for the transceiver waveform plot
|
||||
should be called after checking or unchecking plot checkbox
|
||||
"""
|
||||
if not self.mainWindow.showLegend:
|
||||
self.legend.clear()
|
||||
else:
|
||||
for plot, name in self.getEnabledPlots():
|
||||
self.legend.addItem(plot, name)
|
||||
|
||||
@recordOrApplyPedestal
|
||||
def _processWaveformData(self, data, dSamples, romode, nDBitEnabled, nTransceiverEnabled):
|
||||
"""
|
||||
model function
|
||||
processes raw receiver waveform data
|
||||
@param data: raw receiver waveform data
|
||||
@param dSamples: digital samples
|
||||
@param romode: readout mode value
|
||||
@param nDBitEnabled: number of digital bits enabled
|
||||
@param nTransceiverEnabled: number of transceivers enabled
|
||||
@return: processed transceiver data
|
||||
"""
|
||||
transceiverOffset = 0
|
||||
if romode == 4:
|
||||
nbitsPerDBit = dSamples
|
||||
if dSamples % 8 != 0:
|
||||
nbitsPerDBit += (8 - (dSamples % 8))
|
||||
transceiverOffset += nDBitEnabled * (nbitsPerDBit // 8)
|
||||
trans_array = np.array(np.frombuffer(data, offset=transceiverOffset, dtype=np.uint16))
|
||||
return trans_array.reshape(-1, nTransceiverEnabled)
|
||||
|
||||
def processWaveformData(self, data, dSamples):
|
||||
"""
|
||||
plots raw waveform data
|
||||
data: raw waveform data
|
||||
dsamples: digital samples
|
||||
tsamples: transceiver samples
|
||||
"""
|
||||
waveforms = {}
|
||||
trans_array = self._processWaveformData(data, dSamples, self.mainWindow.romode.value,
|
||||
self.mainWindow.nDBitEnabled, self.nTransceiverEnabled)
|
||||
idx = 0
|
||||
for i in range(Defines.transceiver.count):
|
||||
checkBoxPlot = getattr(self.view, f"checkBoxTransceiver{i}Plot")
|
||||
checkBoxEn = getattr(self.view, f"checkBoxTransceiver{i}")
|
||||
if checkBoxEn.isChecked() and checkBoxPlot.isChecked():
|
||||
waveform = trans_array[:, idx]
|
||||
idx += 1
|
||||
self.mainWindow.transceiverPlots[i].setData(waveform)
|
||||
plotName = getattr(self.view, f"labelTransceiver{i}").text()
|
||||
waveforms[plotName] = waveform
|
||||
return waveforms
|
||||
|
||||
@recordOrApplyPedestal
|
||||
def _processImageData(self, data, dSamples, romode, nDBitEnabled):
|
||||
"""
|
||||
processes raw image data
|
||||
@param data:
|
||||
@param dSamples:
|
||||
@param romode:
|
||||
@param nDBitEnabled:
|
||||
@return:
|
||||
"""
|
||||
transceiverOffset = 0
|
||||
if romode == 4:
|
||||
nbitsPerDBit = dSamples
|
||||
if dSamples % 8 != 0:
|
||||
nbitsPerDBit += (8 - (dSamples % 8))
|
||||
transceiverOffset += nDBitEnabled * (nbitsPerDBit // 8)
|
||||
trans_array = np.array(np.frombuffer(data, offset=transceiverOffset, dtype=np.uint16))
|
||||
return decoder.decode(trans_array, pm.matterhorn_transceiver())
|
||||
|
||||
def processImageData(self, data, dSamples):
|
||||
"""
|
||||
view function
|
||||
plots transceiver image
|
||||
dSamples: digital samples
|
||||
data: raw image data
|
||||
"""
|
||||
# get zoom state
|
||||
viewBox = self.mainWindow.plotTransceiverImage.getView()
|
||||
state = viewBox.getState()
|
||||
try:
|
||||
self.mainWindow.transceiver_frame = self._processImageData(data, dSamples, self.mainWindow.romode.value,
|
||||
self.mainWindow.nDBitEnabled)
|
||||
self.plotTab.ignoreHistogramSignal = True
|
||||
self.mainWindow.plotTransceiverImage.setImage(self.mainWindow.transceiver_frame)
|
||||
except Exception:
|
||||
self.mainWindow.statusbar.setStyleSheet("color:red")
|
||||
message = f'Warning: Invalid size for Transceiver Image. Expected' \
|
||||
f' {self.mainWindow.nTransceiverRows * self.mainWindow.nTransceiverCols} size,' \
|
||||
f' got {self.mainWindow.transceiver_frame.size} instead.'
|
||||
self.acquisitionTab.updateCurrentFrame('Invalid Image')
|
||||
self.mainWindow.statusbar.showMessage(message)
|
||||
print(message)
|
||||
|
||||
self.plotTab.setFrameLimits(self.mainWindow.transceiver_frame)
|
||||
|
||||
# keep the zoomed in state (not 1st image)
|
||||
if self.mainWindow.firstTransceiverImage:
|
||||
self.mainWindow.firstTransceiverImage = False
|
||||
else:
|
||||
viewBox.setState(state)
|
||||
return self.mainWindow.transceiver_frame
|
||||
|
||||
def initializeAllTransceiverPlots(self):
|
||||
self.mainWindow.plotTransceiverWaveform = pg.plot()
|
||||
self.mainWindow.plotTransceiverWaveform.addLegend(colCount=Defines.colCount)
|
||||
self.mainWindow.verticalLayoutPlot.addWidget(self.mainWindow.plotTransceiverWaveform, 5)
|
||||
self.mainWindow.transceiverPlots = {}
|
||||
waveform = np.zeros(1000)
|
||||
for i in range(Defines.transceiver.count):
|
||||
pen = pg.mkPen(color=self.getTransceiverButtonColor(i), width=1)
|
||||
legendName = getattr(self.view, f"labelTransceiver{i}").text()
|
||||
self.mainWindow.transceiverPlots[i] = self.mainWindow.plotTransceiverWaveform.plot(waveform,
|
||||
pen=pen,
|
||||
name=legendName)
|
||||
self.mainWindow.transceiverPlots[i].hide()
|
||||
|
||||
self.mainWindow.plotTransceiverImage = pg.ImageView()
|
||||
self.mainWindow.nTransceiverRows = 0
|
||||
self.mainWindow.nTransceiverCols = 0
|
||||
self.mainWindow.transceiver_frame = np.zeros(
|
||||
(self.mainWindow.nTransceiverRows, self.mainWindow.nTransceiverCols))
|
||||
self.mainWindow.plotTransceiverImage.setImage(self.mainWindow.transceiver_frame)
|
||||
self.mainWindow.verticalLayoutPlot.addWidget(self.mainWindow.plotTransceiverImage, 6)
|
||||
|
||||
cm = pg.colormap.get('CET-L9') # prepare a linear color map
|
||||
self.mainWindow.plotTransceiverImage.setColorMap(cm)
|
||||
|
||||
def getTransceiverEnableReg(self):
|
||||
retval = self.det.transceiverenable
|
||||
self.view.lineEditTransceiverMask.editingFinished.disconnect()
|
||||
self.view.lineEditTransceiverMask.setText("0x{:08x}".format(retval))
|
||||
self.view.lineEditTransceiverMask.editingFinished.connect(self.setTransceiverEnableReg)
|
||||
return retval
|
||||
|
||||
def setTransceiverEnableReg(self):
|
||||
self.view.lineEditTransceiverMask.editingFinished.disconnect()
|
||||
try:
|
||||
mask = int(self.view.lineEditTransceiverMask.text(), 16)
|
||||
self.det.transceiverenable = mask
|
||||
except Exception as e:
|
||||
QtWidgets.QMessageBox.warning(self.mainWindow, "Transceiver Enable Fail", str(e), QtWidgets.QMessageBox.Ok)
|
||||
pass
|
||||
# TODO: handling double event exceptions
|
||||
self.view.lineEditTransceiverMask.editingFinished.connect(self.setTransceiverEnableReg)
|
||||
self.updateTransceiverEnable()
|
||||
|
||||
def getTransceiverEnable(self, i, mask):
|
||||
checkBox = getattr(self.view, f"checkBoxTransceiver{i}")
|
||||
checkBox.stateChanged.disconnect()
|
||||
checkBox.setChecked(bit_is_set(mask, i))
|
||||
checkBox.stateChanged.connect(partial(self.setTransceiverEnable, i))
|
||||
|
||||
def updateTransceiverEnable(self):
|
||||
retval = self.getTransceiverEnableReg()
|
||||
self.nTransceiverEnabled = bin(retval).count('1')
|
||||
for i in range(4):
|
||||
self.getTransceiverEnable(i, retval)
|
||||
self.getTransceiverEnablePlot(i)
|
||||
self.getTransceiverEnableColor(i)
|
||||
self.plotTab.addSelectedTransceiverPlots(i)
|
||||
|
||||
def setTransceiverEnable(self, i):
|
||||
checkBox = getattr(self.view, f"checkBoxTransceiver{i}")
|
||||
try:
|
||||
enableMask = manipulate_bit(checkBox.isChecked(), self.det.transceiverenable, i)
|
||||
self.det.transceiverenable = enableMask
|
||||
except Exception as e:
|
||||
QtWidgets.QMessageBox.warning(self.mainWindow, "Transceiver Enable Fail", str(e), QtWidgets.QMessageBox.Ok)
|
||||
pass
|
||||
|
||||
self.updateTransceiverEnable()
|
||||
|
||||
def getTransceiverEnablePlot(self, i):
|
||||
checkBox = getattr(self.view, f"checkBoxTransceiver{i}")
|
||||
checkBoxPlot = getattr(self.view, f"checkBoxTransceiver{i}Plot")
|
||||
checkBoxPlot.setEnabled(checkBox.isChecked())
|
||||
|
||||
def setTransceiverEnablePlot(self, i):
|
||||
pushButton = getattr(self.view, f"pushButtonTransceiver{i}")
|
||||
checkBox = getattr(self.view, f"checkBoxTransceiver{i}Plot")
|
||||
pushButton.setEnabled(checkBox.isChecked())
|
||||
self.plotTab.addSelectedTransceiverPlots(i)
|
||||
self.updateLegend()
|
||||
|
||||
def getTransceiverEnableColor(self, i):
|
||||
checkBox = getattr(self.view, f"checkBoxTransceiver{i}Plot")
|
||||
pushButton = getattr(self.view, f"pushButtonTransceiver{i}")
|
||||
pushButton.setEnabled(checkBox.isEnabled() and checkBox.isChecked())
|
||||
|
||||
def selectTransceiverColor(self, i):
|
||||
pushButton = getattr(self.view, f"pushButtonTransceiver{i}")
|
||||
self.plotTab.showPalette(pushButton)
|
||||
pen = pg.mkPen(color=self.getTransceiverButtonColor(i), width=1)
|
||||
self.mainWindow.transceiverPlots[i].setPen(pen)
|
||||
|
||||
def getTransceiverButtonColor(self, i):
|
||||
pushButton = getattr(self.view, f"pushButtonTransceiver{i}")
|
||||
return self.plotTab.getActiveColor(pushButton)
|
||||
|
||||
def setTransceiverButtonColor(self, i, color):
|
||||
pushButton = getattr(self.view, f"pushButtonTransceiver{i}")
|
||||
return self.plotTab.setActiveColor(pushButton, color)
|
||||
|
||||
def saveParameters(self):
|
||||
return ["transceiverenable {}".format(self.view.lineEditTransceiverMask.text())]
|
9
pyctbgui/pyctbgui/services/__init__.py
Normal file
9
pyctbgui/pyctbgui/services/__init__.py
Normal file
@ -0,0 +1,9 @@
|
||||
from .ADC import AdcTab
|
||||
from .Acquisition import AcquisitionTab
|
||||
from .DACs import DacTab
|
||||
from .Pattern import PatternTab
|
||||
from .Plot import PlotTab
|
||||
from .PowerSupplies import PowerSuppliesTab
|
||||
from .Signals import SignalsTab
|
||||
from .SlowADCs import SlowAdcTab
|
||||
from .Transceiver import TransceiverTab
|
779
pyctbgui/pyctbgui/ui/CtbGui.ui
Normal file
779
pyctbgui/pyctbgui/ui/CtbGui.ui
Normal file
@ -0,0 +1,779 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>MainWindow</class>
|
||||
<widget class="QMainWindow" name="MainWindow">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1444</width>
|
||||
<height>943</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Chip Test Board</string>
|
||||
</property>
|
||||
<property name="dockNestingEnabled">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralwidget">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>870</width>
|
||||
<height>890</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>870</width>
|
||||
<height>890</height>
|
||||
</size>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="spacing">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QScrollArea" name="scrollArea">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Plain</enum>
|
||||
</property>
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<widget class="QWidget" name="scrollAreaWidgetContents">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>870</width>
|
||||
<height>879</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QFrame" name="frameControl">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Plain</enum>
|
||||
</property>
|
||||
<property name="lineWidth">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_10">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>9</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QTabWidget" name="tabWidget">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>870</width>
|
||||
<height>870</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>870</width>
|
||||
<height>870</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="tabDac">
|
||||
<attribute name="title">
|
||||
<string>DACs</string>
|
||||
</attribute>
|
||||
<widget class="DacTab" name="widgetDacs" native="true">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>851</width>
|
||||
<height>841</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>711</width>
|
||||
<height>791</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tabPower">
|
||||
<attribute name="title">
|
||||
<string>Power Supplies</string>
|
||||
</attribute>
|
||||
<widget class="PowerSuppliesTab" name="widgetPowerSupplies" native="true">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>-1</x>
|
||||
<y>-1</y>
|
||||
<width>841</width>
|
||||
<height>821</height>
|
||||
</rect>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tabSlowAdc">
|
||||
<attribute name="title">
|
||||
<string>Slow ADCs</string>
|
||||
</attribute>
|
||||
<widget class="SlowAdcTab" name="widgetSlowAdcs" native="true">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>871</width>
|
||||
<height>821</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>871</width>
|
||||
<height>571</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tabSignal">
|
||||
<attribute name="title">
|
||||
<string>Signals</string>
|
||||
</attribute>
|
||||
<widget class="SignalsTab" name="widgetSignals" native="true">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>831</width>
|
||||
<height>821</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>831</width>
|
||||
<height>821</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tabTransceivers">
|
||||
<attribute name="title">
|
||||
<string>Transceivers</string>
|
||||
</attribute>
|
||||
<widget class="TransceiverTab" name="widgetTransceiver" native="true">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>9</x>
|
||||
<y>19</y>
|
||||
<width>841</width>
|
||||
<height>341</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>841</width>
|
||||
<height>181</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tabAdc">
|
||||
<attribute name="title">
|
||||
<string>ADCs</string>
|
||||
</attribute>
|
||||
<widget class="AdcTab" name="widgetAdc" native="true">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>-1</x>
|
||||
<y>-1</y>
|
||||
<width>841</width>
|
||||
<height>821</height>
|
||||
</rect>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tabPattern">
|
||||
<attribute name="title">
|
||||
<string>Pattern</string>
|
||||
</attribute>
|
||||
<widget class="PatternTab" name="widgetPattern" native="true">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>851</width>
|
||||
<height>831</height>
|
||||
</rect>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tabAcquisition">
|
||||
<attribute name="title">
|
||||
<string>Acquisition</string>
|
||||
</attribute>
|
||||
<widget class="AcquisitionTab" name="widgetAcquisition" native="true">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>-10</x>
|
||||
<y>0</y>
|
||||
<width>860</width>
|
||||
<height>800</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>860</width>
|
||||
<height>800</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tabPlot">
|
||||
<attribute name="title">
|
||||
<string>Plot</string>
|
||||
</attribute>
|
||||
<widget class="PlotTab" name="widgetPlot" native="true">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>860</width>
|
||||
<height>800</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>860</width>
|
||||
<height>800</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QMenuBar" name="menubar">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>1444</width>
|
||||
<height>25</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QMenu" name="menuFile">
|
||||
<property name="title">
|
||||
<string>File</string>
|
||||
</property>
|
||||
<addaction name="actionLoadParameters"/>
|
||||
<addaction name="actionSaveParameters"/>
|
||||
<addaction name="actionExit"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuHelp">
|
||||
<property name="title">
|
||||
<string>Help</string>
|
||||
</property>
|
||||
<addaction name="actionInfo"/>
|
||||
<addaction name="actionKeyboardShortcuts"/>
|
||||
</widget>
|
||||
<addaction name="menuFile"/>
|
||||
<addaction name="menuHelp"/>
|
||||
</widget>
|
||||
<widget class="QStatusBar" name="statusbar"/>
|
||||
<widget class="QDockWidget" name="dockWidget">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>568</width>
|
||||
<height>214</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>524287</width>
|
||||
<height>524287</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="features">
|
||||
<set>QDockWidget::DockWidgetFloatable|QDockWidget::DockWidgetMovable</set>
|
||||
</property>
|
||||
<property name="allowedAreas">
|
||||
<set>Qt::RightDockWidgetArea</set>
|
||||
</property>
|
||||
<attribute name="dockWidgetArea">
|
||||
<number>2</number>
|
||||
</attribute>
|
||||
<widget class="QWidget" name="dockWidgetContent">
|
||||
<layout class="QGridLayout" name="gridLayout_7">
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QFrame" name="frameAcquisition">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>100</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_25">
|
||||
<item row="1" column="2">
|
||||
<widget class="QLabel" name="labelCurrentMeasurement">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>70</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>70</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>0</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" colspan="5">
|
||||
<widget class="QProgressBar" name="progressBar">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>24</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QPushButton" name="pushButtonStart">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>36</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="palette">
|
||||
<palette>
|
||||
<active>
|
||||
<colorrole role="Button">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>85</red>
|
||||
<green>170</green>
|
||||
<blue>127</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="Base">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>85</red>
|
||||
<green>170</green>
|
||||
<blue>127</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="Window">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>85</red>
|
||||
<green>170</green>
|
||||
<blue>127</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
</active>
|
||||
<inactive>
|
||||
<colorrole role="Button">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>85</red>
|
||||
<green>170</green>
|
||||
<blue>127</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="Base">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>85</red>
|
||||
<green>170</green>
|
||||
<blue>127</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="Window">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>85</red>
|
||||
<green>170</green>
|
||||
<blue>127</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
</inactive>
|
||||
<disabled>
|
||||
<colorrole role="Button">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>85</red>
|
||||
<green>170</green>
|
||||
<blue>127</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="Base">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>85</red>
|
||||
<green>170</green>
|
||||
<blue>127</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
<colorrole role="Window">
|
||||
<brush brushstyle="SolidPattern">
|
||||
<color alpha="255">
|
||||
<red>85</red>
|
||||
<green>170</green>
|
||||
<blue>127</blue>
|
||||
</color>
|
||||
</brush>
|
||||
</colorrole>
|
||||
</disabled>
|
||||
</palette>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Shift + Enter is the keyboard shortcut to start/stop acquisition from any tab</string>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QPushButton {background-color: rgb(85, 170, 127);}
|
||||
QPushButton:checked{background-color: red;}</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Start</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="labelDetectorStatus">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>110</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>IDLE</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="4">
|
||||
<widget class="QLabel" name="label_137">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>70</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Acquired:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="5">
|
||||
<widget class="QLabel" name="labelAcquiredFrames">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>70</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>70</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>0</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLabel" name="label_134">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Measurement:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="3">
|
||||
<spacer name="horizontalSpacer_24">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QFrame" name="framePatternViewer">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayoutPatternViewer"/>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QFrame" name="framePlot">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayoutPlot">
|
||||
<item>
|
||||
<widget class="QLabel" name="labelFrameNumber">
|
||||
<property name="text">
|
||||
<string>#</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<action name="actionLoadParameters">
|
||||
<property name="text">
|
||||
<string>Load Parameters</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionSave">
|
||||
<property name="text">
|
||||
<string>Save</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionExit">
|
||||
<property name="text">
|
||||
<string>Exit</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionInfo">
|
||||
<property name="text">
|
||||
<string>Info</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionKeyboardShortcuts">
|
||||
<property name="text">
|
||||
<string>Keyboard Shortcuts</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionSaveParameters">
|
||||
<property name="text">
|
||||
<string>Save Parameters</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<customwidgets>
|
||||
<customwidget>
|
||||
<class>PowerSuppliesTab</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>pyctbgui.services.PowerSupplies</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>DacTab</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>pyctbgui.services.DACs</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>SlowAdcTab</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>pyctbgui.services.SlowADCs</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>SignalsTab</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>pyctbgui.services.Signals</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>TransceiverTab</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>pyctbgui.services.Transceiver</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>AdcTab</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>pyctbgui.services.ADC</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>PatternTab</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>pyctbgui.services.Pattern</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>AcquisitionTab</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>pyctbgui.services.Acquisition</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>PlotTab</class>
|
||||
<extends>QWidget</extends>
|
||||
<header>pyctbgui.services.Plot</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>actionExit</sender>
|
||||
<signal>triggered()</signal>
|
||||
<receiver>MainWindow</receiver>
|
||||
<slot>close()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>-1</x>
|
||||
<y>-1</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>753</x>
|
||||
<y>496</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
1198
pyctbgui/pyctbgui/ui/Dacs.ui
Normal file
1198
pyctbgui/pyctbgui/ui/Dacs.ui
Normal file
File diff suppressed because it is too large
Load Diff
369
pyctbgui/pyctbgui/ui/MainWindow.py
Normal file
369
pyctbgui/pyctbgui/ui/MainWindow.py
Normal file
@ -0,0 +1,369 @@
|
||||
import logging
|
||||
|
||||
from PyQt5 import QtWidgets, QtCore, uic
|
||||
import argparse
|
||||
import signal
|
||||
import pyqtgraph as pg
|
||||
from pathlib import Path
|
||||
from functools import partial
|
||||
|
||||
from slsdet import Detector, dacIndex
|
||||
|
||||
from pyctbgui.services import TransceiverTab, DacTab, AdcTab, AcquisitionTab, SignalsTab, PatternTab, \
|
||||
SlowAdcTab, PlotTab, PowerSuppliesTab
|
||||
from pyctbgui.utils import alias_utility
|
||||
from pyctbgui.utils.defines import Defines
|
||||
|
||||
|
||||
class MainWindow(QtWidgets.QMainWindow):
|
||||
signalShortcutAcquire = QtCore.pyqtSignal()
|
||||
signalShortcutTabUp = QtCore.pyqtSignal()
|
||||
signalShortcutTabDown = QtCore.pyqtSignal()
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('-a', '--alias', help="Alias file complete path")
|
||||
arglist, __ = parser.parse_known_args()
|
||||
self.alias_file = arglist.alias
|
||||
|
||||
pg.setConfigOption("background", (247, 247, 247))
|
||||
pg.setConfigOption("foreground", "k")
|
||||
pg.setConfigOption('leftButtonPan', False)
|
||||
|
||||
super().__init__(*args, **kwargs)
|
||||
|
||||
uic.loadUi(Path(__file__).parent / "CtbGui.ui", self)
|
||||
logging.basicConfig(encoding='utf-8', level=logging.INFO)
|
||||
|
||||
self.logger = logging.getLogger(__name__)
|
||||
self.det = None
|
||||
self.showLegend = True
|
||||
self.settings = None
|
||||
try:
|
||||
self.det = Detector()
|
||||
# ensure detector is up
|
||||
self.det.detectorserverversion[0]
|
||||
except Exception as e:
|
||||
QtWidgets.QMessageBox.critical(self, "Connect Fail", str(e) + "Exiting Gui...", QtWidgets.QMessageBox.Ok)
|
||||
raise
|
||||
|
||||
# get Tab Classes
|
||||
self.plotTab: PlotTab = self.widgetPlot
|
||||
self.slowAdcTab: SlowAdcTab = self.widgetSlowAdcs
|
||||
self.dacTab: DacTab = self.widgetDacs
|
||||
self.powerSuppliesTab: PowerSuppliesTab = self.widgetPowerSupplies
|
||||
self.signalsTab: SignalsTab = self.widgetSignals
|
||||
self.transceiverTab: TransceiverTab = self.widgetTransceiver
|
||||
self.adcTab: AdcTab = self.widgetAdc
|
||||
self.patternTab: PatternTab = self.widgetPattern
|
||||
self.acquisitionTab: AcquisitionTab = self.widgetAcquisition
|
||||
|
||||
self.tabs_list = [
|
||||
self.dacTab, self.powerSuppliesTab, self.slowAdcTab, self.signalsTab, self.transceiverTab, self.adcTab,
|
||||
self.patternTab, self.acquisitionTab, self.plotTab
|
||||
]
|
||||
|
||||
self.setup_ui()
|
||||
self.acquisitionTab.setup_zmq()
|
||||
self.tabWidget.setCurrentIndex(Defines.Acquisition_Tab_Index)
|
||||
self.tabWidget.currentChanged.connect(self.refresh_tab)
|
||||
self.connect_ui()
|
||||
|
||||
for tab in self.tabs_list:
|
||||
tab.refresh()
|
||||
|
||||
# also refreshes timer to start plotting
|
||||
self.plotTab.plotOptions()
|
||||
self.plotTab.showPlot()
|
||||
|
||||
self.patternTab.getPatViewerColors()
|
||||
self.patternTab.getPatViewerWaitParameters()
|
||||
self.patternTab.getPatViewerLoopParameters()
|
||||
self.patternTab.updatePatViewerParameters()
|
||||
self.plotTab.showPatternViewer(False)
|
||||
|
||||
if self.alias_file is not None:
|
||||
self.loadAliasFile()
|
||||
|
||||
self.signalShortcutAcquire.connect(self.pushButtonStart.click)
|
||||
self.signalShortcutTabUp.connect(partial(self.changeTabIndex, True))
|
||||
self.signalShortcutTabDown.connect(partial(self.changeTabIndex, False))
|
||||
# to catch the ctrl + c to abort
|
||||
signal.signal(signal.SIGINT, signal.SIG_DFL)
|
||||
self.firstAnalogImage = True
|
||||
self.firstDigitalImage = True
|
||||
self.firstTransceiverImage = True
|
||||
|
||||
self.updateSettingValues()
|
||||
|
||||
def updateSettingMainWindow(self):
|
||||
self.settings.beginGroup("mainwindow")
|
||||
# window size
|
||||
width = self.settings.value('window_width')
|
||||
height = self.settings.value('window_height')
|
||||
if width is not None and height is not None:
|
||||
self.resize(int(width), int(height))
|
||||
# print(f'Main window resized to {width}x{height}')
|
||||
|
||||
# window position
|
||||
pos = self.settings.value('window_pos')
|
||||
if type(pos) is QtCore.QPoint:
|
||||
# print(f'Moved main window to {pos}')
|
||||
self.move(pos)
|
||||
self.settings.endGroup()
|
||||
|
||||
def saveSettingMainWindow(self):
|
||||
self.settings.beginGroup("mainwindow")
|
||||
self.settings.setValue('window_width', self.rect().width())
|
||||
self.settings.setValue('window_height', self.rect().height())
|
||||
self.settings.setValue('window_pos', self.pos())
|
||||
self.settings.endGroup()
|
||||
|
||||
def updateSettingDockWidget(self):
|
||||
self.settings.beginGroup("dockwidget")
|
||||
|
||||
# is docked
|
||||
if self.settings.contains('window_width') and self.settings.contains('window_height'):
|
||||
# window size
|
||||
width = self.settings.value('window_width')
|
||||
height = self.settings.value('window_height')
|
||||
if width is not None and height is not None:
|
||||
# print(f'Plot window - Floating ({width}x{height})')
|
||||
self.dockWidget.setFloating(True)
|
||||
self.dockWidget.resize(int(width), int(height))
|
||||
# window position
|
||||
pos = self.settings.value('window_pos')
|
||||
if type(pos) is QtCore.QPoint:
|
||||
# print(f'Moved plot window to {pos}')
|
||||
self.dockWidget.move(pos)
|
||||
self.settings.endGroup()
|
||||
|
||||
def saveSettingDockWidget(self):
|
||||
self.settings.beginGroup("dockwidget")
|
||||
if self.dockWidget.isFloating():
|
||||
self.settings.setValue('window_width', self.dockWidget.rect().width())
|
||||
self.settings.setValue('window_height', self.dockWidget.rect().height())
|
||||
self.settings.setValue('window_pos', self.dockWidget.pos())
|
||||
else:
|
||||
self.settings.remove('window_width')
|
||||
self.settings.remove('window_height')
|
||||
self.settings.remove('window_pos')
|
||||
self.settings.endGroup()
|
||||
|
||||
def savePlotTypeAndDetector(self):
|
||||
self.settings.setValue('isImage', self.plotTab.view.radioButtonImage.isChecked())
|
||||
self.settings.setValue('detector', self.plotTab.view.comboBoxPlot.currentText())
|
||||
|
||||
def updatePlotTypeAndDetector(self):
|
||||
# load plot type from qsettings
|
||||
isImage = self.settings.value('isImage', True, type=bool)
|
||||
self.plotTab.view.radioButtonImage.setChecked(isImage)
|
||||
self.plotTab.plotOptions()
|
||||
# load detector from qsettings
|
||||
if isImage:
|
||||
self.plotTab.view.comboBoxPlot.setCurrentText(self.settings.value('detector', 'Matterhorn'))
|
||||
|
||||
def updateSettingValues(self):
|
||||
self.settings = QtCore.QSettings('slsdetectorgroup', 'pyctbgui')
|
||||
self.updateSettingMainWindow()
|
||||
self.updateSettingDockWidget()
|
||||
self.updatePlotTypeAndDetector()
|
||||
|
||||
def saveSettings(self):
|
||||
# store in ~/.config/slsdetectorgroup/pyctbgui.conf
|
||||
self.saveSettingMainWindow()
|
||||
self.saveSettingDockWidget()
|
||||
self.savePlotTypeAndDetector()
|
||||
|
||||
def closeEvent(self, event):
|
||||
self.saveSettings()
|
||||
|
||||
def loadAliasFile(self):
|
||||
print(f'Loading Alias file: {self.alias_file}')
|
||||
try:
|
||||
bit_names, bit_plots, bit_colors, adc_names, adc_plots, adc_colors, dac_names, slowadc_names, \
|
||||
voltage_names, pat_file_name = alias_utility.read_alias_file(self.alias_file)
|
||||
except Exception as e:
|
||||
QtWidgets.QMessageBox.warning(self, "Alias File Fail",
|
||||
str(e) + "<br> " + self.alias_file, QtWidgets.QMessageBox.Ok)
|
||||
return
|
||||
|
||||
for i in range(Defines.signals.count):
|
||||
if bit_names[i]:
|
||||
self.det.setSignalName(i, bit_names[i])
|
||||
if bit_plots[i]:
|
||||
getattr(self.signalsTab.view, f"checkBoxBIT{i}DB").setChecked(bit_plots[i])
|
||||
getattr(self.signalsTab.view, f"checkBoxBIT{i}Plot").setChecked(bit_plots[i])
|
||||
if bit_colors[i]:
|
||||
self.signalsTab.setDBitButtonColor(i, bit_colors[i])
|
||||
|
||||
for i in range(Defines.adc.count):
|
||||
if adc_names[i]:
|
||||
self.det.setAdcName(i, adc_names[i])
|
||||
if adc_plots[i]:
|
||||
getattr(self.adcTab.view, f"checkBoxADC{i}En").setChecked(adc_plots[i])
|
||||
getattr(self.adcTab.view, f"checkBoxADC{i}Plot").setChecked(adc_plots[i])
|
||||
if adc_colors[i]:
|
||||
self.adcTab.setADCButtonColor(i, adc_colors[i])
|
||||
|
||||
for i in range(Defines.dac.count):
|
||||
if dac_names[i]:
|
||||
iDac = getattr(dacIndex, f"DAC_{i}")
|
||||
self.det.setDacName(iDac, dac_names[i])
|
||||
|
||||
for i in range(Defines.slowAdc.count):
|
||||
slowadc_index = self.det.getSlowADCList()
|
||||
if slowadc_names[i]:
|
||||
self.det.setSlowADCName(slowadc_index[i], slowadc_names[i])
|
||||
|
||||
for i in range(len(Defines.powerSupplies)):
|
||||
voltage_index = self.det.getVoltageList()
|
||||
if voltage_names[i]:
|
||||
self.det.setVoltageName(voltage_index[i], voltage_names[i])
|
||||
|
||||
if pat_file_name:
|
||||
self.lineEditPatternFile.setText(pat_file_name)
|
||||
|
||||
self.signalsTab.updateSignalNames()
|
||||
self.adcTab.updateADCNames()
|
||||
self.slowAdcTab.updateSlowAdcNames()
|
||||
self.dacTab.updateDACNames()
|
||||
self.powerSuppliesTab.updateVoltageNames()
|
||||
|
||||
# For Action options function
|
||||
# TODO Only add the components of action option+ functions
|
||||
# Function to show info
|
||||
def showInfo(self):
|
||||
msg = QtWidgets.QMessageBox()
|
||||
msg.setWindowTitle("About")
|
||||
msg.setText("This Gui is for Chip Test Boards.\n Current Phase: Development")
|
||||
msg.exec_()
|
||||
|
||||
def showKeyBoardShortcuts(self):
|
||||
msg = QtWidgets.QMessageBox()
|
||||
msg.setWindowTitle("Keyboard Shortcuts")
|
||||
msg.setText(
|
||||
"Start Acquisition (from any tab): Shift + Return<br>Move Tab Right : Ctrl + '+'<br>Move Tab Left :"
|
||||
" Ctrl + '-'<br>")
|
||||
msg.exec_()
|
||||
|
||||
def loadParameters(self):
|
||||
response = QtWidgets.QFileDialog.getOpenFileName(
|
||||
parent=self,
|
||||
caption="Select a parameter file to open",
|
||||
directory=str(Path.cwd()),
|
||||
# filter='README (*.md *.ui)'
|
||||
)
|
||||
if response[0] == '':
|
||||
return
|
||||
try:
|
||||
self.det.parameters = (response[0])
|
||||
for tab in self.tabs_list:
|
||||
tab.refresh()
|
||||
QtWidgets.QMessageBox.information(self, "Load Parameter Success", "Parameters loaded successfully",
|
||||
QtWidgets.QMessageBox.Ok)
|
||||
except (RuntimeError, FileNotFoundError) as e:
|
||||
self.logger.exception(e)
|
||||
QtWidgets.QMessageBox.warning(self, "Load Parameter Fail", str(e), QtWidgets.QMessageBox.Ok)
|
||||
|
||||
def refresh_tab(self, tab_index):
|
||||
match tab_index:
|
||||
case 0:
|
||||
self.dacTab.refresh()
|
||||
case 1:
|
||||
self.powerSuppliesTab.refresh()
|
||||
case 2:
|
||||
self.slowAdcTab.refresh()
|
||||
case 3:
|
||||
self.transceiverTab.refresh()
|
||||
case 4:
|
||||
self.signalsTab.refresh()
|
||||
case 5:
|
||||
self.adcTab.refresh()
|
||||
case 6:
|
||||
self.patternTab.refresh()
|
||||
case 7:
|
||||
self.acquisitionTab.refresh()
|
||||
case 8:
|
||||
self.plotTab.refresh()
|
||||
|
||||
def setup_ui(self):
|
||||
# To check detector status
|
||||
self.statusTimer = QtCore.QTimer()
|
||||
self.statusTimer.timeout.connect(self.acquisitionTab.checkEndofAcquisition)
|
||||
|
||||
# To auto trigger the read
|
||||
self.read_timer = QtCore.QTimer()
|
||||
self.read_timer.timeout.connect(self.acquisitionTab.read_zmq)
|
||||
|
||||
for tab in self.tabs_list:
|
||||
tab.mainWindow = self
|
||||
tab.det = self.det
|
||||
|
||||
for tab in self.tabs_list:
|
||||
tab.setup_ui()
|
||||
|
||||
def keyPressEvent(self, event):
|
||||
if event.modifiers() & QtCore.Qt.ShiftModifier:
|
||||
if event.key() == QtCore.Qt.Key_Return:
|
||||
self.signalShortcutAcquire.emit()
|
||||
if event.modifiers() & QtCore.Qt.ControlModifier:
|
||||
if event.key() == QtCore.Qt.Key_Plus:
|
||||
self.signalShortcutTabUp.emit()
|
||||
if event.key() == QtCore.Qt.Key_Minus:
|
||||
self.signalShortcutTabDown.emit()
|
||||
|
||||
def changeTabIndex(self, up):
|
||||
ind = self.tabWidget.currentIndex()
|
||||
if up:
|
||||
ind += 1
|
||||
if ind == Defines.Max_Tabs:
|
||||
ind = 0
|
||||
else:
|
||||
ind -= 1
|
||||
if ind == -1:
|
||||
ind = Defines.Max_Tabs - 1
|
||||
self.tabWidget.setCurrentIndex(ind)
|
||||
|
||||
def connect_ui(self):
|
||||
# Show info
|
||||
self.actionInfo.triggered.connect(self.showInfo)
|
||||
self.actionKeyboardShortcuts.triggered.connect(self.showKeyBoardShortcuts)
|
||||
self.actionLoadParameters.triggered.connect(self.loadParameters)
|
||||
self.pushButtonStart.clicked.connect(self.acquisitionTab.toggleAcquire)
|
||||
self.actionSaveParameters.triggered.connect(self.saveParameters)
|
||||
|
||||
for tab in self.tabs_list:
|
||||
tab.connect_ui()
|
||||
|
||||
def saveParameters(self):
|
||||
response = QtWidgets.QFileDialog.getSaveFileName(self, "Save Parameters", str(self.det.fpath))
|
||||
if response[0] == '':
|
||||
return
|
||||
|
||||
# save DACs
|
||||
commands = self.dacTab.saveParameters()
|
||||
# save signals
|
||||
commands.extend(self.signalsTab.saveParameters())
|
||||
# save transceiver
|
||||
commands.extend(self.transceiverTab.saveParameters())
|
||||
# save ADCs
|
||||
commands.extend(self.adcTab.saveParameters())
|
||||
# save pattern
|
||||
commands.extend(self.patternTab.saveParameters())
|
||||
# save acquisition
|
||||
commands.extend(self.acquisitionTab.saveParameters())
|
||||
# save power supplies
|
||||
commands.extend(self.powerSuppliesTab.saveParameters())
|
||||
# save plot
|
||||
commands.extend(self.plotTab.saveParameters())
|
||||
|
||||
try:
|
||||
with open(response[0], 'w') as fp:
|
||||
fp.write('\n'.join(commands))
|
||||
except Exception as e:
|
||||
self.logger.exception(e)
|
||||
QtWidgets.QMessageBox.warning(self, "Save Parameter Fail", str(e), QtWidgets.QMessageBox.Ok)
|
||||
|
||||
QtWidgets.QMessageBox.information(self, "Save Parameter Success", "Parameters saved successfully",
|
||||
QtWidgets.QMessageBox.Ok)
|
1
pyctbgui/pyctbgui/ui/__init__.py
Normal file
1
pyctbgui/pyctbgui/ui/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
from .MainWindow import MainWindow
|
927
pyctbgui/pyctbgui/ui/acquisition.ui
Normal file
927
pyctbgui/pyctbgui/ui/acquisition.ui
Normal file
@ -0,0 +1,927 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Form</class>
|
||||
<widget class="QWidget" name="Form">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>870</width>
|
||||
<height>823</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>870</width>
|
||||
<height>800</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<widget class="QFrame" name="frame_20">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>10</y>
|
||||
<width>841</width>
|
||||
<height>71</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Sunken</enum>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_19">
|
||||
<item row="1" column="5">
|
||||
<widget class="QSpinBox" name="spinBoxRunF">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>125</width>
|
||||
<height>31</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>125</width>
|
||||
<height>31</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="buttonSymbols">
|
||||
<enum>QAbstractSpinBox::UpDownArrows</enum>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>1000</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_398">
|
||||
<property name="text">
|
||||
<string>Read Out Mode: </string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QComboBox" name="comboBoxROMode">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>32</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>32</height>
|
||||
</size>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Analog</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Digital</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Analog and Digital</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Transceiver</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>Digital and Transceiver</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="4">
|
||||
<widget class="QLabel" name="label_70">
|
||||
<property name="text">
|
||||
<string>Run Clock Frequency (MHz):</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QFrame" name="frame_13">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>90</y>
|
||||
<width>841</width>
|
||||
<height>51</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_24">
|
||||
<item row="0" column="1">
|
||||
<widget class="QSpinBox" name="spinBoxTransceiver">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>125</width>
|
||||
<height>32</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>125</width>
|
||||
<height>32</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100000</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<spacer name="horizontalSpacer_16">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="labelTransceiver">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>200</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Transceiver Samples:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QFrame" name="frame_15">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>150</y>
|
||||
<width>841</width>
|
||||
<height>201</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Sunken</enum>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_6">
|
||||
<item row="2" column="3">
|
||||
<widget class="QLabel" name="label_74">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>200</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>DBIT Clock Frequency (MHz):</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_71">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>200</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>ADC Clock Frequency (MHz):</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="4">
|
||||
<widget class="QSpinBox" name="spinBoxDBITPhase">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>125</width>
|
||||
<height>31</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>125</width>
|
||||
<height>31</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>9999</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="3">
|
||||
<widget class="QLabel" name="label_76">
|
||||
<property name="text">
|
||||
<string>DBIT Pipeline:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QSpinBox" name="spinBoxADCF">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>125</width>
|
||||
<height>31</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>125</width>
|
||||
<height>31</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>1000</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QSpinBox" name="spinBoxADCPipeline">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>125</width>
|
||||
<height>31</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>125</width>
|
||||
<height>31</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_73">
|
||||
<property name="text">
|
||||
<string>ADC Pipeline:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="label_72">
|
||||
<property name="text">
|
||||
<string>ADC Clock Phase (a.u.):</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="3">
|
||||
<widget class="QLabel" name="label_75">
|
||||
<property name="text">
|
||||
<string>DBIT Clock Phase (a.u.):</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Expanding</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>10</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="2" column="4">
|
||||
<widget class="QSpinBox" name="spinBoxDBITF">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>125</width>
|
||||
<height>31</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>125</width>
|
||||
<height>31</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>1000</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="4">
|
||||
<widget class="QSpinBox" name="spinBoxDBITPipeline">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>125</width>
|
||||
<height>31</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>125</width>
|
||||
<height>31</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QSpinBox" name="spinBoxADCPhase">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>125</width>
|
||||
<height>31</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>125</width>
|
||||
<height>31</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>9999</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="labelAnalog">
|
||||
<property name="text">
|
||||
<string>Analog Samples:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QSpinBox" name="spinBoxAnalog">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>125</width>
|
||||
<height>32</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>125</width>
|
||||
<height>32</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100000</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<widget class="QLabel" name="labelDigital">
|
||||
<property name="text">
|
||||
<string>Digital Samples:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="4">
|
||||
<widget class="QSpinBox" name="spinBoxDigital">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>125</width>
|
||||
<height>32</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>125</width>
|
||||
<height>32</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>100000</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QFrame" name="frame_11">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>370</y>
|
||||
<width>841</width>
|
||||
<height>181</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Sunken</enum>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_15">
|
||||
<item row="0" column="0" colspan="2">
|
||||
<widget class="QLabel" name="label_127">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>11</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Sunken</enum>
|
||||
</property>
|
||||
<property name="lineWidth">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Output Settings</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_129">
|
||||
<property name="text">
|
||||
<string>File name:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QLineEdit" name="lineEditFileName">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>31</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>31</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">background-color: rgb(200, 219, 230);</string>
|
||||
</property>
|
||||
<property name="placeholderText">
|
||||
<string>File Name</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="label_131">
|
||||
<property name="text">
|
||||
<string>Index:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QSpinBox" name="spinBoxAcquisitionIndex">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>31</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>200</width>
|
||||
<height>31</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>999999999</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="4">
|
||||
<widget class="QCheckBox" name="checkBoxFileWriteRaw">
|
||||
<property name="text">
|
||||
<string>Raw</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="4">
|
||||
<widget class="QPushButton" name="pushButtonFilePath">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>36</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">background-color: rgb(199, 213, 207);</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Browse</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="lineEditFilePath">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>31</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>31</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">background-color: rgb(200, 219, 230);</string>
|
||||
</property>
|
||||
<property name="placeholderText">
|
||||
<string>File Path</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_130">
|
||||
<property name="text">
|
||||
<string>File path:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<widget class="QCheckBox" name="checkBoxFileWriteNumpy">
|
||||
<property name="text">
|
||||
<string>Numpy</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Save format:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QFrame" name="frame_53">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>570</y>
|
||||
<width>841</width>
|
||||
<height>141</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Sunken</enum>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_3">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Number of frames:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QSpinBox" name="spinBoxFrames">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>120</width>
|
||||
<height>32</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>32</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>999999999</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>999999999</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<spacer name="horizontalSpacer_4">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<widget class="QLabel" name="label_392">
|
||||
<property name="text">
|
||||
<string>Period (s):</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="4">
|
||||
<widget class="QDoubleSpinBox" name="spinBoxPeriod">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>120</width>
|
||||
<height>32</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>32</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="decimals">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<double>99999.990000000005239</double>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="5">
|
||||
<widget class="QComboBox" name="comboBoxPeriod">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>31</height>
|
||||
</size>
|
||||
</property>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>s</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>ms</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>μs</string>
|
||||
</property>
|
||||
</item>
|
||||
<item>
|
||||
<property name="text">
|
||||
<string>ns</string>
|
||||
</property>
|
||||
</item>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_393">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Number of triggers:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QSpinBox" name="spinBoxTriggers">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>120</width>
|
||||
<height>32</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>32</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>999999999</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="label_132">
|
||||
<property name="text">
|
||||
<string>Number of measurements:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QSpinBox" name="spinBoxMeasurements">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>120</width>
|
||||
<height>32</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>32</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>999999999</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
4212
pyctbgui/pyctbgui/ui/adc.ui
Normal file
4212
pyctbgui/pyctbgui/ui/adc.ui
Normal file
File diff suppressed because it is too large
Load Diff
2733
pyctbgui/pyctbgui/ui/pattern.ui
Normal file
2733
pyctbgui/pyctbgui/ui/pattern.ui
Normal file
File diff suppressed because it is too large
Load Diff
1055
pyctbgui/pyctbgui/ui/plot.ui
Normal file
1055
pyctbgui/pyctbgui/ui/plot.ui
Normal file
File diff suppressed because it is too large
Load Diff
483
pyctbgui/pyctbgui/ui/powerSupplies.ui
Normal file
483
pyctbgui/pyctbgui/ui/powerSupplies.ui
Normal file
@ -0,0 +1,483 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Form</class>
|
||||
<widget class="QWidget" name="Form">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>827</width>
|
||||
<height>375</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<widget class="QFrame" name="frame_3">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>841</width>
|
||||
<height>381</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Sunken</enum>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_12">
|
||||
<item row="2" column="1">
|
||||
<widget class="QSpinBox" name="spinBoxVC">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>32</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>32</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Only accepts value range (636 - 2468)</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string> mV</string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>2468</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="4">
|
||||
<widget class="QLabel" name="labelID">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>0</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QSpinBox" name="spinBoxVA">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>32</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>32</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Only accepts value range (636 - 2468)</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="specialValueText">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string> mV</string>
|
||||
</property>
|
||||
<property name="minimum">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>2468</number>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>0</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="4">
|
||||
<widget class="QLabel" name="labelIA">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>0</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="3" colspan="2">
|
||||
<widget class="QPushButton" name="pushButtonPowerOff">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>36</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QPushButton{background-color: red;}
|
||||
QPushButton:disabled{background-color: grey;}</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Power off</string>
|
||||
</property>
|
||||
<property name="checkable">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="3">
|
||||
<widget class="QLabel" name="labelVIO">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>0</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="4">
|
||||
<widget class="QLabel" name="labelIC">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>0</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QCheckBox" name="checkBoxVC">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>VC</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QSpinBox" name="spinBoxVIO">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>32</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>32</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Only accepts value range (1200 - 2468)</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string> mV</string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>2468</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<widget class="QSpinBox" name="spinBoxVChip">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>32</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>32</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Only accepts value range (1200 - 2468)</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string> mV</string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>2468</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QCheckBox" name="checkBoxVB">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>VB</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="4">
|
||||
<widget class="QLabel" name="labelIIO">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>0</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="3">
|
||||
<widget class="QLabel" name="labelVB">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>0</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="checkBoxVA">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>VA</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="3">
|
||||
<widget class="QLabel" name="labelVD">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>0</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QCheckBox" name="checkBoxVD">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>VD</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="label_136">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>VCHIP</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="3">
|
||||
<widget class="QLabel" name="labelVC">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>0</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QSpinBox" name="spinBoxVD">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>32</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>32</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Only accepts value range (636 - 2468)</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string> mV</string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>2468</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QCheckBox" name="checkBoxVIO">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>VIO</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="4">
|
||||
<widget class="QLabel" name="labelIB">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>0</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<spacer name="horizontalSpacer_12">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>80</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<widget class="QLabel" name="labelVA">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>0</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QSpinBox" name="spinBoxVB">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>32</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>32</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Only accepts value range (636 - 2468)</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="suffix">
|
||||
<string> mV</string>
|
||||
</property>
|
||||
<property name="maximum">
|
||||
<number>2468</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="5">
|
||||
<spacer name="horizontalSpacer_22">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>80</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
6189
pyctbgui/pyctbgui/ui/signals.ui
Normal file
6189
pyctbgui/pyctbgui/ui/signals.ui
Normal file
File diff suppressed because it is too large
Load Diff
472
pyctbgui/pyctbgui/ui/slowAdcs.ui
Normal file
472
pyctbgui/pyctbgui/ui/slowAdcs.ui
Normal file
@ -0,0 +1,472 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Form</class>
|
||||
<widget class="QWidget" name="Form">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>841</width>
|
||||
<height>571</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>841</width>
|
||||
<height>571</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<widget class="QFrame" name="frame_4">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>841</width>
|
||||
<height>571</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Sunken</enum>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_11">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="labelSlowAdc0">
|
||||
<property name="text">
|
||||
<string>SENSE 0:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QLabel" name="labelSlowAdcValue0">
|
||||
<property name="text">
|
||||
<string>***</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="4">
|
||||
<widget class="QPushButton" name="pushButtonSlowAdc0">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>36</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>36</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Cantarell</family>
|
||||
</font>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">background-color: rgb(199, 213, 207);</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Update</string>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset theme="update">
|
||||
<normaloff>../../../../.designer</normaloff>../../../../.designer</iconset>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QLabel" name="labelSlowAdcValue1">
|
||||
<property name="text">
|
||||
<string>***</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="2">
|
||||
<widget class="QLabel" name="labelSlowAdcValue3">
|
||||
<property name="text">
|
||||
<string>***</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="4">
|
||||
<widget class="QPushButton" name="pushButtonSlowAdc3">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>36</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>36</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">background-color: rgb(199, 213, 207);</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Update</string>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QLabel" name="labelSlowAdc4">
|
||||
<property name="text">
|
||||
<string>SENSE 4:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="2">
|
||||
<widget class="QLabel" name="labelTempValue">
|
||||
<property name="text">
|
||||
<string>***</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="4">
|
||||
<widget class="QPushButton" name="pushButtonSlowAdc4">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>36</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>36</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">background-color: rgb(199, 213, 207);</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Update</string>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<spacer name="horizontalSpacer_7">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<widget class="QLabel" name="labelSlowAdc5">
|
||||
<property name="text">
|
||||
<string>SENSE 5:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="2">
|
||||
<widget class="QLabel" name="labelSlowAdcValue5">
|
||||
<property name="text">
|
||||
<string>***</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="4">
|
||||
<widget class="QPushButton" name="pushButtonSlowAdc5">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>36</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>36</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">background-color: rgb(199, 213, 207);</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Update</string>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QLabel" name="labelSlowAdc6">
|
||||
<property name="text">
|
||||
<string>SENSE 6:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="2">
|
||||
<widget class="QLabel" name="labelSlowAdcValue6">
|
||||
<property name="text">
|
||||
<string>***</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="labelSlowAdc1">
|
||||
<property name="text">
|
||||
<string>SENSE 1:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="4">
|
||||
<widget class="QPushButton" name="pushButtonSlowAdc1">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>36</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>36</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">background-color: rgb(199, 213, 207);</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Update</string>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="labelSlowAdc2">
|
||||
<property name="text">
|
||||
<string>SENSE 2:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="2">
|
||||
<widget class="QLabel" name="labelSlowAdcValue4">
|
||||
<property name="text">
|
||||
<string>***</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<widget class="QLabel" name="labelSlowAdcValue2">
|
||||
<property name="text">
|
||||
<string>***</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="4">
|
||||
<widget class="QPushButton" name="pushButtonSlowAdc2">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>36</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>36</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">background-color: rgb(199, 213, 207);</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Update</string>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="labelSlowAdc3">
|
||||
<property name="text">
|
||||
<string>SENSE 3:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="4">
|
||||
<widget class="QPushButton" name="pushButtonSlowAdc6">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>36</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>36</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">background-color: rgb(199, 213, 207);</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Update</string>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<widget class="QLabel" name="labelSlowAdc7">
|
||||
<property name="text">
|
||||
<string>SENSE 7:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="2">
|
||||
<widget class="QLabel" name="labelSlowAdcValue7">
|
||||
<property name="text">
|
||||
<string>***</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="4">
|
||||
<widget class="QPushButton" name="pushButtonSlowAdc7">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>36</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>36</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">background-color: rgb(199, 213, 207);</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Update</string>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="0">
|
||||
<widget class="QLabel" name="labelTemp">
|
||||
<property name="text">
|
||||
<string>Temperature</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="8" column="4">
|
||||
<widget class="QPushButton" name="pushButtonTemp">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>36</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>36</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">background-color: rgb(199, 213, 207);</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Update</string>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<spacer name="horizontalSpacer_10">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="0" column="5">
|
||||
<spacer name="horizontalSpacer_11">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
542
pyctbgui/pyctbgui/ui/transceiver.ui
Normal file
542
pyctbgui/pyctbgui/ui/transceiver.ui
Normal file
@ -0,0 +1,542 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Form</class>
|
||||
<widget class="QWidget" name="Form">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>841</width>
|
||||
<height>239</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>841</width>
|
||||
<height>181</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<widget class="QFrame" name="frame_37">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>20</y>
|
||||
<width>841</width>
|
||||
<height>181</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>841</width>
|
||||
<height>181</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Sunken</enum>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_45">
|
||||
<item row="5" column="0" colspan="7">
|
||||
<widget class="QFrame" name="frame_38">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::StyledPanel</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Raised</enum>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_46">
|
||||
<item row="0" column="2">
|
||||
<widget class="QLineEdit" name="lineEditTransceiverMask">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>32</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>32</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Monospace</family>
|
||||
<pointsize>10</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">background-color: rgb(255, 255, 255);</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>0xFFFF</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QLabel" name="label_87">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Enable mask:</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="3">
|
||||
<spacer name="horizontalSpacer_43">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<widget class="QCheckBox" name="checkBoxTransceiver2Plot">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Plot</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QCheckBox" name="checkBoxTransceiver1Plot">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Plot</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="labelTransceiver0">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>80</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Transceiver 0</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QCheckBox" name="checkBoxTransceiver2">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>En</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="0">
|
||||
<widget class="QLabel" name="labelTransceiver2">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Transceiver 2</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<spacer name="verticalSpacer_7">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="1" column="4">
|
||||
<widget class="QPushButton" name="pushButtonTransceiver1">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QCheckBox" name="checkBoxTransceiver1">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>En</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QCheckBox" name="checkBoxTransceiver0">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>En</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="labelTransceiver1">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Transceiver 1</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="2">
|
||||
<widget class="QCheckBox" name="checkBoxTransceiver0Plot">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Plot</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QLabel" name="labelTransceiver3">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Transceiver 3</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="2">
|
||||
<widget class="QCheckBox" name="checkBoxTransceiver3Plot">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Plot</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="4">
|
||||
<widget class="QPushButton" name="pushButtonTransceiver2">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="5">
|
||||
<spacer name="horizontalSpacer_44">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="3" column="1">
|
||||
<widget class="QCheckBox" name="checkBoxTransceiver3">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>En</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="4">
|
||||
<widget class="QPushButton" name="pushButtonTransceiver3">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="4">
|
||||
<widget class="QPushButton" name="pushButtonTransceiver0">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="flat">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
0
pyctbgui/pyctbgui/utils/__init__.py
Normal file
0
pyctbgui/pyctbgui/utils/__init__.py
Normal file
101
pyctbgui/pyctbgui/utils/alias_utility.py
Normal file
101
pyctbgui/pyctbgui/utils/alias_utility.py
Normal file
@ -0,0 +1,101 @@
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def read_alias_file(alias_file):
|
||||
with open(alias_file) as fp:
|
||||
lines_alias = fp.readlines()
|
||||
return parse_alias_lines(lines_alias)
|
||||
|
||||
|
||||
def parse_alias_lines(lines_alias):
|
||||
bit_names = [None] * 64
|
||||
bit_plots = [None] * 64
|
||||
bit_colors = [None] * 64
|
||||
adc_names = [None] * 32
|
||||
adc_plots = [None] * 32
|
||||
adc_colors = [None] * 32
|
||||
dac_names = [None] * 18
|
||||
sense_names = [None] * 8
|
||||
power_names = [None] * 5
|
||||
pat_file_name = None
|
||||
|
||||
for line_nr, line in enumerate(lines_alias):
|
||||
ignore_list = ['PATCOMPILER']
|
||||
|
||||
# skip empty lines
|
||||
if line == '\n' or len(line) == 0:
|
||||
continue
|
||||
# skip comments
|
||||
if line.startswith('#'):
|
||||
continue
|
||||
|
||||
cmd, *args = line.split()
|
||||
|
||||
if not args:
|
||||
raise Exception(
|
||||
f"Alias file parsing failed: Require atleast one argument in addition to command. ({line_nr}:{line})")
|
||||
|
||||
if cmd.startswith("BIT"):
|
||||
process_alias_bit_or_adc(cmd, args, bit_names, bit_plots, bit_colors)
|
||||
|
||||
elif cmd.startswith("ADC"):
|
||||
process_alias_bit_or_adc(cmd, args, adc_names, adc_plots, adc_colors)
|
||||
|
||||
elif cmd.startswith("DAC"):
|
||||
if len(args) > 1:
|
||||
raise Exception(f"Too many arguments {len(args)} (expected max: 1) for this type. ({line_nr}:{line})")
|
||||
i = int(cmd[3:])
|
||||
dac_names[i] = args[0]
|
||||
|
||||
elif cmd.startswith("SENSE"):
|
||||
if len(args) > 1:
|
||||
raise Exception(f"Too many arguments {len(args)} (expected max: 1) for this type. ({line_nr}:{line})")
|
||||
i = int(cmd[5:])
|
||||
sense_names[i] = args[0]
|
||||
|
||||
elif cmd in ["VA", "VB", "VC", "VD", "VIO"]:
|
||||
if len(args) > 1:
|
||||
raise Exception(f"Too many arguments {len(args)} (expected max: 1) for this type. ({line_nr}:{line})")
|
||||
|
||||
match cmd:
|
||||
case "VA":
|
||||
i = 0
|
||||
case "VB":
|
||||
i = 1
|
||||
case "VC":
|
||||
i = 2
|
||||
case "VD":
|
||||
i = 3
|
||||
case "VIO":
|
||||
i = 4
|
||||
power_names[i] = args[0]
|
||||
|
||||
elif cmd == "PATFILE":
|
||||
if len(args) > 1:
|
||||
raise Exception(f"Too many arguments {len(args)} (expected max: 1) for this type. ({line_nr}:{line})")
|
||||
|
||||
pat_file_name = args[0]
|
||||
path = Path(pat_file_name)
|
||||
if not path.is_file():
|
||||
raise Exception("Pattern file provided in alias file does not exist.<br><br>Pattern file:" +
|
||||
pat_file_name)
|
||||
elif cmd in ignore_list:
|
||||
pass
|
||||
|
||||
else:
|
||||
raise Exception(f"Command: {cmd} not supported. Line {line_nr}:{line}")
|
||||
|
||||
return bit_names, bit_plots, bit_colors, adc_names, adc_plots, adc_colors, dac_names, sense_names, power_names,\
|
||||
pat_file_name
|
||||
|
||||
|
||||
def process_alias_bit_or_adc(cmd, args, names, plots, colors):
|
||||
n_args = len(args)
|
||||
i = int(cmd[3:])
|
||||
names[i] = args[0]
|
||||
if n_args > 1:
|
||||
plots[i] = bool(int(args[1]))
|
||||
if n_args > 2:
|
||||
colors[i] = args[2]
|
||||
if n_args > 3:
|
||||
raise Exception(f"Too many arguments {args} (expected max: 3) for this type in line.")
|
16
pyctbgui/pyctbgui/utils/bit_utils.py
Normal file
16
pyctbgui/pyctbgui/utils/bit_utils.py
Normal file
@ -0,0 +1,16 @@
|
||||
def set_bit(value, bit_nr):
|
||||
return value | 1 << bit_nr
|
||||
|
||||
|
||||
def remove_bit(value, bit_nr):
|
||||
return value & ~(1 << bit_nr)
|
||||
|
||||
|
||||
def bit_is_set(value, bit_nr):
|
||||
return (value >> bit_nr) & 1 == 1
|
||||
|
||||
|
||||
def manipulate_bit(is_set, value, bit_nr):
|
||||
if is_set:
|
||||
return set_bit(value, bit_nr)
|
||||
return remove_bit(value, bit_nr)
|
51
pyctbgui/pyctbgui/utils/decoder.py
Normal file
51
pyctbgui/pyctbgui/utils/decoder.py
Normal file
@ -0,0 +1,51 @@
|
||||
from pyctbgui.utils.defines import Defines
|
||||
from pyctbgui._decoder import * #bring in the function from the compiled extension
|
||||
import numpy as np
|
||||
"""
|
||||
Python implementation, keep as a reference. Change name and replace
|
||||
with C version to swap it out in the GUI
|
||||
"""
|
||||
|
||||
|
||||
def moench04(analog_buffer):
|
||||
nAnalogCols = Defines.Moench04.nCols
|
||||
nAnalogRows = Defines.Moench04.nRows
|
||||
adcNumbers = Defines.Moench04.adcNumbers
|
||||
nPixelsPerSC = Defines.Moench04.nPixelsPerSuperColumn
|
||||
scWidth = Defines.Moench04.superColumnWidth
|
||||
|
||||
analog_frame = np.zeros((nAnalogCols, nAnalogRows), dtype=analog_buffer.dtype)
|
||||
|
||||
for iPixel in range(nPixelsPerSC):
|
||||
for iSC, iAdc in enumerate(adcNumbers):
|
||||
col = ((iAdc % 16) * scWidth) + (iPixel % scWidth)
|
||||
if iSC < 16:
|
||||
row = 199 - int(iPixel / scWidth)
|
||||
else:
|
||||
row = 200 + int(iPixel / scWidth)
|
||||
index_min = iPixel * 32 + iSC
|
||||
pixel_value = analog_buffer[index_min]
|
||||
analog_frame[row, col] = pixel_value
|
||||
|
||||
return analog_frame
|
||||
|
||||
|
||||
def matterhorn(trans_buffer):
|
||||
nTransceiverRows = Defines.Matterhorn.nRows
|
||||
nTransceiverCols = Defines.Matterhorn.nCols
|
||||
|
||||
transceiver_frame = np.zeros((nTransceiverCols, nTransceiverRows), dtype=trans_buffer.dtype)
|
||||
|
||||
offset = 0
|
||||
nSamples = Defines.Matterhorn.nPixelsPerTransceiver
|
||||
for row in range(Defines.Matterhorn.nRows):
|
||||
for col in range(Defines.Matterhorn.nHalfCols):
|
||||
#print(f'row:{row} col:{col} offset: {offset}')
|
||||
for iTrans in range(Defines.Matterhorn.nTransceivers):
|
||||
transceiver_frame[iTrans * Defines.Matterhorn.nHalfCols + col,
|
||||
row] = trans_buffer[offset + nSamples * iTrans]
|
||||
offset += 1
|
||||
if (col + 1) % nSamples == 0:
|
||||
offset += nSamples
|
||||
|
||||
return transceiver_frame
|
111
pyctbgui/pyctbgui/utils/defines.py
Normal file
111
pyctbgui/pyctbgui/utils/defines.py
Normal file
@ -0,0 +1,111 @@
|
||||
from enum import Enum
|
||||
|
||||
|
||||
class Defines:
|
||||
Time_Wait_For_Packets_ms = 0.5
|
||||
Time_Status_Refresh_ms = 100
|
||||
Time_Plot_Refresh_ms = 20
|
||||
|
||||
Zmq_hwm_high_speed = 2
|
||||
Zmq_hwm_low_speed = -1
|
||||
|
||||
Acquisition_Tab_Index = 7
|
||||
Max_Tabs = 9
|
||||
|
||||
class adc:
|
||||
tabIndex = 5
|
||||
count = 32
|
||||
half = 16
|
||||
BIT0_15_MASK = 0x0000FFFF
|
||||
BIT16_31_MASK = 0xFFFF0000
|
||||
|
||||
class dac:
|
||||
tabIndex = 0
|
||||
count = 18
|
||||
|
||||
class signals:
|
||||
tabIndex = 3
|
||||
count = 64
|
||||
half = 32
|
||||
BIT0_31_MASK = 0x00000000FFFFFFFF
|
||||
BIT32_63_MASK = 0xFFFFFFFF00000000
|
||||
|
||||
class pattern:
|
||||
tabIndex = 6
|
||||
loops_count = 6
|
||||
|
||||
class transceiver:
|
||||
count = 4
|
||||
tabIndex = 4
|
||||
|
||||
class slowAdc:
|
||||
tabIndex = 2
|
||||
count = 8
|
||||
|
||||
colCount = 4
|
||||
|
||||
powerSupplies = ('A', 'B', 'C', 'D', 'IO')
|
||||
|
||||
class ImageIndex(Enum):
|
||||
Matterhorn = 0
|
||||
Moench04 = 1
|
||||
|
||||
class Matterhorn:
|
||||
nRows = 48
|
||||
nHalfCols = 24
|
||||
nCols = 48
|
||||
nTransceivers = 2
|
||||
tranceiverEnable = 0x3
|
||||
nPixelsPerTransceiver = 4
|
||||
|
||||
class Moench04:
|
||||
nRows = 400
|
||||
nCols = 400
|
||||
adcNumbers = [
|
||||
9, 8, 11, 10, 13, 12, 15, 14, 1, 0, 3, 2, 5, 4, 7, 6, 23, 22, 21, 20, 19, 18, 17, 16, 31, 30, 29, 28, 27,
|
||||
26, 25, 24
|
||||
]
|
||||
nPixelsPerSuperColumn = 5000
|
||||
superColumnWidth = 25
|
||||
|
||||
Color_map = [
|
||||
'viridis', 'plasma', 'inferno', 'magma', 'cividis', 'binary', 'gist_yarg', 'gist_gray', 'gray', 'bone', 'pink',
|
||||
'spring', 'summer', 'autumn', 'winter', 'cool', 'Wistia', 'hot', 'afmhot', 'gist_heat', 'copper',
|
||||
'gist_rainbow', 'rainbow', 'jet', 'turbo'
|
||||
]
|
||||
Default_Color_Map = 'viridis'
|
||||
|
||||
# pattern viewer defines
|
||||
|
||||
# pattern plot
|
||||
Colors_plot = ['Blue', 'Orange']
|
||||
|
||||
# Wait colors and line styles (6 needed from 0 to 5)
|
||||
# Colors_wait = ['b', 'g', 'r', 'c', 'm', 'y']
|
||||
Colors_wait = ['Blue', 'Green', 'Red', 'Cyan', 'Magenta', 'Yellow']
|
||||
Linestyles_wait = ['--', '--', '--', '--', '--', '--']
|
||||
Alpha_wait = [0.5, 0.5, 0.5, 0.5, 0.5, 0.5]
|
||||
Alpha_wait_rect = [0.2, 0.2, 0.2, 0.2, 0.2, 0.2]
|
||||
|
||||
# Loop colors and line styles (6 needed from 0 to 5)
|
||||
Colors_loop = ['Green', 'Red', 'Purple', 'Brown', 'Pink', 'Grey']
|
||||
Linestyles_loop = ['-.', '-.', '-.', '-.', '-.', '-.']
|
||||
Alpha_loop = [0.5, 0.5, 0.5, 0.5, 0.5, 0.5]
|
||||
Alpha_loop_rect = [0.2, 0.2, 0.2, 0.2, 0.2, 0.2]
|
||||
|
||||
# Display the count of clocks
|
||||
Clock_vertical_lines_spacing = 50
|
||||
Show_clocks_number = True
|
||||
Line_width = 2.0
|
||||
|
||||
Colors = [
|
||||
'Blue', 'Orange', 'Green', 'Red', 'Purple', 'Brown', 'Pink', 'Gray', 'Olive', 'Cyan', 'Magenta', 'Yellow',
|
||||
'Black', 'White'
|
||||
]
|
||||
|
||||
LineStyles = ['-', '--', '-.', ':']
|
||||
|
||||
class colorRange(Enum):
|
||||
all = 0
|
||||
center = 1
|
||||
fixed = 2
|
0
pyctbgui/pyctbgui/utils/numpyWriter/__init__.py
Normal file
0
pyctbgui/pyctbgui/utils/numpyWriter/__init__.py
Normal file
224
pyctbgui/pyctbgui/utils/numpyWriter/npy_writer.py
Normal file
224
pyctbgui/pyctbgui/utils/numpyWriter/npy_writer.py
Normal file
@ -0,0 +1,224 @@
|
||||
"""
|
||||
Wrapper to be able to append frames to a numpy file
|
||||
|
||||
numpy header v1
|
||||
|
||||
- 6bytes \x93NUMPY
|
||||
- 1 byte major version number \x01
|
||||
- 1 byte minor version number \x00
|
||||
- 2 bytes (unsigned short) HEADER_LEN length of header to follow
|
||||
- Header as an ASCII dict terminated by \n padded with space \x20 to make sure
|
||||
we get len(magic string) + 2 + len(length) + HEADER_LEN divisible with 64
|
||||
Allocate enough space to allow for the data to grow
|
||||
"""
|
||||
|
||||
import ast
|
||||
import os
|
||||
import zipfile
|
||||
from pathlib import Path
|
||||
|
||||
import numpy as np
|
||||
|
||||
|
||||
class NumpyFileManager:
|
||||
"""
|
||||
class used to read and write into .npy files that can't be loaded completely into memory
|
||||
|
||||
for read mode implements numpy like interface and file-like object function
|
||||
"""
|
||||
magic_str = np.lib.format.magic(1, 0)
|
||||
headerLength = np.uint16(128)
|
||||
FSEEK_FILE_END = 2
|
||||
BUFFER_MAX = 500
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
file: str | Path | zipfile.ZipExtFile,
|
||||
mode: str = 'r',
|
||||
frameShape: tuple = None,
|
||||
dtype=None,
|
||||
):
|
||||
"""
|
||||
initiates a NumpyFileManager class for reading or writing bytes directly to/from a .npy file
|
||||
@param file: path to the file to open or create
|
||||
@param frameShape: shape of the frame ex: (5000,) for waveforms or (400,400) for image
|
||||
@param dtype: type of the numpy array's header
|
||||
@param mode: file open mode must be in 'rwx'
|
||||
"""
|
||||
if mode not in ['r', 'w', 'x', 'r+']:
|
||||
raise ValueError('file mode should be either r,w,x,r+')
|
||||
|
||||
if isinstance(file, zipfile.ZipExtFile):
|
||||
if mode != 'r':
|
||||
raise ValueError('NumpyFileManager only supports read mode for zipfiles')
|
||||
else:
|
||||
if mode == 'x' and Path.is_file(Path(file)):
|
||||
raise FileExistsError(f'file {file} exists while given mode is x')
|
||||
|
||||
self.dtype = np.dtype(dtype) # in case we pass a type like np.float32
|
||||
self.frameShape = frameShape
|
||||
self.frameCount = 0
|
||||
self.cursorPosition = self.headerLength
|
||||
self.mode = mode
|
||||
|
||||
# if newFile frameShape and dtype should be present
|
||||
if mode == 'w' or mode == 'x':
|
||||
assert frameShape is not None
|
||||
assert dtype is not None
|
||||
# create/clear the file with mode wb+
|
||||
self.file = open(file, 'wb+')
|
||||
self.updateHeader()
|
||||
|
||||
else:
|
||||
# opens file for read and check if the header of the file corresponds to the given function
|
||||
# arguments
|
||||
if isinstance(file, zipfile.ZipExtFile):
|
||||
self.file = file
|
||||
else:
|
||||
mode = 'rb' if self.mode == 'r' else 'rb+'
|
||||
self.file = open(file, mode)
|
||||
self.file.seek(10)
|
||||
headerStr = self.file.read(np.uint16(self.headerLength - 10)).decode("UTF-8")
|
||||
header_dict = ast.literal_eval(headerStr)
|
||||
self.frameShape = header_dict['shape'][1:]
|
||||
if frameShape is not None:
|
||||
assert frameShape == self.frameShape, \
|
||||
f"shape in arguments ({frameShape}) is not the same as the shape of the stored " \
|
||||
f"file ({self.frameShape})"
|
||||
|
||||
self.dtype = np.lib.format.descr_to_dtype(header_dict['descr'])
|
||||
if dtype is not None:
|
||||
assert dtype == self.dtype, \
|
||||
f"dtype in argument ({dtype}) is not the same as the dtype of the stored file ({self.dtype})"
|
||||
|
||||
self.frameCount = header_dict['shape'][0]
|
||||
|
||||
assert not header_dict['fortran_order'], "fortran_order in the stored file is not False"
|
||||
|
||||
self.__frameSize = np.dtype(self.dtype).itemsize * np.prod(self.frameShape)
|
||||
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type, exc_val, exc_tb):
|
||||
self.close()
|
||||
|
||||
def restoreCursorPosition(func):
|
||||
"""
|
||||
decorator function used to restore the file descriptors
|
||||
cursor position after using read or write functions
|
||||
"""
|
||||
|
||||
def wrapper(self, *args, **kwargs):
|
||||
tmp = self.cursorPosition
|
||||
result = func(self, *args, **kwargs)
|
||||
self.cursorPosition = tmp
|
||||
self.file.seek(tmp)
|
||||
return result
|
||||
|
||||
return wrapper
|
||||
|
||||
@restoreCursorPosition
|
||||
def updateHeader(self):
|
||||
"""
|
||||
updates the header of the .npy file with the class attributes
|
||||
@note: fortran_order is always set to False
|
||||
"""
|
||||
if self.mode == 'r':
|
||||
return
|
||||
self.file.seek(0)
|
||||
header_dict = {
|
||||
'descr': np.lib.format.dtype_to_descr(self.dtype),
|
||||
'fortran_order': False,
|
||||
'shape': (self.frameCount, *self.frameShape)
|
||||
}
|
||||
np.lib.format.write_array_header_1_0(self.file, header_dict)
|
||||
self.flush()
|
||||
|
||||
@restoreCursorPosition
|
||||
def writeOneFrame(self, frame: np.ndarray):
|
||||
"""
|
||||
write one frame without buffering
|
||||
@param frame: numpy array for a frame
|
||||
"""
|
||||
if frame.shape != self.frameShape:
|
||||
raise ValueError(f"frame shape given {frame.shape} is not the same as the file's shape {self.frameShape}")
|
||||
if frame.dtype != self.dtype:
|
||||
raise ValueError(f"frame dtype given {frame.dtype} is not the same as the file's dtype {self.dtype}")
|
||||
|
||||
self.file.seek(0, self.FSEEK_FILE_END)
|
||||
self.frameCount += 1
|
||||
self.file.write(frame.tobytes())
|
||||
|
||||
def flush(self):
|
||||
"""
|
||||
persist data into disk
|
||||
"""
|
||||
self.file.flush()
|
||||
os.fsync(self.file)
|
||||
|
||||
@restoreCursorPosition
|
||||
def readFrames(self, frameStart: int, frameEnd: int) -> np.ndarray:
|
||||
"""
|
||||
read frames from .npy file without loading the whole file to memory with np.load
|
||||
@param frameStart: number of the frame to start reading from
|
||||
@param frameEnd: index of the last frame (not inclusive)
|
||||
@return: np.ndarray of frames of the shape [frameEnd-frameStart,*self.frameShape]
|
||||
"""
|
||||
frameCount = frameEnd - frameStart
|
||||
|
||||
if frameStart < 0:
|
||||
raise NotImplementedError("frameStart must be bigger than 0")
|
||||
if frameCount < 0:
|
||||
if frameStart <= 0:
|
||||
raise NotImplementedError("frameEnd must be bigger than frameStart")
|
||||
frameCount = 0
|
||||
self.file.seek(self.headerLength + frameStart * self.__frameSize)
|
||||
data = self.file.read(frameCount * self.__frameSize)
|
||||
return np.frombuffer(data, self.dtype).reshape([-1, *self.frameShape])
|
||||
|
||||
def read(self, frameCount):
|
||||
"""
|
||||
file like interface to read frameCount frames from the already stored position
|
||||
@param frameCount: number of frames to read
|
||||
@return: numpy array containing frameCount frames
|
||||
"""
|
||||
assert frameCount > 0
|
||||
data = self.file.read(frameCount * self.__frameSize)
|
||||
self.cursorPosition += frameCount * self.__frameSize
|
||||
return np.frombuffer(data, self.dtype).reshape([-1, *self.frameShape])
|
||||
|
||||
def seek(self, frameNumber):
|
||||
"""
|
||||
file-like interface to move the file's cursor position to the frameNumber
|
||||
"""
|
||||
assert frameNumber >= 0
|
||||
self.cursorPosition = self.headerLength + frameNumber * self.__frameSize
|
||||
self.file.seek(self.cursorPosition)
|
||||
|
||||
def close(self):
|
||||
self.updateHeader()
|
||||
self.file.close()
|
||||
|
||||
def __getitem__(self, item):
|
||||
isSlice = False
|
||||
if isinstance(item, slice):
|
||||
isSlice = True
|
||||
if item.step is not None:
|
||||
raise NotImplementedError("step parameter is not implemented yet")
|
||||
if isSlice:
|
||||
return self.readFrames(item.start, item.stop)
|
||||
frame = self.readFrames(item, item + 1)
|
||||
if frame.size != 0:
|
||||
frame = frame.squeeze(0)
|
||||
return frame
|
||||
|
||||
def __del__(self):
|
||||
"""
|
||||
in case the user forgot to close the file
|
||||
"""
|
||||
if hasattr(self, 'file') and not self.file.closed:
|
||||
try:
|
||||
self.close()
|
||||
except ImportError:
|
||||
self.file.close()
|
91
pyctbgui/pyctbgui/utils/numpyWriter/npz_writer.py
Normal file
91
pyctbgui/pyctbgui/utils/numpyWriter/npz_writer.py
Normal file
@ -0,0 +1,91 @@
|
||||
from pathlib import Path
|
||||
import shutil
|
||||
import zipfile
|
||||
import io
|
||||
|
||||
import numpy as np
|
||||
from pyctbgui.utils.numpyWriter.npy_writer import NumpyFileManager
|
||||
|
||||
|
||||
class NpzFileWriter:
|
||||
"""
|
||||
Write data to npz file incrementally rather than compute all and write
|
||||
once, as in ``np.save``. This class can be used with ``contextlib.closing``
|
||||
to ensure closed after usage.
|
||||
"""
|
||||
|
||||
def __init__(self, tofile: str, mode='w', compress_file=False):
|
||||
"""
|
||||
:param tofile: the ``npz`` file to write
|
||||
:param mode: must be one of {'x', 'w', 'a'}. See
|
||||
https://docs.python.org/3/library/zipfile.html for detail
|
||||
"""
|
||||
self.__openedFiles = {}
|
||||
self.compression = zipfile.ZIP_DEFLATED if compress_file else zipfile.ZIP_STORED
|
||||
self.tofile = tofile
|
||||
self.mode = mode
|
||||
self.file = zipfile.ZipFile(self.tofile, mode=self.mode, compression=self.compression)
|
||||
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
||||
def __exit__(self, exc_type, exc_val, exc_tb):
|
||||
self.close()
|
||||
|
||||
def writeArray(self, key: str, data: np.ndarray | bytes) -> None:
|
||||
"""
|
||||
overwrite existing data of name ``key``.
|
||||
|
||||
:param key: the name of data to write
|
||||
:param data: the data
|
||||
"""
|
||||
key += '.npy'
|
||||
with io.BytesIO() as cbuf:
|
||||
np.save(cbuf, data)
|
||||
cbuf.seek(0)
|
||||
with self.file.open(key, mode='w', force_zip64=True) as outfile:
|
||||
shutil.copyfileobj(cbuf, outfile)
|
||||
|
||||
def readFrames(self, file: str, frameStart: int, frameEnd: int):
|
||||
file += '.npy'
|
||||
with self.file.open(file, mode='r') as outfile:
|
||||
npw = NumpyFileManager(outfile)
|
||||
return npw.readFrames(frameStart, frameEnd)
|
||||
|
||||
@staticmethod
|
||||
def zipNpyFiles(filename: str,
|
||||
files: list[str | Path],
|
||||
fileKeys: list[str],
|
||||
deleteOriginals=False,
|
||||
compressed=False):
|
||||
compression = zipfile.ZIP_DEFLATED if compressed else zipfile.ZIP_STORED
|
||||
|
||||
with zipfile.ZipFile(filename, mode='w', compression=compression, allowZip64=True) as zipf:
|
||||
for idx, file in enumerate(files):
|
||||
zipf.write(file, arcname=fileKeys[idx] + '.npy')
|
||||
if deleteOriginals:
|
||||
for file in files:
|
||||
Path.unlink(file)
|
||||
|
||||
def __getitem__(self, item: str) -> NumpyFileManager:
|
||||
"""
|
||||
returns NumpyFileManager file handling the .npy file under the key item inside of the .npz file
|
||||
@param item:
|
||||
@return:
|
||||
"""
|
||||
if not isinstance(item, str):
|
||||
raise TypeError('given item is not of type str')
|
||||
if item not in self.__openedFiles:
|
||||
outfile = self.file.open(item + '.npy', mode='r')
|
||||
self.__openedFiles[item] = NumpyFileManager(outfile)
|
||||
return self.__openedFiles[item]
|
||||
|
||||
def namelist(self):
|
||||
return sorted([key[:-4] for key in self.file.namelist()])
|
||||
|
||||
def close(self):
|
||||
if hasattr(self, 'file') and self.file is not None:
|
||||
self.file.close()
|
||||
|
||||
def __del__(self):
|
||||
self.close()
|
71
pyctbgui/pyctbgui/utils/numpyWriter/usage.md
Normal file
71
pyctbgui/pyctbgui/utils/numpyWriter/usage.md
Normal file
@ -0,0 +1,71 @@
|
||||
# Using numpyWriter module
|
||||
## concept
|
||||
numpyWriter is used to write and load huge numpy arrays that can't be fully loaded in RAM.
|
||||
It is designed to write frames of a constant shape (defined by user) and incrementally add to .npy and .npz files without accessing all of its contents
|
||||
|
||||
### NumpyFileManager
|
||||
class to handle writing in .npy files frame by frame.
|
||||
its positional parameter `file` can be of type: str,pathlib.Path, zipfile.ZipExtFile. This way we can use NumpyFileManager to open files by getting their path or
|
||||
**in read mode** it can receiver file-like objects to read their data.
|
||||
|
||||
the complexity of initializing from file-like objects is added to be able to read from .npz files which are simply a zip of .npy files. Furthermore now we can save our files .npz files and read from them (even when compressed (⊙_⊙) ) without loading the whole .npy or .npz in memory.
|
||||
|
||||
### NpzFileWriter
|
||||
class used to handle .npz file functionalities. it can zip existing .npy files, write a whole array in an .npz file without loading the whole .npz in memory,
|
||||
and read frames from .npy files inside the .npz file
|
||||
|
||||
## Usage
|
||||
|
||||
```python
|
||||
# create .npy file
|
||||
npw = NumpyFileManager('file.npy', 'w', (400, 400), np.int32)
|
||||
npw.addFrame(np.ones([400, 400], dtype=np.int32))
|
||||
npw.close()
|
||||
|
||||
# read frames from existing .npy file
|
||||
npw = NumpyFileManager('file.npy')
|
||||
# if arr is stored in the .npy file this statement will return arr[50:100]
|
||||
npw.readFrames(50, 100)
|
||||
|
||||
# Numpy like interface
|
||||
# NumpyFileManager is also subscriptable
|
||||
npw[50:100] # returns the array arr[50:100]
|
||||
npw[0] # returns the array arr[0]
|
||||
|
||||
# File like interface
|
||||
# the npw class's cursors is initialized on the first frame
|
||||
npw.read(5) # reads five frames and updates the cursor
|
||||
npw.seek(99) # updates the cursor to point it to the 99-th frame
|
||||
|
||||
# to ensure that files are written to disk
|
||||
npw.flush()
|
||||
|
||||
# zip existing .npy files (stored on disk)
|
||||
# filePaths: the paths to .npy files
|
||||
# keys: name of the arrays inside of the .npz file
|
||||
NpzFileWriter.zipNpyFiles('file.npz', filePaths, keys, compressed=True)
|
||||
|
||||
# add numpy arrays incrementally to a .npz file
|
||||
with NpzFileWriter('tmp.npz', 'w', compress_file=True) as npz:
|
||||
npz.writeArray('adc', arr1)
|
||||
npz.writeArray('tx', arr2)
|
||||
|
||||
# read frames from adc.npy inside of tmp.npz
|
||||
with NpzFileWriter('tmp.npz', 'r') as npz:
|
||||
frames = npz.readFrames('adc', 5, 8)
|
||||
|
||||
# NpzFileWriter is also subscriptable and returns a NumpyFileManager initialized
|
||||
# to open the the file with the given key inside the .npz file
|
||||
npz = NpzFileWriter('tmp.npz', 'r')
|
||||
npz.writeArray('adc', arr1)
|
||||
|
||||
|
||||
npz['adc'] # returns a NumpyFileManager
|
||||
npz['adc'][50:100] # returns the array from 50 to 100
|
||||
# note once a NumpyFileManager instance is created internally NpzFileWriter stores it
|
||||
# this is done to avoid opening and closing the same file
|
||||
# also file-like interface can be used
|
||||
npz['adc'].read(5) # returns arr[:5]
|
||||
npz['adc'].seek(100) # updates the cursor
|
||||
npz['adc'].read(2) # returns arr[100:2]
|
||||
```
|
61
pyctbgui/pyctbgui/utils/pixelmap.py
Normal file
61
pyctbgui/pyctbgui/utils/pixelmap.py
Normal file
@ -0,0 +1,61 @@
|
||||
import numpy as np
|
||||
# generate pixelmaps for various CTB detectors
|
||||
|
||||
|
||||
def moench03():
|
||||
out = np.zeros((400, 400), dtype=np.uint32)
|
||||
adc_numbers = np.array(
|
||||
(12, 13, 14, 15, 12, 13, 14, 15, 8, 9, 10, 11, 8, 9, 10, 11, 4, 5, 6, 7, 4, 5, 6, 7, 0, 1, 2, 3, 0, 1, 2, 3),
|
||||
dtype=np.int_)
|
||||
for n_pixel in range(5000):
|
||||
for i_sc in range(32):
|
||||
adc_nr = adc_numbers[i_sc]
|
||||
col = ((adc_nr * 25) + (n_pixel % 25))
|
||||
row = 0
|
||||
if (i_sc // 4 % 2 == 0):
|
||||
row = 199 - (n_pixel // 25)
|
||||
else:
|
||||
row = 200 + (n_pixel // 25)
|
||||
|
||||
i_analog = n_pixel * 32 + i_sc
|
||||
out[row, col] = i_analog
|
||||
|
||||
return out
|
||||
|
||||
|
||||
def moench04_analog():
|
||||
out = np.zeros((400, 400), dtype=np.uint32)
|
||||
adc_numbers = np.array((9, 8, 11, 10, 13, 12, 15, 14, 1, 0, 3, 2, 5, 4, 7, 6, 23, 22, 21, 20, 19, 18, 17, 16, 31,
|
||||
30, 29, 28, 27, 26, 25, 24),
|
||||
dtype=np.int_)
|
||||
|
||||
for n_pixel in range(5000):
|
||||
for i_sc in range(32):
|
||||
adc_nr = adc_numbers[i_sc]
|
||||
col = ((adc_nr % 16) * 25) + (n_pixel % 25)
|
||||
row = 0
|
||||
if i_sc < 16:
|
||||
row = 199 - (n_pixel // 25)
|
||||
else:
|
||||
row = 200 + (n_pixel // 25)
|
||||
|
||||
i_analog = n_pixel * 32 + i_sc
|
||||
out[row, col] = i_analog
|
||||
|
||||
return out
|
||||
|
||||
|
||||
def matterhorn_transceiver():
|
||||
out = np.zeros((48, 48), dtype=np.uint32)
|
||||
|
||||
offset = 0
|
||||
nSamples = 4
|
||||
for row in range(48):
|
||||
for col in range(24):
|
||||
for iTrans in range(2):
|
||||
out[iTrans * 24 + col, row] = offset + nSamples * iTrans
|
||||
offset += 1
|
||||
if (col + 1) % nSamples == 0:
|
||||
offset += nSamples
|
||||
|
||||
return out
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user