mirror of
https://github.com/slsdetectorgroup/slsDetectorPackage.git
synced 2025-06-17 15:27:13 +02:00
Compare commits
59 Commits
submodfix
...
patrick_25
Author | SHA1 | Date | |
---|---|---|---|
0ac52b81b9 | |||
6cbd0b0529 | |||
505bf9642f | |||
76ab0228ac | |||
a1e69bba37 | |||
270ee48148 | |||
c679135138 | |||
0f88617477 | |||
04eed990c7 | |||
d2bfb91a16 | |||
5e024153bc | |||
e59de85a33 | |||
fd010b9aa5 | |||
45957391a6 | |||
f2f3817a7f | |||
f43bb8eea4 | |||
8a7ed30676 | |||
5b832cb6aa | |||
7fa5b5d70a | |||
6348ccd05b | |||
8144397b2c | |||
2dc0963c56 | |||
a44ba4dc35 | |||
007330caa7 | |||
492b4815a6 | |||
33b8e0817e | |||
ab7425a9d3 | |||
d8f925520e | |||
9f079b17a2 | |||
5b61ff24bb | |||
c6477e0ed6 | |||
38d7fb0c38 | |||
e848293916 | |||
15e8c0d9f1 | |||
588d11dedf | |||
782c8abd9a | |||
1d4a5d6d29 | |||
9c57571a41 | |||
b4533ac11f | |||
991a4115d4 | |||
ff107faae6 | |||
d57643434d | |||
de33aff077 | |||
c13049f144 | |||
ce7f01bdc4 | |||
bf523c0c5e | |||
1efd106c6a | |||
08dc8e3cbb | |||
96f7a1ecfb | |||
64d489f1e6 | |||
56abf82d92 | |||
3d21bb64c4 | |||
f6b0ba9703 | |||
d17bc5da62 | |||
a884db0e2c | |||
5e9fd43d49 | |||
8bce89d5dc | |||
aa40128965 | |||
a03780718e |
@ -2,7 +2,7 @@
|
||||
# Copyright (C) 2021 Contributors to the SLS Detector Package
|
||||
cmake_minimum_required(VERSION 3.14)
|
||||
project(slsDetectorPackage)
|
||||
set(PROJECT_VERSION 7.0.0)
|
||||
set(PROJECT_VERSION 9.0.0)
|
||||
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "-O3 -DNDEBUG")
|
||||
|
||||
@ -148,7 +148,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 +231,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()
|
||||
@ -316,7 +317,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
|
||||
|
55
RELEASE.txt
55
RELEASE.txt
@ -1,7 +1,7 @@
|
||||
SLS Detector Package Major Release 7.x.x released on xx.xx.2023
|
||||
SLS Detector Package Major Release x.x.x released on xx.xx.202x
|
||||
===============================================================
|
||||
|
||||
This document describes the differences between v7.x.x and v7.0.2
|
||||
This document describes the differences between vx.x.x and vx.0.2
|
||||
|
||||
|
||||
|
||||
@ -28,9 +28,6 @@ This document describes the differences between v7.x.x and v7.0.2
|
||||
=====================================
|
||||
|
||||
|
||||
- moench being made compatible with jungfrau 2.0 boards (jungfrau structure, away from ctb)
|
||||
- eiger febl and feb in versions
|
||||
- fix ctb slow adcs
|
||||
|
||||
|
||||
|
||||
@ -38,22 +35,24 @@ This document describes the differences between v7.x.x and v7.0.2
|
||||
==========================================
|
||||
|
||||
|
||||
Eiger 7.0.0
|
||||
Jungfrau 7.0.2
|
||||
Mythen3 7.0.0
|
||||
Gotthard2 7.0.0
|
||||
Gotthard 7.0.0
|
||||
Moench 7.0.0
|
||||
Ctb 7.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'
|
||||
From 5.0.0 (with tftp):
|
||||
Using command 'copydetectorserver'
|
||||
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
|
||||
@ -65,22 +64,20 @@ This document describes the differences between v7.x.x and v7.0.2
|
||||
========================
|
||||
|
||||
|
||||
Eiger 20.02.2023 (v31)
|
||||
Eiger 02.10.2023 (v32) (updated in 7.0.3)
|
||||
|
||||
Jungfrau 04.11.2022 (v1.4, HW v1.0)
|
||||
03.11.2022 (v2.4, HW v2.0)
|
||||
Jungfrau 01.10.2024 (v1.6, HW v1.0) (updated in 9.0.0)
|
||||
01.10.2024 (v2.6, HW v2.0) (updated in 9.0.0)
|
||||
|
||||
Mythen3 24.01.2023 (v1.4)
|
||||
Mythen3 11.10.2024 (v1.5) (updated in 9.0.0)
|
||||
|
||||
Gotthard2 23.11.2022 (v0.3)
|
||||
Gotthard2 03.10.2024 (v1.0) (updated in 9.0.0)
|
||||
|
||||
Moench 26.10.2023 (v2.0) (updated in 9.0.0)
|
||||
|
||||
Gotthard 08.02.2018 (50um and 25um Master)
|
||||
09.02.2018 (25 um Slave)
|
||||
|
||||
Moench 05.12.2022 (v0.3)
|
||||
|
||||
Ctb 03.04.2023 (v1.2?)
|
||||
|
||||
|
||||
Detector Upgrade
|
||||
----------------
|
||||
@ -92,7 +89,6 @@ This document describes the differences between v7.x.x and v7.0.2
|
||||
Mythen3 via command <.rbf>
|
||||
Gotthard2 via command <.rbf>
|
||||
Moench via command <.pof>
|
||||
Ctb via command <.pof>
|
||||
|
||||
Gotthard cannot be upgraded remotely
|
||||
|
||||
@ -100,7 +96,7 @@ This document describes the differences between v7.x.x and v7.0.2
|
||||
upgrade
|
||||
Using command 'programfpga' or
|
||||
|
||||
udpate both server and firmware simultaneously
|
||||
udpate both on-board detector server and firmware simultaneously
|
||||
Using command 'update'
|
||||
|
||||
|
||||
@ -113,6 +109,7 @@ This document describes the differences between v7.x.x and v7.0.2
|
||||
4 Kernel Requirements
|
||||
======================
|
||||
|
||||
|
||||
Blackfin
|
||||
--------
|
||||
Latest version: Fri Oct 29 00:00:00 2021
|
||||
@ -120,10 +117,12 @@ This document describes the differences between v7.x.x and v7.0.2
|
||||
Older ones will work, but might have issues with programming firmware via
|
||||
the package.
|
||||
|
||||
|
||||
Nios
|
||||
-----
|
||||
Compatible version: Mon May 10 18:00:21 CEST 2021
|
||||
|
||||
|
||||
Kernel Upgrade
|
||||
---------------
|
||||
Eiger via bit files
|
||||
@ -212,4 +211,4 @@ This document describes the differences between v7.x.x and v7.0.2
|
||||
-------
|
||||
|
||||
dhanya.thattil@psi.ch
|
||||
erik.frojdh@psi.ch
|
||||
erik.frojdh@psi.ch
|
@ -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
|
||||
|
@ -890,7 +890,7 @@ EXCLUDE_SYMLINKS = NO
|
||||
# Note that the wildcards are matched against the file with absolute path, so to
|
||||
# exclude all test directories for example use the pattern */test/*
|
||||
|
||||
EXCLUDE_PATTERNS = */docs/* */tests/* */python/* */manual */slsDetectorServers/* */libs/* */integrationTests *README* */slsDetectorGui/* */ctbGui/* */slsDetectorCalibration/*
|
||||
EXCLUDE_PATTERNS = */docs/* */tests/* */python/* */manual */slsDetectorServers/* */libs/* */integrationTests *README* */slsDetectorGui/* */ctbGui/* */slsDetectorCalibration/* *TobiSchluter*
|
||||
|
||||
# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
|
||||
# (namespaces, classes, functions, etc.) that should be excluded from the
|
||||
|
@ -32,14 +32,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
|
||||
|
||||
|
@ -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 = proxy.GetDeprecatedCommands();
|
||||
for (auto it : cmds) {
|
||||
fs2 << it.first << ", " << it.second << '\n';
|
||||
}
|
||||
|
@ -22,6 +22,8 @@ Common
|
||||
* Check transeiver and fibers are compatible (all MMF 850nm or all SMF 1030nm)
|
||||
* Check fiber
|
||||
* Check fiber polarity (if short range, unplug the link anywhere, and look at the light/dark pattern: dark has to mate with light)
|
||||
* For Jungfrau, check if the blue sfp light is blinking rapidly (even when it is not sending data). If so, most likely the link is down and something is wrong with the board. If it connected to a switch, then you do not see it with the ethtool command if link is down. One option is to connect it directly to a pc to see if link is down.
|
||||
* With nc, try "nc -u -p 50001 -l" in receiving pc, and from another pc try "echo hallo | nc -u 10.1.2.172 50001" to send something to the recieving pc interface to see if the link is up and see if the other nc console receives the hallo.
|
||||
|
||||
#. Detector is not acquiring (Not Eiger)
|
||||
* Take an acquisition with many images and using the following steps instead of acquire:
|
||||
@ -47,11 +49,20 @@ Common
|
||||
* Ensure that the interfaces (on NIC and the switch) used in receiver pc have MTU 9000 (jumbo frames) enabled.
|
||||
|
||||
|
||||
#. Check if 'rx_frames' counter in 'ifconfig' do not increment for interface.
|
||||
#. Check if 'rx packets' counter in 'ifconfig' do not increment for interface.
|
||||
* If no, check switch configuration if present. Port counters of switch can also help to identify problem.
|
||||
* If yes, but receiver software does not see it:
|
||||
|
||||
* Check no firewall (eg. firewalld) is present or add rules
|
||||
|
||||
.. code-block:: bash
|
||||
|
||||
# Stop and disable firewall
|
||||
service firewalld stop
|
||||
systemctl disable firewalld
|
||||
# Check status
|
||||
service firewalld status
|
||||
|
||||
* Check that selinux is disabled ( or add rules)
|
||||
|
||||
#. Source UDP IP in config file (Not Eiger)
|
||||
|
22
examples/rawdata.config
Normal file
22
examples/rawdata.config
Normal file
@ -0,0 +1,22 @@
|
||||
numfiles 1
|
||||
nthreads 5,
|
||||
fifosize 5000
|
||||
nsigma 5
|
||||
gainfile none
|
||||
detectorMode counting
|
||||
threshold 0
|
||||
pedestalfile none
|
||||
nframes 0
|
||||
xMin 0
|
||||
xMax 400
|
||||
yMin 0
|
||||
yMax 400
|
||||
outdir ./
|
||||
indir ./
|
||||
flist none
|
||||
fformat none
|
||||
runmin 0
|
||||
runmax -1
|
||||
readnrows 400
|
||||
eMin 0
|
||||
eMax 16000
|
16
examples/zmq.config
Normal file
16
examples/zmq.config
Normal file
@ -0,0 +1,16 @@
|
||||
numinterfaces 1
|
||||
rx_zmqip 10.1.2.102
|
||||
rx_zmqport 1978
|
||||
zmqip 129.129.202.57
|
||||
zmqport 1979
|
||||
nthreads 6
|
||||
fifosize 5000
|
||||
nsigma 5
|
||||
gainfile none
|
||||
nbinsx 5
|
||||
nbinsy 5
|
||||
etafile none
|
||||
etabinsx 1000
|
||||
etabinsy 1000
|
||||
etamin -1
|
||||
etamax 2
|
@ -316,7 +316,8 @@ struct GenericStringRef {
|
||||
|
||||
GenericStringRef(const GenericStringRef& rhs) : s(rhs.s), length(rhs.length) {}
|
||||
|
||||
GenericStringRef& operator=(const GenericStringRef& rhs) { s = rhs.s; length = rhs.length; }
|
||||
// Removed to fix failing build in GCC 14
|
||||
// GenericStringRef& operator=(const GenericStringRef& rhs) { s = rhs.s; length = rhs.length; }
|
||||
|
||||
//! implicit conversion to plain CharType pointer
|
||||
operator const Ch *() const { return s; }
|
||||
|
@ -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
|
726
pyctbgui/pyctbgui/utils/plotPattern.py
Executable file
726
pyctbgui/pyctbgui/utils/plotPattern.py
Executable file
@ -0,0 +1,726 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Created on Wed May 24 09:44:53 2017
|
||||
|
||||
Plot the pattern for New Chip Test Box (.pat)
|
||||
|
||||
Changes:
|
||||
- 2017-11-21 Adapt it to python-3
|
||||
- 2017-09-25 All can be plotted
|
||||
- 2017-09-22 Can be plotted but the loop and wait not work yet
|
||||
|
||||
@author: Jiaguo Zhang and Julian Heymes
|
||||
"""
|
||||
|
||||
import matplotlib.pyplot as plt
|
||||
import numpy as np
|
||||
from matplotlib.patches import Rectangle
|
||||
|
||||
|
||||
class PlotPattern:
|
||||
|
||||
def __init__(self, pattern, signalNames, colors_plot, colors_wait, linestyles_wait, alpha_wait, alpha_wait_rect,
|
||||
colors_loop, linestyles_loop, alpha_loop, alpha_loop_rect, clock_vertical_lines_spacing,
|
||||
show_clocks_number, line_width):
|
||||
self.pattern = pattern
|
||||
self.signalNames = signalNames
|
||||
self.verbose = False
|
||||
# TODO: send alias
|
||||
|
||||
self.colors_plot = colors_plot.copy()
|
||||
self.colors_wait = colors_wait.copy()
|
||||
self.linestyles_wait = linestyles_wait.copy()
|
||||
self.alpha_wait = alpha_wait.copy()
|
||||
self.alpha_wait_rect = alpha_wait_rect.copy()
|
||||
self.colors_loop = colors_loop.copy()
|
||||
self.linestyles_loop = linestyles_loop.copy()
|
||||
self.alpha_loop = alpha_loop.copy()
|
||||
self.alpha_loop_rect = alpha_loop_rect.copy()
|
||||
self.clock_vertical_lines_spacing = clock_vertical_lines_spacing
|
||||
self.show_clocks_number = show_clocks_number
|
||||
self.line_width = line_width
|
||||
|
||||
self.colors_plot[0] = f'xkcd:{colors_plot[0].lower()}'
|
||||
self.colors_plot[1] = f'xkcd:{colors_plot[1].lower()}'
|
||||
|
||||
for i in range(6):
|
||||
self.colors_wait[i] = f'xkcd:{colors_wait[i].lower()}'
|
||||
self.colors_loop[i] = f'xkcd:{colors_loop[i].lower()}'
|
||||
|
||||
if self.verbose:
|
||||
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 dec2binary(self, dec_num, width=None):
|
||||
return np.binary_repr(int(dec_num), width=width)
|
||||
|
||||
def hex2dec(self, string_num):
|
||||
return str(int(string_num.upper(), 16))
|
||||
|
||||
def hex2binary(self, string_num, width=None):
|
||||
return self.dec2binary(self.hex2dec(string_num.upper()), width=width)
|
||||
|
||||
def patternPlot(self):
|
||||
# Define a hex to binary function
|
||||
# global definition
|
||||
# base = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F]
|
||||
self.base = [str(x) for x in range(10)] + [chr(x) for x in range(ord('A'), ord('A') + 6)]
|
||||
|
||||
# Load the pattern and get all lines
|
||||
# Loop all lines
|
||||
# with open(Folder + "/" + File_pat + ".pat") as f_pat:
|
||||
with open(self.pattern) as f_pat:
|
||||
lines_pat = f_pat.readlines()
|
||||
|
||||
# number of lines for pattern file
|
||||
nlines_pat = len(lines_pat)
|
||||
# a counter
|
||||
cnt = 0
|
||||
if self.verbose:
|
||||
print("The total number of lines of pattern:", nlines_pat)
|
||||
|
||||
# Loop all lines of pattern
|
||||
waittime0 = None
|
||||
waittime1 = None
|
||||
waittime2 = None
|
||||
waittime3 = None
|
||||
waittime4 = None
|
||||
waittime5 = None
|
||||
|
||||
nloop0 = None
|
||||
nloop1 = None
|
||||
nloop2 = None
|
||||
nloop3 = None
|
||||
nloop4 = None
|
||||
nloop5 = None
|
||||
|
||||
for k in range(nlines_pat):
|
||||
# content of line
|
||||
words_line = lines_pat[k].split()
|
||||
if len(words_line) < 2:
|
||||
continue
|
||||
if words_line[0] == "patword":
|
||||
# print words_line from b0 to b63
|
||||
bits = self.hex2binary(words_line[-1], 64)[::-1]
|
||||
if self.verbose:
|
||||
print("The bits for line-", k + 1, "is:", bits)
|
||||
# convert string bits to decimal array
|
||||
num_bits = np.array(list(map(str, bits)), dtype="uint16")
|
||||
if cnt == 0:
|
||||
mat_pat = num_bits
|
||||
else:
|
||||
# add bits to matrix
|
||||
mat_pat = np.concatenate((mat_pat, num_bits), axis=0)
|
||||
cnt = cnt + 1
|
||||
# print("The matrix of pattern:", mat_pat.reshape(int(cnt), int(len(num_bits))))
|
||||
|
||||
# Look at the io: 0 for sending to ASIC, 1 for reading from ASIC
|
||||
if words_line[0] == "patioctrl":
|
||||
# print words_line
|
||||
if self.verbose:
|
||||
print(words_line[-1])
|
||||
bits = self.hex2binary(words_line[-1], 64)[::-1]
|
||||
if self.verbose:
|
||||
print(bits)
|
||||
# convert string bits to decimal array
|
||||
self.out_bits = np.array(list(map(str, bits)), dtype="uint16")
|
||||
|
||||
if self.verbose:
|
||||
print(words_line)
|
||||
# Deal with waiting point
|
||||
|
||||
# ====== WAIT ======
|
||||
if words_line[0] == "patwait" and words_line[1] == "0":
|
||||
wait0 = int(self.hex2dec(words_line[2]))
|
||||
if self.verbose:
|
||||
print("wait 0 at:", wait0)
|
||||
if words_line[0] == "patwaittime" and words_line[1] == "0":
|
||||
waittime0 = int(words_line[2])
|
||||
if self.verbose:
|
||||
print("wait 0 for:", waittime0)
|
||||
|
||||
if words_line[0] == "patwait" and words_line[1] == "1":
|
||||
wait1 = int(self.hex2dec(words_line[2]))
|
||||
if self.verbose:
|
||||
print("wait 1 at:", wait1)
|
||||
if words_line[0] == "patwaittime" and words_line[1] == "1":
|
||||
waittime1 = int(words_line[2])
|
||||
if self.verbose:
|
||||
print("wait 1 for:", waittime1)
|
||||
|
||||
if words_line[0] == "patwait" and words_line[1] == "2":
|
||||
wait2 = int(self.hex2dec(words_line[2]))
|
||||
if self.verbose:
|
||||
print("wait 2 at:", wait2)
|
||||
if words_line[0] == "patwaittime" and words_line[1] == "2":
|
||||
waittime2 = int(words_line[2])
|
||||
if self.verbose:
|
||||
print("wait 2 for:", waittime2)
|
||||
|
||||
if words_line[0] == "patwait" and words_line[1] == "3":
|
||||
wait3 = int(self.hex2dec(words_line[2]))
|
||||
if self.verbose:
|
||||
print("wait 0 at:", wait3)
|
||||
if words_line[0] == "patwaittime" and words_line[1] == "3":
|
||||
waittime3 = int(words_line[2])
|
||||
if self.verbose:
|
||||
print("wait 0 for:", waittime3)
|
||||
|
||||
if words_line[0] == "patwait" and words_line[1] == "4":
|
||||
wait4 = int(self.hex2dec(words_line[2]))
|
||||
if self.verbose:
|
||||
print("wait 1 at:", wait4)
|
||||
if words_line[0] == "patwaittime" and words_line[1] == "4":
|
||||
waittime4 = int(words_line[2])
|
||||
if self.verbose:
|
||||
print("wait 1 for:", waittime4)
|
||||
|
||||
if words_line[0] == "patwait" and words_line[1] == "5":
|
||||
wait5 = int(self.hex2dec(words_line[2]))
|
||||
if self.verbose:
|
||||
print("wait 2 at:", wait5)
|
||||
if words_line[0] == "patwaittime" and words_line[1] == "5":
|
||||
waittime5 = int(words_line[2])
|
||||
if self.verbose:
|
||||
print("wait 2 for:", waittime5)
|
||||
|
||||
# ====== LOOPS ======
|
||||
if words_line[0] == "patloop" and words_line[1] == "0":
|
||||
loop0_start = int(self.hex2dec(words_line[2]))
|
||||
loop0_end = int(self.hex2dec(words_line[3]))
|
||||
if self.verbose:
|
||||
print("loop 0 start:", loop0_start, ", end:", loop0_end)
|
||||
if words_line[0] == "patnloop" and words_line[1] == "0":
|
||||
nloop0 = int(words_line[2])
|
||||
if self.verbose:
|
||||
print("loop 0 times:", nloop0)
|
||||
|
||||
if words_line[0] == "patloop" and words_line[1] == "1":
|
||||
loop1_start = int(self.hex2dec(words_line[2]))
|
||||
loop1_end = int(self.hex2dec(words_line[3]))
|
||||
if self.verbose:
|
||||
print("loop 1 start:", loop1_start, ", end:", loop1_end)
|
||||
if words_line[0] == "patnloop" and words_line[1] == "1":
|
||||
nloop1 = int(words_line[2])
|
||||
if self.verbose:
|
||||
print("loop 1 times:", nloop1)
|
||||
|
||||
if words_line[0] == "patloop" and words_line[1] == "2":
|
||||
loop2_start = int(self.hex2dec(words_line[2]))
|
||||
loop2_end = int(self.hex2dec(words_line[3]))
|
||||
if self.verbose:
|
||||
print("loop 2 start:", loop2_start, ", end:", loop2_end)
|
||||
if words_line[0] == "patnloop" and words_line[1] == "2":
|
||||
nloop2 = int(words_line[2])
|
||||
if self.verbose:
|
||||
print("loop 2 times:", nloop2)
|
||||
|
||||
if words_line[0] == "patloop" and words_line[1] == "3":
|
||||
loop3_start = int(self.hex2dec(words_line[2]))
|
||||
loop3_end = int(self.hex2dec(words_line[3]))
|
||||
if self.verbose:
|
||||
print("loop 3 start:", loop3_start, ", end:", loop3_end)
|
||||
if words_line[0] == "patnloop" and words_line[1] == "3":
|
||||
nloop3 = int(words_line[2])
|
||||
if self.verbose:
|
||||
print("loop 3 times:", nloop3)
|
||||
|
||||
if words_line[0] == "patloop" and words_line[1] == "4":
|
||||
loop4_start = int(self.hex2dec(words_line[2]))
|
||||
loop4_end = int(self.hex2dec(words_line[3]))
|
||||
if self.verbose:
|
||||
print("loop 4 start:", loop4_start, ", end:", loop4_end)
|
||||
if words_line[0] == "patnloop" and words_line[1] == "4":
|
||||
nloop4 = int(words_line[2])
|
||||
if self.verbose:
|
||||
print("loop 4 times:", nloop4)
|
||||
|
||||
if words_line[0] == "patloop" and words_line[1] == "5":
|
||||
loop5_start = int(self.hex2dec(words_line[2]))
|
||||
loop5_end = int(self.hex2dec(words_line[3]))
|
||||
if self.verbose:
|
||||
print("loop 5 start:", loop5_start, ", end:", loop5_end)
|
||||
if words_line[0] == "patnloop" and words_line[1] == "5":
|
||||
nloop5 = int(words_line[2])
|
||||
if self.verbose:
|
||||
print("loop 5 times:", nloop5)
|
||||
|
||||
# no patioctrl commands read
|
||||
if not hasattr(self, 'out_bits'):
|
||||
raise Exception("No patioctrl command found in pattern file")
|
||||
# print(self.out_bits)
|
||||
|
||||
# internal counter
|
||||
avail_index = []
|
||||
avail_name = []
|
||||
# Remove non-used bits
|
||||
for i in range(64):
|
||||
# if self.out_bits[0][i] == 1:
|
||||
if self.out_bits[i] == 1:
|
||||
avail_index.append(i)
|
||||
avail_name.append(self.signalNames[i])
|
||||
if self.verbose:
|
||||
print(avail_index)
|
||||
print(avail_name)
|
||||
|
||||
# number of effective used bits
|
||||
nbiteff = len(avail_name)
|
||||
|
||||
# subMat = mat_ext[:,index]
|
||||
# print(mat_pat.shape)
|
||||
subMat = mat_pat.reshape(int(cnt), int(len(num_bits)))[0:, avail_index]
|
||||
# subMat = mat_pat[avail_index]
|
||||
# timing = np.linspace(0, subMat.shape[0] - 1, subMat.shape[0])
|
||||
plt.rcParams['figure.figsize'] = 15, 5
|
||||
|
||||
# ============= PLOTTING =============
|
||||
|
||||
plt.rcParams["font.weight"] = "bold"
|
||||
plt.rcParams["axes.labelweight"] = "bold"
|
||||
fig, axs = plt.subplots(nbiteff, sharex='all')
|
||||
plt.subplots_adjust(wspace=0, hspace=0)
|
||||
# axs[nbiteff - 1].set(xlabel='Timing [clk]')
|
||||
for idx, i in enumerate(range(nbiteff)):
|
||||
axs[idx].tick_params(axis='x', labelsize=6)
|
||||
|
||||
axs[idx].plot(subMat.T[i],
|
||||
"-",
|
||||
drawstyle="steps-post",
|
||||
linewidth=self.line_width,
|
||||
color=self.colors_plot[idx % 2])
|
||||
x_additional = range(len(subMat.T[i]) - 1, len(subMat.T[i]) + 2)
|
||||
additional_stuff = [subMat.T[i][-1]] * 3
|
||||
|
||||
axs[idx].plot(x_additional,
|
||||
additional_stuff,
|
||||
"--",
|
||||
drawstyle="steps-post",
|
||||
linewidth=self.line_width,
|
||||
color=self.colors_plot[idx % 2],
|
||||
alpha=0.5)
|
||||
axs[idx].yaxis.set_ticks([0.5], minor=False)
|
||||
axs[idx].xaxis.set_ticks(np.arange(0, len(subMat.T[i]) + 10, self.clock_vertical_lines_spacing))
|
||||
|
||||
axs[idx].yaxis.set_ticklabels([avail_name[i]])
|
||||
axs[idx].get_yticklabels()[0].set_color(self.colors_plot[idx % 2])
|
||||
|
||||
axs[idx].grid(1, 'both', 'both', alpha=0.5)
|
||||
axs[idx].yaxis.grid(which="both", color=self.colors_plot[idx % 2], alpha=0.2)
|
||||
if idx != nbiteff - 1:
|
||||
if not self.show_clocks_number:
|
||||
axs[idx].xaxis.set_ticklabels([])
|
||||
axs[idx].set(xlabel=' ', ylim=(-0.2, 1.2))
|
||||
else:
|
||||
axs[idx].set(xlabel='Timing [clk]', ylim=(-0.2, 1.2))
|
||||
# axs[idx].set_xlim(left=0)
|
||||
axs[idx].set_xlim(left=0, right=len(subMat.T[i]) + 1)
|
||||
axs[idx].spines['top'].set_visible(False)
|
||||
axs[idx].spines['right'].set_alpha(0.2)
|
||||
axs[idx].spines['right'].set_visible(True)
|
||||
axs[idx].spines['bottom'].set_visible(False)
|
||||
axs[idx].spines['left'].set_visible(False)
|
||||
|
||||
# =====================================================================================================
|
||||
# Plot the wait lines
|
||||
# Wait 0
|
||||
if waittime0 is not None:
|
||||
if waittime0 == 0:
|
||||
axs[idx].plot([wait0, wait0], [-10, 10],
|
||||
linestyle=self.linestyles_wait[0],
|
||||
color=self.colors_wait[0],
|
||||
alpha=self.alpha_wait[0],
|
||||
linewidth=self.line_width)
|
||||
axs[idx].plot([wait0 + 1, wait0 + 1], [-10, 10],
|
||||
linestyle=self.linestyles_wait[0],
|
||||
color=self.colors_wait[0],
|
||||
linewidth=self.line_width,
|
||||
alpha=self.alpha_wait[0])
|
||||
axs[idx].add_patch(
|
||||
Rectangle((wait0, -10),
|
||||
1,
|
||||
20,
|
||||
label="wait 0: skipped" if idx == 0 else "",
|
||||
facecolor=self.colors_wait[0],
|
||||
alpha=self.alpha_wait_rect[0],
|
||||
hatch='\\\\'))
|
||||
else:
|
||||
axs[idx].plot([wait0, wait0], [-10, 10],
|
||||
linestyle=self.linestyles_wait[0],
|
||||
color=self.colors_wait[0],
|
||||
label="wait 0: " + str(waittime0) + " clk" if idx == 0 else "",
|
||||
linewidth=self.line_width,
|
||||
alpha=self.alpha_wait[0])
|
||||
|
||||
# Wait 1
|
||||
if waittime1 is not None:
|
||||
if waittime1 == 0:
|
||||
axs[idx].plot([wait1, wait1], [-10, 10],
|
||||
linestyle=self.linestyles_wait[1],
|
||||
color=self.colors_wait[1],
|
||||
alpha=self.alpha_wait[1],
|
||||
linewidth=self.line_width)
|
||||
axs[idx].plot([wait1 + 1, wait1 + 1], [-10, 10],
|
||||
linestyle=self.linestyles_wait[1],
|
||||
color=self.colors_wait[1],
|
||||
linewidth=self.line_width,
|
||||
alpha=self.alpha_wait[1])
|
||||
axs[idx].add_patch(
|
||||
Rectangle((wait1, -10),
|
||||
1,
|
||||
20,
|
||||
label="wait 1: skipped" if idx == 0 else "",
|
||||
facecolor=self.colors_wait[1],
|
||||
alpha=self.alpha_wait_rect[1],
|
||||
hatch='\\\\'))
|
||||
else:
|
||||
axs[idx].plot([wait1, wait1], [-10, 10],
|
||||
linestyle=self.linestyles_wait[1],
|
||||
color=self.colors_wait[1],
|
||||
label="wait 1: " + str(waittime1) + " clk" if idx == 0 else "",
|
||||
linewidth=self.line_width,
|
||||
alpha=self.alpha_wait[1])
|
||||
|
||||
# Wait 2
|
||||
if waittime2 is not None:
|
||||
if waittime2 == 0:
|
||||
axs[idx].plot([wait2, wait2], [-10, 10],
|
||||
linestyle=self.linestyles_wait[2],
|
||||
color=self.colors_wait[2],
|
||||
alpha=self.alpha_wait[2],
|
||||
linewidth=self.line_width)
|
||||
axs[idx].plot([wait2 + 1, wait2 + 1], [-10, 10],
|
||||
linestyle=self.linestyles_wait[2],
|
||||
color=self.colors_wait[2],
|
||||
linewidth=self.line_width,
|
||||
alpha=self.alpha_wait[2])
|
||||
axs[idx].add_patch(
|
||||
Rectangle((wait2, -10),
|
||||
1,
|
||||
20,
|
||||
label="wait 2: skipped" if idx == 0 else "",
|
||||
facecolor=self.colors_wait[2],
|
||||
alpha=self.alpha_wait_rect[2],
|
||||
hatch='\\\\'))
|
||||
else:
|
||||
axs[idx].plot([wait2, wait2], [-10, 10],
|
||||
linestyle=self.linestyles_wait[2],
|
||||
color=self.colors_wait[2],
|
||||
label="wait 2: " + str(waittime2) + " clk" if idx == 0 else "",
|
||||
linewidth=self.line_width,
|
||||
alpha=self.alpha_wait[2])
|
||||
|
||||
# Wait 3
|
||||
if waittime3 is not None:
|
||||
if waittime3 == 0:
|
||||
axs[idx].plot([wait3, wait3], [-10, 10],
|
||||
linestyle=self.linestyles_wait[3],
|
||||
color=self.colors_wait[3],
|
||||
alpha=self.alpha_wait[3],
|
||||
linewidth=self.line_width)
|
||||
axs[idx].plot([wait3 + 1, wait3 + 1], [-10, 10],
|
||||
linestyle=self.linestyles_wait[3],
|
||||
color=self.colors_wait[3],
|
||||
linewidth=self.line_width,
|
||||
alpha=self.alpha_wait[3])
|
||||
axs[idx].add_patch(
|
||||
Rectangle((wait3, -10),
|
||||
1,
|
||||
20,
|
||||
label="wait 3: skipped" if idx == 0 else "",
|
||||
facecolor=self.colors_wait[3],
|
||||
alpha=self.alpha_wait_rect[3],
|
||||
hatch='\\\\'))
|
||||
else:
|
||||
axs[idx].plot([wait3, wait3], [-10, 10],
|
||||
linestyle=self.linestyles_wait[3],
|
||||
color=self.colors_wait[3],
|
||||
label="wait 3: " + str(waittime3) + " clk" if idx == 0 else "",
|
||||
linewidth=self.line_width,
|
||||
alpha=self.alpha_wait[3])
|
||||
|
||||
# Wait 4
|
||||
if waittime4 is not None:
|
||||
if waittime4 == 0:
|
||||
axs[idx].plot([wait4, wait4], [-10, 10],
|
||||
linestyle=self.linestyles_wait[4],
|
||||
color=self.colors_wait[4],
|
||||
alpha=self.alpha_wait[4],
|
||||
linewidth=self.line_width)
|
||||
axs[idx].plot([wait4 + 1, wait4 + 1], [-10, 10],
|
||||
linestyle=self.linestyles_wait[4],
|
||||
color=self.colors_wait[4],
|
||||
linewidth=self.line_width,
|
||||
alpha=self.alpha_wait[4])
|
||||
axs[idx].add_patch(
|
||||
Rectangle((wait4, -10),
|
||||
1,
|
||||
20,
|
||||
label="wait 4: skipped" if idx == 0 else "",
|
||||
facecolor=self.colors_wait[4],
|
||||
alpha=self.alpha_wait_rect[4],
|
||||
hatch='\\\\'))
|
||||
else:
|
||||
axs[idx].plot([wait4, wait4], [-10, 10],
|
||||
linestyle=self.linestyles_wait[4],
|
||||
color=self.colors_wait[4],
|
||||
label="wait 4: " + str(waittime4) + " clk" if idx == 0 else "",
|
||||
linewidth=self.line_width,
|
||||
alpha=self.alpha_wait[4])
|
||||
|
||||
# Wait 5
|
||||
if waittime5 is not None:
|
||||
if waittime5 == 0:
|
||||
axs[idx].plot([wait5, wait5], [-10, 10],
|
||||
linestyle=self.linestyles_wait[5],
|
||||
color=self.colors_wait[5],
|
||||
alpha=self.alpha_wait[5],
|
||||
linewidth=self.line_width)
|
||||
axs[idx].plot([wait5 + 1, wait5 + 1], [-10, 10],
|
||||
linestyle=self.linestyles_wait[5],
|
||||
color=self.colors_wait[5],
|
||||
linewidth=self.line_width,
|
||||
alpha=self.alpha_wait[5])
|
||||
axs[idx].add_patch(
|
||||
Rectangle((wait5, -10),
|
||||
1,
|
||||
20,
|
||||
label="wait 5: skipped" if idx == 0 else "",
|
||||
facecolor=self.colors_wait[5],
|
||||
alpha=self.alpha_wait_rect[5],
|
||||
hatch='\\\\'))
|
||||
else:
|
||||
axs[idx].plot([wait5, wait5], [-10, 10],
|
||||
linestyle=self.linestyles_wait[5],
|
||||
color=self.colors_wait[5],
|
||||
label="wait 5: " + str(waittime5) + " clk" if idx == 0 else "",
|
||||
linewidth=self.line_width,
|
||||
alpha=self.alpha_wait[5])
|
||||
|
||||
# =====================================================================================================
|
||||
# Plot the loop lines
|
||||
# Loop 0
|
||||
if nloop0 is not None:
|
||||
if nloop0 == 0:
|
||||
axs[idx].plot([loop0_start, loop0_start], [-10, 10],
|
||||
linestyle=self.linestyles_loop[0],
|
||||
color=self.colors_loop[0],
|
||||
alpha=self.alpha_loop[0],
|
||||
linewidth=self.line_width)
|
||||
axs[idx].plot([loop0_end + 1, loop0_end + 1], [-10, 10],
|
||||
linestyle=self.linestyles_loop[0],
|
||||
color=self.colors_loop[0],
|
||||
alpha=self.alpha_loop[0],
|
||||
linewidth=self.line_width)
|
||||
axs[idx].add_patch(
|
||||
Rectangle((loop0_start, -10),
|
||||
loop0_end + 1 - loop0_start,
|
||||
20,
|
||||
label="loop 0: skipped" if idx == 0 else "",
|
||||
facecolor=self.colors_loop[0],
|
||||
alpha=self.alpha_loop_rect[0],
|
||||
hatch='//'))
|
||||
else:
|
||||
axs[idx].plot([loop0_start, loop0_start], [-10, 10],
|
||||
linestyle=self.linestyles_loop[0],
|
||||
color=self.colors_loop[0],
|
||||
alpha=self.alpha_loop[0],
|
||||
label="loop 0: " + str(nloop0) + " times" if idx == 0 else "",
|
||||
linewidth=self.line_width)
|
||||
axs[idx].plot([loop0_end, loop0_end], [-10, 10],
|
||||
linestyle=self.linestyles_loop[0],
|
||||
color=self.colors_loop[0],
|
||||
alpha=self.alpha_loop[0],
|
||||
linewidth=self.line_width)
|
||||
|
||||
# Loop 1
|
||||
if nloop1 is not None:
|
||||
if nloop1 == 0:
|
||||
axs[idx].plot([loop1_start, loop1_start], [-10, 10],
|
||||
linestyle=self.linestyles_loop[1],
|
||||
color=self.colors_loop[1],
|
||||
alpha=self.alpha_loop[1],
|
||||
linewidth=self.line_width)
|
||||
axs[idx].plot([loop1_end + 1, loop1_end + 1], [-10, 10],
|
||||
linestyle=self.linestyles_loop[1],
|
||||
color=self.colors_loop[1],
|
||||
alpha=self.alpha_loop[1],
|
||||
linewidth=self.line_width)
|
||||
axs[idx].add_patch(
|
||||
Rectangle((loop1_start, -10),
|
||||
loop1_end + 1 - loop1_start,
|
||||
20,
|
||||
label="loop 1: skipped" if idx == 0 else "",
|
||||
facecolor=self.colors_loop[1],
|
||||
alpha=self.alpha_loop_rect[1],
|
||||
hatch='//'))
|
||||
else:
|
||||
axs[idx].plot([loop1_start, loop1_start], [-10, 10],
|
||||
linestyle=self.linestyles_loop[1],
|
||||
color=self.colors_loop[1],
|
||||
alpha=self.alpha_loop[1],
|
||||
label="loop 1: " + str(nloop1) + " times" if idx == 0 else "",
|
||||
linewidth=self.line_width)
|
||||
axs[idx].plot([loop1_end, loop1_end], [-10, 10],
|
||||
linestyle=self.linestyles_loop[1],
|
||||
color=self.colors_loop[1],
|
||||
alpha=self.alpha_loop[1],
|
||||
linewidth=self.line_width)
|
||||
|
||||
# Loop 2
|
||||
if nloop2 is not None:
|
||||
if nloop2 == 0:
|
||||
axs[idx].plot([loop2_start, loop2_start], [-10, 10],
|
||||
linestyle=self.linestyles_loop[2],
|
||||
color=self.colors_loop[2],
|
||||
alpha=self.alpha_loop[2],
|
||||
linewidth=self.line_width)
|
||||
axs[idx].plot([loop2_end + 1, loop2_end + 1], [-10, 10],
|
||||
linestyle=self.linestyles_loop[2],
|
||||
color=self.colors_loop[2],
|
||||
alpha=self.alpha_loop[2],
|
||||
linewidth=self.line_width)
|
||||
axs[idx].add_patch(
|
||||
Rectangle((loop2_start, -10),
|
||||
loop2_end + 1 - loop2_start,
|
||||
20,
|
||||
label="loop 2: skipped" if idx == 0 else "",
|
||||
facecolor=self.colors_loop[2],
|
||||
alpha=self.alpha_loop_rect[2],
|
||||
hatch='//'))
|
||||
else:
|
||||
axs[idx].plot([loop2_start, loop2_start], [-10, 10],
|
||||
linestyle=self.linestyles_loop[2],
|
||||
color=self.colors_loop[2],
|
||||
alpha=self.alpha_loop[2],
|
||||
label="loop 2: " + str(nloop2) + " times" if idx == 0 else "",
|
||||
linewidth=self.line_width)
|
||||
axs[idx].plot([loop2_end, loop2_end], [-10, 10],
|
||||
linestyle=self.linestyles_loop[2],
|
||||
color=self.colors_loop[2],
|
||||
alpha=self.alpha_loop[2],
|
||||
linewidth=self.line_width)
|
||||
|
||||
# Loop 3
|
||||
if nloop3 is not None:
|
||||
if nloop3 == 0:
|
||||
axs[idx].plot([loop3_start, loop3_start], [-10, 10],
|
||||
linestyle=self.linestyles_loop[3],
|
||||
color=self.colors_loop[3],
|
||||
alpha=self.alpha_loop[3],
|
||||
linewidth=self.line_width)
|
||||
axs[idx].plot([loop3_end + 1, loop3_end + 1], [-10, 10],
|
||||
linestyle=self.linestyles_loop[3],
|
||||
color=self.colors_loop[3],
|
||||
alpha=self.alpha_loop[3],
|
||||
linewidth=self.line_width)
|
||||
axs[idx].add_patch(
|
||||
Rectangle((loop3_start, -10),
|
||||
loop3_end + 1 - loop3_start,
|
||||
20,
|
||||
label="loop 3: skipped" if idx == 0 else "",
|
||||
facecolor=self.colors_loop[3],
|
||||
alpha=self.alpha_loop_rect[3],
|
||||
hatch='//'))
|
||||
else:
|
||||
axs[idx].plot([loop3_start, loop3_start], [-10, 10],
|
||||
linestyle=self.linestyles_loop[3],
|
||||
color=self.colors_loop[3],
|
||||
alpha=self.alpha_loop[3],
|
||||
label="loop 3: " + str(nloop3) + " times" if idx == 0 else "",
|
||||
linewidth=self.line_width)
|
||||
axs[idx].plot([loop3_end, loop3_end], [-10, 10],
|
||||
linestyle=self.linestyles_loop[3],
|
||||
color=self.colors_loop[3],
|
||||
alpha=self.alpha_loop[3],
|
||||
linewidth=self.line_width)
|
||||
|
||||
# Loop 4
|
||||
if nloop4 is not None:
|
||||
if nloop4 == 0:
|
||||
axs[idx].plot([loop4_start, loop4_start], [-10, 10],
|
||||
linestyle=self.linestyles_loop[4],
|
||||
color=self.colors_loop[4],
|
||||
alpha=self.alpha_loop[4],
|
||||
linewidth=self.line_width)
|
||||
axs[idx].plot([loop4_end + 1, loop4_end + 1], [-10, 10],
|
||||
linestyle=self.linestyles_loop[4],
|
||||
color=self.colors_loop[4],
|
||||
alpha=self.alpha_loop[4],
|
||||
linewidth=self.line_width)
|
||||
axs[idx].add_patch(
|
||||
Rectangle((loop4_start, -10),
|
||||
loop4_end + 1 - loop4_start,
|
||||
20,
|
||||
label="loop 4: skipped" if idx == 0 else "",
|
||||
facecolor=self.colors_loop[4],
|
||||
alpha=self.alpha_loop_rect[4],
|
||||
hatch='//'))
|
||||
else:
|
||||
axs[idx].plot([loop4_start, loop4_start], [-10, 10],
|
||||
linestyle=self.linestyles_loop[4],
|
||||
color=self.colors_loop[4],
|
||||
alpha=self.alpha_loop[4],
|
||||
label="loop 4: " + str(nloop4) + " times" if idx == 0 else "",
|
||||
linewidth=self.line_width)
|
||||
axs[idx].plot([loop4_end, loop4_end], [-10, 10],
|
||||
linestyle=self.linestyles_loop[4],
|
||||
color=self.colors_loop[4],
|
||||
alpha=self.alpha_loop[4],
|
||||
linewidth=self.line_width)
|
||||
|
||||
# Loop 5
|
||||
if nloop5 is not None:
|
||||
if nloop5 == 0:
|
||||
axs[idx].plot([loop5_start, loop5_start], [-10, 10],
|
||||
linestyle=self.linestyles_loop[5],
|
||||
color=self.colors_loop[5],
|
||||
alpha=self.alpha_loop[5],
|
||||
linewidth=self.line_width)
|
||||
axs[idx].plot([loop5_end + 1, loop5_end + 1], [-10, 10],
|
||||
linestyle=self.linestyles_loop[5],
|
||||
color=self.colors_loop[5],
|
||||
alpha=self.alpha_loop[5],
|
||||
linewidth=self.line_width)
|
||||
axs[idx].add_patch(
|
||||
Rectangle((loop5_start, -10),
|
||||
loop5_end + 1 - loop5_start,
|
||||
20,
|
||||
label="loop 5: skipped" if idx == 0 else "",
|
||||
facecolor=self.colors_loop[5],
|
||||
alpha=self.alpha_loop_rect[5],
|
||||
hatch='//'))
|
||||
else:
|
||||
axs[idx].plot([loop5_start, loop5_start], [-10, 10],
|
||||
linestyle=self.linestyles_loop[5],
|
||||
color=self.colors_loop[5],
|
||||
alpha=self.alpha_loop[5],
|
||||
label="loop 5: " + str(nloop5) + " times" if idx == 0 else "",
|
||||
linewidth=self.line_width)
|
||||
axs[idx].plot([loop5_end, loop5_end], [-10, 10],
|
||||
linestyle=self.linestyles_loop[5],
|
||||
color=self.colors_loop[5],
|
||||
alpha=self.alpha_loop[5],
|
||||
linewidth=self.line_width)
|
||||
|
||||
n_cols = np.count_nonzero([
|
||||
waittime0 != 0, waittime1 != 0, waittime2 != 0, waittime3 != 0, waittime4 != 0, waittime5 != 0, nloop0
|
||||
!= 0, nloop1 != 0, nloop2 != 0, nloop3 != 0, nloop4 != 0, nloop5 != 0
|
||||
])
|
||||
if n_cols > 0:
|
||||
fig.legend(loc="upper center", ncol=n_cols)
|
||||
return fig
|
100
pyctbgui/pyctbgui/utils/recordOrApplyPedestal.py
Normal file
100
pyctbgui/pyctbgui/utils/recordOrApplyPedestal.py
Normal file
@ -0,0 +1,100 @@
|
||||
import logging
|
||||
from pathlib import Path
|
||||
|
||||
import numpy as np
|
||||
|
||||
__frameCount = 0
|
||||
__pedestalSum = np.array(0, np.float64)
|
||||
__pedestal = np.array(0, np.float32)
|
||||
__loadedPedestal = False
|
||||
|
||||
|
||||
def reset(plotTab):
|
||||
global __frameCount, __pedestalSum, __pedestal, __loadedPedestal
|
||||
__frameCount = 0
|
||||
__pedestalSum = np.array(0, np.float64)
|
||||
__pedestal = np.array(0, np.float64)
|
||||
__loadedPedestal = False
|
||||
|
||||
plotTab.updateLabelPedestalFrames()
|
||||
|
||||
|
||||
def getFramesCount():
|
||||
return __frameCount
|
||||
|
||||
|
||||
def getPedestal():
|
||||
return __pedestal
|
||||
|
||||
|
||||
def calculatePedestal():
|
||||
global __pedestalSum, __pedestal
|
||||
if __loadedPedestal:
|
||||
return __pedestal
|
||||
if __frameCount == 0:
|
||||
__pedestal = np.array(0, np.float64)
|
||||
else:
|
||||
__pedestal = __pedestalSum / __frameCount
|
||||
return __pedestal
|
||||
|
||||
|
||||
def savePedestal(path=Path('/tmp/pedestal')):
|
||||
pedestal = calculatePedestal()
|
||||
np.save(path, pedestal)
|
||||
|
||||
|
||||
def loadPedestal(path: Path):
|
||||
global __pedestal, __loadedPedestal
|
||||
__loadedPedestal = True
|
||||
__pedestal = np.load(path)
|
||||
|
||||
|
||||
__logger = logging.getLogger('recordOrApplyPedestal')
|
||||
|
||||
|
||||
def recordOrApplyPedestal(func):
|
||||
"""
|
||||
decorator function used to apply pedestal functionalities
|
||||
@param func: processing function that needs to be wrapped
|
||||
@return: wrapper function to be called
|
||||
"""
|
||||
|
||||
def wrapper(obj, *args, **kwargs):
|
||||
"""
|
||||
wrapeer that calls func (a raw data _processing function) and calculates or applies a pedestal to it
|
||||
@param obj: reference to func's class instance (self of its class)
|
||||
@return: if record mode: return frame untouched, if apply mode: return frame - pedestal
|
||||
"""
|
||||
global __frameCount, __pedestal, __pedestalSum
|
||||
|
||||
frame = func(obj, *args, **kwargs)
|
||||
if not np.array_equal(0, __pedestalSum) and __pedestalSum.shape != frame.shape:
|
||||
# check if __pedestalSum has same different shape as the frame
|
||||
__logger.info('pedestal shape mismatch. resetting pedestal...')
|
||||
reset(obj.plotTab)
|
||||
|
||||
if obj.plotTab.pedestalRecord:
|
||||
if __loadedPedestal:
|
||||
# reset loaded pedestal if we acquire in record mode
|
||||
__logger.warning('resetting loaded pedestal...')
|
||||
reset(obj.plotTab)
|
||||
__frameCount += 1
|
||||
|
||||
__pedestalSum = np.add(__pedestalSum, frame, dtype=np.float64)
|
||||
|
||||
obj.plotTab.updateLabelPedestalFrames()
|
||||
return frame
|
||||
if obj.plotTab.pedestalApply:
|
||||
# apply pedestal
|
||||
# check if pedestal is calculated
|
||||
if __loadedPedestal and frame.shape != __pedestal.shape:
|
||||
__logger.warning('pedestal shape mismatch. resetting pedestal...')
|
||||
obj.plotTab.mainWindow.statusbar.setStyleSheet("color:red")
|
||||
obj.plotTab.mainWindow.statusbar.showMessage('pedestal shape mismatch. resetting pedestal...')
|
||||
reset(obj.plotTab)
|
||||
|
||||
return frame - calculatePedestal()
|
||||
|
||||
return frame
|
||||
|
||||
return wrapper
|
55
pyctbgui/pyproject.toml
Normal file
55
pyctbgui/pyproject.toml
Normal file
@ -0,0 +1,55 @@
|
||||
[build-system]
|
||||
requires = ["setuptools", "numpy"]
|
||||
build-backend = "setuptools.build_meta"
|
||||
|
||||
[tool.ruff]
|
||||
line-length = 119
|
||||
select = ["E","F","UP","PT","RET","SLF","TID","PTH","NPY"]
|
||||
# other usefule rules "N" "PL"
|
||||
# rules to ignore
|
||||
# PTH123 causes issues with gh actions
|
||||
ignore = ["UP032","PTH123"]
|
||||
|
||||
# Exclude a variety of commonly ignored directories.
|
||||
exclude = [
|
||||
".bzr",
|
||||
".direnv",
|
||||
".eggs",
|
||||
".git",
|
||||
".git-rewrite",
|
||||
".hg",
|
||||
".mypy_cache",
|
||||
".nox",
|
||||
".pants.d",
|
||||
".pytype",
|
||||
".ruff_cache",
|
||||
".svn",
|
||||
".tox",
|
||||
".venv",
|
||||
"__pypackages__",
|
||||
"_build",
|
||||
"buck-out",
|
||||
"build",
|
||||
"dist",
|
||||
"node_modules",
|
||||
"venv",
|
||||
]
|
||||
|
||||
target-version = "py311"
|
||||
|
||||
[tool.ruff.per-file-ignores]
|
||||
"__init__.py" = ["F401"]
|
||||
"pyctbgui/utils/decoder.py" = ["F403"]
|
||||
|
||||
|
||||
[tool.yapf]
|
||||
based_on_style = "pep8"
|
||||
COLUMN_LIMIT = 119
|
||||
|
||||
[tool.coverage.run]
|
||||
branch = false
|
||||
|
||||
[tool.coverage.report]
|
||||
include = [
|
||||
"pyctbgui/*"
|
||||
]
|
44
pyctbgui/setup.py
Normal file
44
pyctbgui/setup.py
Normal file
@ -0,0 +1,44 @@
|
||||
import setuptools
|
||||
import numpy as np
|
||||
|
||||
c_ext = setuptools.Extension("pyctbgui._decoder",
|
||||
sources=["src/decoder.c", "src/pm_decode.c"],
|
||||
include_dirs=[
|
||||
np.get_include(),
|
||||
"src/",
|
||||
],
|
||||
extra_compile_args=['-std=c99', '-Wall', '-Wextra'])
|
||||
|
||||
c_ext.language = 'c'
|
||||
setuptools.setup(
|
||||
name='pyctbgui',
|
||||
version='2023.8.17',
|
||||
description='Experimental GUI for the chip test board',
|
||||
packages=setuptools.find_packages(exclude=[
|
||||
'tests',
|
||||
]),
|
||||
include_package_data=True,
|
||||
ext_modules=[c_ext],
|
||||
scripts=[
|
||||
'CtbGui',
|
||||
],
|
||||
python_requires='>=3.10', # using match statement
|
||||
install_requires=[
|
||||
'numpy',
|
||||
'pyzmq',
|
||||
'pillow',
|
||||
'PyQt5',
|
||||
'pyqtgraph',
|
||||
'matplotlib',
|
||||
# 'slsdet', not yet available on pypi, maybe v8
|
||||
],
|
||||
extras_require={
|
||||
'dev': [
|
||||
'pytest==7.4.0',
|
||||
'ruff==0.0.285',
|
||||
'yapf==0.40.1',
|
||||
'pytest-ruff==0.1.1',
|
||||
'pre-commit',
|
||||
'pytest-qt',
|
||||
],
|
||||
})
|
177
pyctbgui/src/decoder.c
Normal file
177
pyctbgui/src/decoder.c
Normal file
@ -0,0 +1,177 @@
|
||||
#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION
|
||||
#define PY_SSIZE_T_CLEAN
|
||||
#include <Python.h>
|
||||
#include <numpy/arrayobject.h>
|
||||
|
||||
#include <pthread.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "pm_decode.h"
|
||||
#include "thread_utils.h"
|
||||
|
||||
/*Decode various types of CTB data using a pixel map. Works on single frames and
|
||||
on stacks of frames*/
|
||||
static PyObject *decode(PyObject *Py_UNUSED(self), PyObject *args,
|
||||
PyObject *kwds) {
|
||||
// Function arguments to be parsed
|
||||
PyObject *raw_data_obj = NULL;
|
||||
PyObject *data_obj = NULL;
|
||||
PyObject *pm_obj = NULL;
|
||||
size_t n_threads = 1;
|
||||
|
||||
static char *kwlist[] = {"raw_data", "pixel_map", "out", "n_threads", NULL};
|
||||
if (!PyArg_ParseTupleAndKeywords(args, kwds, "OO|On", kwlist, &raw_data_obj,
|
||||
&pm_obj, &data_obj, &n_threads)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Create a handle to the numpy array from the generic python object
|
||||
PyObject *raw_data = PyArray_FROM_OTF(
|
||||
raw_data_obj, NPY_UINT16,
|
||||
NPY_ARRAY_C_CONTIGUOUS | NPY_ARRAY_ENSUREARRAY | NPY_ARRAY_ALIGNED);
|
||||
if (!raw_data) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// Handle to the pixel map
|
||||
PyObject *pixel_map = PyArray_FROM_OTF(
|
||||
pm_obj, NPY_UINT32, NPY_ARRAY_C_CONTIGUOUS); // Make 64bit?
|
||||
if (!pixel_map) {
|
||||
return NULL;
|
||||
}
|
||||
if (PyArray_NDIM((PyArrayObject *)pixel_map) != 2) {
|
||||
PyErr_SetString(PyExc_TypeError, "The pixel map needs to be 2D");
|
||||
return NULL;
|
||||
}
|
||||
npy_intp n_rows = PyArray_DIM((PyArrayObject *)pixel_map, 0);
|
||||
npy_intp n_cols = PyArray_DIM((PyArrayObject *)pixel_map, 1);
|
||||
|
||||
// If called with an output array get an handle to it, otherwise allocate
|
||||
// the output array
|
||||
PyObject *data_out = NULL;
|
||||
if (data_obj) {
|
||||
data_out =
|
||||
PyArray_FROM_OTF(data_obj, NPY_UINT16, NPY_ARRAY_C_CONTIGUOUS);
|
||||
} else {
|
||||
int ndim = PyArray_NDIM((PyArrayObject *)raw_data) + 1;
|
||||
npy_intp dims_arr[3] = {PyArray_DIM((PyArrayObject *)raw_data, 0),
|
||||
n_rows, n_cols};
|
||||
npy_intp *dims = NULL;
|
||||
if (ndim == 2)
|
||||
dims = &dims_arr[1];
|
||||
else
|
||||
dims = &dims_arr[0];
|
||||
// Allocate output array
|
||||
data_out = PyArray_SimpleNew(ndim, dims, NPY_UINT16);
|
||||
}
|
||||
|
||||
// Check that raw_data has one less dimension than frame
|
||||
// eg raw_data[n_frames, pixels] frame[nframes, nrows, ncols]
|
||||
// raw data is an array of values and data_out is 2/3D
|
||||
int rd_dim = PyArray_NDIM((PyArrayObject *)raw_data);
|
||||
int f_dim = PyArray_NDIM((PyArrayObject *)data_out);
|
||||
|
||||
if (rd_dim != (f_dim - 1)) {
|
||||
PyErr_SetString(
|
||||
PyExc_TypeError,
|
||||
"Raw data and data needs to have the one less dim"); // eg -1
|
||||
return NULL;
|
||||
}
|
||||
|
||||
uint16_t *src = (uint16_t *)PyArray_DATA((PyArrayObject *)raw_data);
|
||||
uint16_t *dst = (uint16_t *)PyArray_DATA((PyArrayObject *)data_out);
|
||||
uint32_t *pm = (uint32_t *)PyArray_DATA((PyArrayObject *)pixel_map);
|
||||
|
||||
// Check sizes
|
||||
npy_intp rd_size = PyArray_SIZE((PyArrayObject *)raw_data);
|
||||
npy_intp fr_size = PyArray_SIZE((PyArrayObject *)data_out);
|
||||
npy_intp pm_size = PyArray_SIZE((PyArrayObject *)pixel_map);
|
||||
|
||||
// TODO! Add exceptions
|
||||
if (rd_size != fr_size) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"Raw data size and data size needs to match");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int64_t n_frames = 1;
|
||||
if (rd_dim == 2)
|
||||
n_frames = PyArray_DIM((PyArrayObject *)raw_data, 0);
|
||||
// printf("n_frames: %lu\n", n_frames);
|
||||
|
||||
// do the correct size check
|
||||
if (rd_size / n_frames != pm_size) {
|
||||
PyErr_SetString(PyExc_TypeError,
|
||||
"Pixel map size needs to match with frame size");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (n_threads == 1) {
|
||||
pm_decode(src, dst, pm, n_frames, n_rows * n_cols);
|
||||
} else {
|
||||
// Multithreaded processing
|
||||
pthread_t *threads = malloc(sizeof(pthread_t *) * n_threads);
|
||||
thread_args *arguments = malloc(sizeof(thread_args) * n_threads);
|
||||
|
||||
size_t frames_per_thread = n_frames / n_threads;
|
||||
size_t assigned_frames = 0;
|
||||
for (size_t i = 0; i < n_threads; i++) {
|
||||
arguments[i].src = src + (i * frames_per_thread * pm_size);
|
||||
arguments[i].dst = dst + (i * frames_per_thread * pm_size);
|
||||
arguments[i].pm = pm;
|
||||
arguments[i].n_frames =
|
||||
frames_per_thread; // TODO! not matching frames.
|
||||
arguments[i].n_pixels = n_rows * n_cols;
|
||||
assigned_frames += frames_per_thread;
|
||||
}
|
||||
arguments[n_threads - 1].n_frames += n_frames - assigned_frames;
|
||||
|
||||
for (size_t i = 0; i < n_threads; i++) {
|
||||
pthread_create(&threads[i], NULL, (void *)thread_pmdecode,
|
||||
&arguments[i]);
|
||||
}
|
||||
for (size_t i = 0; i < n_threads; i++) {
|
||||
pthread_join(threads[i], NULL);
|
||||
}
|
||||
free(threads);
|
||||
free(arguments);
|
||||
}
|
||||
|
||||
Py_DECREF(raw_data);
|
||||
Py_DECREF(pixel_map);
|
||||
|
||||
return data_out;
|
||||
}
|
||||
|
||||
// Module docstring, shown as a part of help(creader)
|
||||
static char module_docstring[] = "C functions decode CTB data";
|
||||
|
||||
// Module methods
|
||||
static PyMethodDef creader_methods[] = {
|
||||
{"decode", (PyCFunction)(void (*)(void))decode,
|
||||
METH_VARARGS | METH_KEYWORDS, "Decode analog data using a pixel map"},
|
||||
{NULL, NULL, 0, NULL} /* Sentinel */
|
||||
};
|
||||
|
||||
// Module defenition
|
||||
static struct PyModuleDef decoder_def = {
|
||||
PyModuleDef_HEAD_INIT,
|
||||
"_decoder",
|
||||
module_docstring,
|
||||
-1,
|
||||
creader_methods, // m_methods
|
||||
NULL, // m_slots
|
||||
NULL, // m_traverse
|
||||
NULL, // m_clear
|
||||
NULL // m_free
|
||||
};
|
||||
|
||||
// Initialize module and add classes
|
||||
PyMODINIT_FUNC PyInit__decoder(void) {
|
||||
|
||||
PyObject *m = PyModule_Create(&decoder_def);
|
||||
if (m == NULL)
|
||||
return NULL;
|
||||
import_array(); // Needed for numpy
|
||||
return m;
|
||||
}
|
18
pyctbgui/src/pm_decode.c
Normal file
18
pyctbgui/src/pm_decode.c
Normal file
@ -0,0 +1,18 @@
|
||||
#include "pm_decode.h"
|
||||
#include "thread_utils.h"
|
||||
|
||||
void thread_pmdecode(void *args) {
|
||||
thread_args *a;
|
||||
a = (thread_args *)args;
|
||||
pm_decode(a->src, a->dst, a->pm, a->n_frames, a->n_pixels);
|
||||
}
|
||||
|
||||
void pm_decode(uint16_t *src, uint16_t *dst, uint32_t *pm, size_t n_frames,
|
||||
size_t n_pixels) {
|
||||
for (size_t i = 0; i < n_frames; i++) {
|
||||
for (size_t j = 0; j < n_pixels; j++) {
|
||||
*dst++ = src[pm[j]];
|
||||
}
|
||||
src += n_pixels;
|
||||
}
|
||||
}
|
8
pyctbgui/src/pm_decode.h
Normal file
8
pyctbgui/src/pm_decode.h
Normal file
@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
// Wrapper to be used with pthreads
|
||||
void thread_pmdecode(void *args);
|
||||
|
||||
void pm_decode(uint16_t *src, uint16_t *dst, uint32_t *pm, size_t n_frames,
|
||||
size_t n_pixels);
|
10
pyctbgui/src/thread_utils.h
Normal file
10
pyctbgui/src/thread_utils.h
Normal file
@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
typedef struct {
|
||||
uint16_t *src;
|
||||
uint16_t *dst;
|
||||
uint32_t *pm;
|
||||
size_t n_frames;
|
||||
size_t n_pixels;
|
||||
} thread_args;
|
0
pyctbgui/tests/gui/__init__.py
Normal file
0
pyctbgui/tests/gui/__init__.py
Normal file
11
pyctbgui/tests/gui/conftest.py
Normal file
11
pyctbgui/tests/gui/conftest.py
Normal file
@ -0,0 +1,11 @@
|
||||
import pytest
|
||||
|
||||
from pyctbgui.ui import MainWindow
|
||||
|
||||
|
||||
@pytest.fixture(scope='package')
|
||||
def main():
|
||||
main = MainWindow()
|
||||
main.show()
|
||||
yield main
|
||||
main.close()
|
BIN
pyctbgui/tests/gui/data/matterhorm_image_transceiver.npy
Normal file
BIN
pyctbgui/tests/gui/data/matterhorm_image_transceiver.npy
Normal file
Binary file not shown.
BIN
pyctbgui/tests/gui/data/matterhorn_waveform_transceiver1and2.npz
Normal file
BIN
pyctbgui/tests/gui/data/matterhorn_waveform_transceiver1and2.npz
Normal file
Binary file not shown.
BIN
pyctbgui/tests/gui/data/moench04_image_analog.npy
Normal file
BIN
pyctbgui/tests/gui/data/moench04_image_analog.npy
Normal file
Binary file not shown.
BIN
pyctbgui/tests/gui/data/moench04_waveform_adc.npz
Normal file
BIN
pyctbgui/tests/gui/data/moench04_waveform_adc.npz
Normal file
Binary file not shown.
232
pyctbgui/tests/gui/data/pattern.pat
Normal file
232
pyctbgui/tests/gui/data/pattern.pat
Normal file
@ -0,0 +1,232 @@
|
||||
patword 0x0000 0x000000006b2e8001
|
||||
patword 0x0001 0x000000006b2e8001
|
||||
patword 0x0002 0x000000006b2e8001
|
||||
patword 0x0003 0x000000006b2e8001
|
||||
patword 0x0004 0x000000006b2e8001
|
||||
patword 0x0005 0x000000006b2e8001
|
||||
patword 0x0006 0x000000006b2e8001
|
||||
patword 0x0007 0x000000006b2e8001
|
||||
patword 0x0008 0x000000006b2e8001
|
||||
patword 0x0009 0x000000006b2e8001
|
||||
patword 0x000a 0x000000006b2e8001
|
||||
patword 0x000b 0x000000006b2e8001
|
||||
patword 0x000c 0x00000000692e8001
|
||||
patword 0x000d 0x00000000692e8001
|
||||
patword 0x000e 0x00000000692e8001
|
||||
patword 0x000f 0x00000000692e8001
|
||||
patword 0x0010 0x00000000692e8001
|
||||
patword 0x0011 0x00000000692e8001
|
||||
patword 0x0012 0x00000000692e8001
|
||||
patword 0x0013 0x00000000692e8001
|
||||
patword 0x0014 0x00000000692e8001
|
||||
patword 0x0015 0x00000000692e8001
|
||||
patword 0x0016 0x00000000682e8001
|
||||
patword 0x0017 0x00000000682e8001
|
||||
patword 0x0018 0x00000000682e8001
|
||||
patword 0x0019 0x00000000682e8001
|
||||
patword 0x001a 0x00000000482c8001
|
||||
patword 0x001b 0x00000000482c8001
|
||||
patword 0x001c 0x00000000482c8001
|
||||
patword 0x001d 0x00000000482c8001
|
||||
patword 0x001e 0x00000000482c8001
|
||||
patword 0x001f 0x00000000482c8001
|
||||
patword 0x0020 0x00000000482c8001
|
||||
patword 0x0021 0x00000000482c8001
|
||||
patword 0x0022 0x00000000482c8001
|
||||
patword 0x0023 0x00000000482c8001
|
||||
patword 0x0024 0x00000000482c8001
|
||||
patword 0x0025 0x00000000482c8001
|
||||
patword 0x0026 0x00000000482c8001
|
||||
patword 0x0027 0x00000000482c8001
|
||||
patword 0x0028 0x00000000482c8001
|
||||
patword 0x0029 0x00000000482c8001
|
||||
patword 0x002a 0x00000000482c8001
|
||||
patword 0x002b 0x00000000482c8001
|
||||
patword 0x002c 0x00000000482c8001
|
||||
patword 0x002d 0x00000000482c8001
|
||||
patword 0x002e 0x00000000582c8001
|
||||
patword 0x002f 0x00000000582c8001
|
||||
patword 0x0030 0x00000000582c8001
|
||||
patword 0x0031 0x00000000582c8001
|
||||
patword 0x0032 0x00000000582c8001
|
||||
patword 0x0033 0x00000000582c8001
|
||||
patword 0x0034 0x00000000582c8001
|
||||
patword 0x0035 0x00000000582c8001
|
||||
patword 0x0036 0x00000000582c8001
|
||||
patword 0x0037 0x00000000582c8001
|
||||
patword 0x0038 0x00000000582c8001
|
||||
patword 0x0039 0x00000000582c8001
|
||||
patword 0x003a 0x00000000582c8001
|
||||
patword 0x003b 0x00000000582c8001
|
||||
patword 0x003c 0x00000000582c8001
|
||||
patword 0x003d 0x00000000582c8001
|
||||
patword 0x003e 0x00000000582c8001
|
||||
patword 0x003f 0x00000000582c8001
|
||||
patword 0x0040 0x00000000582c8001
|
||||
patword 0x0041 0x00000000582c8001
|
||||
patword 0x0042 0x00000000582c9011
|
||||
patword 0x0043 0x00000000582c9011
|
||||
patword 0x0044 0x00000000582c8001
|
||||
patword 0x0045 0x00000000582c8001
|
||||
patword 0x0046 0x00000000582c8001
|
||||
patword 0x0047 0x00000000582c8001
|
||||
patword 0x0048 0x00000000582c8001
|
||||
patword 0x0049 0x00000000582c8001
|
||||
patword 0x004a 0x00000000582c8001
|
||||
patword 0x004b 0x00000000582c8001
|
||||
patword 0x004c 0x00000000582c8001
|
||||
patword 0x004d 0x00000000582c8001
|
||||
patword 0x004e 0x00000000582c8001
|
||||
patword 0x004f 0x00000000582c8001
|
||||
patword 0x0050 0x00000000582c8001
|
||||
patword 0x0051 0x00000000582c8001
|
||||
patword 0x0052 0x00000000582c8001
|
||||
patword 0x0053 0x00000000582c8001
|
||||
patword 0x0054 0x00000000582c8001
|
||||
patword 0x0055 0x00000000582c8001
|
||||
patword 0x0056 0x00000000582c8001
|
||||
patword 0x0057 0x00000000582c8001
|
||||
patword 0x0058 0x00000000582c8001
|
||||
patword 0x0059 0x00000000582c8001
|
||||
patword 0x005a 0x00000000582c8041
|
||||
patword 0x005b 0x00000000582c8041
|
||||
patword 0x005c 0x00000000582c8141
|
||||
patword 0x005d 0x00000000582c8041
|
||||
patword 0x005e 0x00000000582c8041
|
||||
patword 0x005f 0x00000000582c8041
|
||||
patword 0x0060 0x00000000582c8041
|
||||
patword 0x0061 0x00000000582c8041
|
||||
patword 0x0062 0x00000000582c8041
|
||||
patword 0x0063 0x00000000582c8041
|
||||
patword 0x0064 0x00000000582c8041
|
||||
patword 0x0065 0x00000000582c8041
|
||||
patword 0x0066 0x00000000582c8041
|
||||
patword 0x0067 0x00000000582c8041
|
||||
patword 0x0068 0x00000000582c8041
|
||||
patword 0x0069 0x00000000582c8041
|
||||
patword 0x006a 0x00000000582c8041
|
||||
patword 0x006b 0x00000000582c8041
|
||||
patword 0x006c 0x00000000582c8041
|
||||
patword 0x006d 0x00000000582c8041
|
||||
patword 0x006e 0x00000000582c8041
|
||||
patword 0x006f 0x00000000582c8041
|
||||
patword 0x0070 0x00000000582c8041
|
||||
patword 0x0071 0x00000000582c8041
|
||||
patword 0x0072 0x00000000582c8041
|
||||
patword 0x0073 0x00000000582c8041
|
||||
patword 0x0074 0x00000000d82c8941
|
||||
patword 0x0075 0x00000000d82c8041
|
||||
patword 0x0076 0x00000000582c8001
|
||||
patword 0x0077 0x00000000582c8001
|
||||
patword 0x0078 0xc0000000582c8001
|
||||
patword 0x0079 0xc0000000582c8801
|
||||
patword 0x007a 0xc0000000582c8001
|
||||
patword 0x007b 0xc0000000582c8801
|
||||
patword 0x007c 0xc0000000582c8001
|
||||
patword 0x007d 0xc0000000582c8801
|
||||
patword 0x007e 0xc0000000582c8001
|
||||
patword 0x007f 0xc0000000582c8801
|
||||
patword 0x0080 0xc0000000582c8001
|
||||
patword 0x0081 0xc0000000582c8801
|
||||
patword 0x0082 0xc0000000582c8001
|
||||
patword 0x0083 0xc0000000582c8801
|
||||
patword 0x0084 0xc0000000582c8001
|
||||
patword 0x0085 0xc0000000582c8801
|
||||
patword 0x0086 0xc0000000582c8001
|
||||
patword 0x0087 0xc0000000582c8801
|
||||
patword 0x0088 0xc0000000582c8001
|
||||
patword 0x0089 0xc0000000582c8801
|
||||
patword 0x008a 0xc0000000582c8001
|
||||
patword 0x008b 0xc0000000582c8801
|
||||
patword 0x008c 0xc0000000582c8001
|
||||
patword 0x008d 0xc0000000582c8801
|
||||
patword 0x008e 0xc0000000582c8001
|
||||
patword 0x008f 0xc0000000582c8801
|
||||
patword 0x0090 0xc0000000582c8001
|
||||
patword 0x0091 0xc0000000582c8901
|
||||
patword 0x0092 0xc0000000582c8001
|
||||
patword 0x0093 0xc0000000582c8801
|
||||
patword 0x0094 0xc0000000582c8001
|
||||
patword 0x0095 0xc0000000582c8801
|
||||
patword 0x0096 0xc0000000582c8001
|
||||
patword 0x0097 0xc0000000582c8801
|
||||
patword 0x0098 0xc0000000582c8001
|
||||
patword 0x0099 0xc0000000582c8801
|
||||
patword 0x009a 0xc0000000582c8001
|
||||
patword 0x009b 0xc0000000582c8801
|
||||
patword 0x009c 0xc0000000582c8001
|
||||
patword 0x009d 0xc0000000582c8801
|
||||
patword 0x009e 0xc0000000582c8001
|
||||
patword 0x009f 0xc0000000582c8801
|
||||
patword 0x00a0 0xc0000000582c8001
|
||||
patword 0x00a1 0xc0000000582c8801
|
||||
patword 0x00a2 0xc0000000582c8001
|
||||
patword 0x00a3 0xc0000000582c8801
|
||||
patword 0x00a4 0xc0000000582c8001
|
||||
patword 0x00a5 0xc0000000582c8801
|
||||
patword 0x00a6 0xc0000000582c8001
|
||||
patword 0x00a7 0xc0000000582c8801
|
||||
patword 0x00a8 0xc0000000582c8001
|
||||
patword 0x00a9 0xc0000000d82c8901
|
||||
patword 0x00aa 0xc0000000d82c8001
|
||||
patword 0x00ab 0xc0000000582c8801
|
||||
patword 0x00ac 0xc0000000582c8001
|
||||
patword 0x00ad 0xc0000000582c8801
|
||||
patword 0x00ae 0xc0000000582c8001
|
||||
patword 0x00af 0xc0000000582c8801
|
||||
patword 0x00b0 0xc0000000582c8001
|
||||
patword 0x00b1 0xc0000000582c8801
|
||||
patword 0x00b2 0xc0000000582c8001
|
||||
patword 0x00b3 0xc0000000582c8801
|
||||
patword 0x00b4 0xc0000000582c8001
|
||||
patword 0x00b5 0xc0000000582c8801
|
||||
patword 0x00b6 0xc0000000582c8001
|
||||
patword 0x00b7 0xc0000000582c8801
|
||||
patword 0x00b8 0xc0000000582c8001
|
||||
patword 0x00b9 0xc0000000582c8801
|
||||
patword 0x00ba 0xc0000000582c8001
|
||||
patword 0x00bb 0xc0000000582c8801
|
||||
patword 0x00bc 0xc0000000582c8001
|
||||
patword 0x00bd 0xc0000000582c8801
|
||||
patword 0x00be 0xc0000000582c8001
|
||||
patword 0x00bf 0xc0000000582c8801
|
||||
patword 0x00c0 0xc0000000582c8001
|
||||
patword 0x00c1 0xc0000000582c8801
|
||||
patword 0x00c2 0xc0000000582c8001
|
||||
patword 0x00c3 0xc0000000582c8901
|
||||
patword 0x00c4 0xc0000000582c8001
|
||||
patword 0x00c5 0xc0000000582c8801
|
||||
patword 0x00c6 0xc0000000582c8001
|
||||
patword 0x00c7 0xc0000000582c8801
|
||||
patword 0x00c8 0xc0000000582c8001
|
||||
patword 0x00c9 0xc0000000582c8801
|
||||
patword 0x00ca 0xc0000000582c8001
|
||||
patword 0x00cb 0xc0000000582c8801
|
||||
patword 0x00cc 0xc0000000582c8001
|
||||
patword 0x00cd 0xc0000000582c8801
|
||||
patword 0x00ce 0xc0000000582c8001
|
||||
patword 0x00cf 0xc0000000582c8801
|
||||
patword 0x00d0 0xc0000000582c8001
|
||||
patword 0x00d1 0xc0000000582c8801
|
||||
patword 0x00d2 0xc0000000582c8001
|
||||
patword 0x00d3 0xc0000000582c8801
|
||||
patword 0x00d4 0xc0000000582c8001
|
||||
patword 0x00d5 0xc0000000582c8801
|
||||
patword 0x00d6 0xc0000000582c8001
|
||||
patword 0x00d7 0xc0000000582c8801
|
||||
patword 0x00d8 0xc0000000582c8001
|
||||
patword 0x00d9 0xc0000000582c8801
|
||||
patword 0x00da 0xc0000000582c8001
|
||||
patword 0x00db 0x00000000582c8001
|
||||
patword 0x00dc 0x00000000582c8001
|
||||
patword 0x00dd 0x00000000482c8901
|
||||
patword 0x00de 0x00000000482c8001
|
||||
patword 0x00df 0x00000000482c8901
|
||||
patword 0x00e0 0x00000000482c8001
|
||||
patword 0x00e1 0x000000006b2e8001
|
||||
patlimits 0x0000 0x00e1
|
||||
patioctrl 0x01000000fb7fdd55
|
||||
patloop 0 0x00a9 0x00da
|
||||
patnloop 0 199
|
||||
patwait 0 0x0018
|
||||
patwaittime 0 800
|
BIN
pyctbgui/tests/gui/data/pattern.png
Normal file
BIN
pyctbgui/tests/gui/data/pattern.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 46 KiB |
9
pyctbgui/tests/gui/data/simulator.config
Normal file
9
pyctbgui/tests/gui/data/simulator.config
Normal file
@ -0,0 +1,9 @@
|
||||
hostname localhost
|
||||
rx_hostname localhost
|
||||
udp_dstip auto
|
||||
udp_srcip auto
|
||||
|
||||
romode analog
|
||||
asamples 5000
|
||||
tsamples 288
|
||||
|
57
pyctbgui/tests/gui/test_analog_moench.py
Normal file
57
pyctbgui/tests/gui/test_analog_moench.py
Normal file
@ -0,0 +1,57 @@
|
||||
from pathlib import Path
|
||||
|
||||
import numpy as np
|
||||
from pytestqt.qt_compat import qt_api
|
||||
|
||||
from .utils import setup_gui, defaultParams
|
||||
|
||||
|
||||
def test_image_acq(main, qtbot, tmp_path):
|
||||
"""
|
||||
tests Analog image acquisition and numpy saving
|
||||
"""
|
||||
params = defaultParams()
|
||||
params.detector = "Moench04"
|
||||
params.mode = "Analog"
|
||||
params.enabled = list(range(32))
|
||||
|
||||
setup_gui(qtbot, main, params, tmp_path=tmp_path)
|
||||
|
||||
qtbot.mouseClick(main.pushButtonStart, qt_api.QtCore.Qt.MouseButton.LeftButton)
|
||||
|
||||
acqIndex = main.acquisitionTab.view.spinBoxAcquisitionIndex.value() - 1
|
||||
newPath = main.acquisitionTab.outputDir / f'{main.acquisitionTab.outputFileNamePrefix}_{acqIndex}.npy'
|
||||
qtbot.wait_until(lambda: newPath.is_file())
|
||||
|
||||
testArray = np.load(newPath)
|
||||
dataArray = np.load(Path(__file__).parent / 'data' / 'moench04_image_analog.npy')
|
||||
|
||||
assert testArray.shape == (1, 400, 400)
|
||||
assert np.array_equal(dataArray, testArray)
|
||||
|
||||
|
||||
def test_waveform_acq(main, qtbot, tmp_path):
|
||||
"""
|
||||
tests Analog waveform acquisition and numpy saving
|
||||
"""
|
||||
params = defaultParams()
|
||||
params.image = False
|
||||
params.detector = "Moench04"
|
||||
params.mode = "Analog"
|
||||
params.enabled = list(range(32))
|
||||
params.plotted = params.enabled
|
||||
|
||||
setup_gui(qtbot, main, params, tmp_path=tmp_path)
|
||||
|
||||
qtbot.mouseClick(main.pushButtonStart, qt_api.QtCore.Qt.MouseButton.LeftButton)
|
||||
|
||||
acqIndex = main.acquisitionTab.view.spinBoxAcquisitionIndex.value() - 1
|
||||
newPath = main.acquisitionTab.outputDir / f'{main.acquisitionTab.outputFileNamePrefix}_{acqIndex}.npz'
|
||||
|
||||
qtbot.wait_until(lambda: newPath.is_file())
|
||||
testArray = np.load(newPath)
|
||||
dataArray = np.load(Path(__file__).parent / 'data' / 'moench04_waveform_adc.npz')
|
||||
files = [f"ADC{i}" for i in params.enabled]
|
||||
assert testArray.files == files
|
||||
for i in files:
|
||||
assert np.array_equal(dataArray[i], testArray[i])
|
27
pyctbgui/tests/gui/test_pattern.py
Normal file
27
pyctbgui/tests/gui/test_pattern.py
Normal file
@ -0,0 +1,27 @@
|
||||
from pathlib import Path
|
||||
|
||||
from pytestqt.qt_compat import qt_api
|
||||
|
||||
from pyctbgui.utils.defines import Defines
|
||||
from tests.gui.utils import defaultParams
|
||||
|
||||
|
||||
def test_view_pattern(main, qtbot, tmp_path):
|
||||
"""
|
||||
Tests pattern file viewing
|
||||
"""
|
||||
params = defaultParams()
|
||||
params.image = False
|
||||
main.tabWidget.setCurrentIndex(Defines.pattern.tabIndex)
|
||||
qtbot.keyClicks(main.patternTab.view.lineEditPatternFile, "tests/gui/data/pattern.pat")
|
||||
qtbot.mouseClick(main.patternTab.view.pushButtonViewPattern, qt_api.QtCore.Qt.MouseButton.LeftButton)
|
||||
qtbot.wait_until(lambda: main.patternTab.figure is not None)
|
||||
assert main.patternTab.figure is not None
|
||||
|
||||
# save pattern
|
||||
main.patternTab.figure.savefig(tmp_path / "pattern.png")
|
||||
assert Path(tmp_path / "pattern.png").exists()
|
||||
|
||||
# pattern files generated from python3.10 libraries differ from python3.11. this would make this
|
||||
# test flaky so we skip it for now
|
||||
# assert filecmp.cmp("tests/gui/data/pattern.png", tmp_path / "pattern.png")
|
34
pyctbgui/tests/gui/test_pedestal_matterhorn.py
Normal file
34
pyctbgui/tests/gui/test_pedestal_matterhorn.py
Normal file
@ -0,0 +1,34 @@
|
||||
import numpy as np
|
||||
from pytestqt.qt_compat import qt_api
|
||||
|
||||
from tests.gui.utils import defaultParams, setup_gui
|
||||
|
||||
|
||||
def test_pedestal_substraction(main, qtbot, tmp_path):
|
||||
"""
|
||||
tests Transceiver image acquisition, numpy saving and pedestal substraction
|
||||
"""
|
||||
|
||||
# record 10 frames
|
||||
params = defaultParams()
|
||||
params.pedestalRecord = True
|
||||
params.nFrames = 10
|
||||
params.numpy = False
|
||||
setup_gui(qtbot, main, params, tmp_path=tmp_path)
|
||||
qtbot.mouseClick(main.pushButtonStart, qt_api.QtCore.Qt.MouseButton.LeftButton)
|
||||
qtbot.wait_until(lambda: main.plotTab.view.labelPedestalFrames.text() == 'recorded frames: 10')
|
||||
|
||||
# apply pedestal and save
|
||||
params.pedestalRecord = False
|
||||
params.numpy = True
|
||||
params.nFrames = 2
|
||||
setup_gui(qtbot, main, params, tmp_path=tmp_path)
|
||||
qtbot.mouseClick(main.pushButtonStart, qt_api.QtCore.Qt.MouseButton.LeftButton)
|
||||
acqIndex = main.acquisitionTab.view.spinBoxAcquisitionIndex.value() - 1
|
||||
newPath = main.acquisitionTab.outputDir / f'{main.acquisitionTab.outputFileNamePrefix}_{acqIndex}.npy'
|
||||
qtbot.wait_until(lambda: newPath.is_file())
|
||||
|
||||
testArray = np.load(newPath)
|
||||
|
||||
assert testArray.shape == (2, 48, 48)
|
||||
assert np.array_equal(testArray, np.zeros((2, 48, 48)))
|
28
pyctbgui/tests/gui/test_signal_matterhorn.py
Normal file
28
pyctbgui/tests/gui/test_signal_matterhorn.py
Normal file
@ -0,0 +1,28 @@
|
||||
# from pathlib import Path
|
||||
#
|
||||
# import numpy as np
|
||||
# from pytestqt.qt_compat import qt_api
|
||||
#
|
||||
# from .utils import setup_gui, defaultParams
|
||||
#
|
||||
#
|
||||
# def test_waveform_signals(main, qtbot, tmp_path):
|
||||
# """
|
||||
# tests signals waveform acquisition and numpy saving
|
||||
# """
|
||||
# params = defaultParams()
|
||||
# params.image = False
|
||||
# params.mode = "Signal"
|
||||
# params.enabled = list(range(128))
|
||||
# params.plotted = params.enabled
|
||||
#
|
||||
# setup_gui(qtbot, main, params, tmp_path=tmp_path)
|
||||
#
|
||||
# qtbot.mouseClick(main.pushButtonStart, qt_api.QtCore.Qt.MouseButton.LeftButton)
|
||||
#
|
||||
# acqIndex = main.acquisitionTab.view.spinBoxAcquisitionIndex.value() - 1
|
||||
# newPath = main.acquisitionTab.outputDir / f'{main.acquisitionTab.outputFileNamePrefix}_{acqIndex}.npz'
|
||||
#
|
||||
# qtbot.wait_until(lambda: newPath.is_file())
|
||||
# testArray = np.load(newPath)
|
||||
#
|
50
pyctbgui/tests/gui/test_transceiver_matterhorn.py
Normal file
50
pyctbgui/tests/gui/test_transceiver_matterhorn.py
Normal file
@ -0,0 +1,50 @@
|
||||
from pathlib import Path
|
||||
|
||||
import numpy as np
|
||||
from pytestqt.qt_compat import qt_api
|
||||
|
||||
from .utils import setup_gui, defaultParams
|
||||
|
||||
|
||||
def test_image_acq(main, qtbot, tmp_path):
|
||||
"""
|
||||
tests Transceiver image acquisition and numpy saving
|
||||
"""
|
||||
|
||||
setup_gui(qtbot, main, tmp_path=tmp_path)
|
||||
|
||||
qtbot.mouseClick(main.pushButtonStart, qt_api.QtCore.Qt.MouseButton.LeftButton)
|
||||
|
||||
acqIndex = main.acquisitionTab.view.spinBoxAcquisitionIndex.value() - 1
|
||||
newPath = main.acquisitionTab.outputDir / f'{main.acquisitionTab.outputFileNamePrefix}_{acqIndex}.npy'
|
||||
qtbot.wait_until(lambda: newPath.is_file())
|
||||
|
||||
testArray = np.load(newPath)
|
||||
dataArray = np.load(Path(__file__).parent / 'data' / 'matterhorm_image_transceiver.npy')
|
||||
|
||||
assert testArray.shape == (1, 48, 48)
|
||||
assert np.array_equal(dataArray, testArray)
|
||||
|
||||
|
||||
def test_waveform_acq(main, qtbot, tmp_path):
|
||||
"""
|
||||
tests Transceiver waveform acquisition and numpy saving
|
||||
"""
|
||||
params = defaultParams()
|
||||
params.image = False
|
||||
params.enabled = [0, 1]
|
||||
params.plotted = [0, 1]
|
||||
|
||||
setup_gui(qtbot, main, params, tmp_path=tmp_path)
|
||||
|
||||
qtbot.mouseClick(main.pushButtonStart, qt_api.QtCore.Qt.MouseButton.LeftButton)
|
||||
|
||||
acqIndex = main.acquisitionTab.view.spinBoxAcquisitionIndex.value() - 1
|
||||
newPath = main.acquisitionTab.outputDir / f'{main.acquisitionTab.outputFileNamePrefix}_{acqIndex}.npz'
|
||||
|
||||
qtbot.wait_until(lambda: newPath.is_file())
|
||||
testArray = np.load(newPath)
|
||||
dataArray = np.load(Path(__file__).parent / 'data' / 'matterhorn_waveform_transceiver1and2.npz')
|
||||
assert testArray.files == ['Transceiver 0', 'Transceiver 1']
|
||||
assert np.array_equal(dataArray['Transceiver 0'], testArray['Transceiver 0'])
|
||||
assert np.array_equal(dataArray['Transceiver 1'], testArray['Transceiver 1'])
|
78
pyctbgui/tests/gui/utils.py
Normal file
78
pyctbgui/tests/gui/utils.py
Normal file
@ -0,0 +1,78 @@
|
||||
from pathlib import Path
|
||||
|
||||
from pyctbgui.utils.defines import Defines
|
||||
|
||||
|
||||
class defaultParams:
|
||||
image = True
|
||||
detector = "Matterhorn"
|
||||
numpy = True
|
||||
mode = "Transceiver"
|
||||
outputDir = "/tmp"
|
||||
filename = "run"
|
||||
nFrames = 1
|
||||
enabled = []
|
||||
plotted = []
|
||||
pedestalRecord = True
|
||||
pattern = False
|
||||
|
||||
|
||||
def setup_gui(qtbot, widget, params=defaultParams(), tmp_path=Path('/tmp')):
|
||||
if params.image:
|
||||
widget.plotTab.view.radioButtonImage.setChecked(True)
|
||||
widget.plotTab.view.radioButtonWaveform.setChecked(False)
|
||||
if params.mode == "Transceiver":
|
||||
params.enabled = [0, 1]
|
||||
else:
|
||||
params.enabled = range(128)
|
||||
else:
|
||||
widget.plotTab.view.radioButtonWaveform.setChecked(True)
|
||||
widget.plotTab.view.radioButtonImage.setChecked(False)
|
||||
|
||||
if params.mode == "Transceiver":
|
||||
widget.tabWidget.setCurrentIndex(Defines.transceiver.tabIndex)
|
||||
for i in range(Defines.transceiver.count):
|
||||
# check or uncheck enable/plot checkboxes
|
||||
enable = getattr(widget.transceiverTab.view, f"checkBoxTransceiver{i}")
|
||||
enable.setChecked(i in params.enabled)
|
||||
enable = getattr(widget.transceiverTab.view, f"checkBoxTransceiver{i}Plot")
|
||||
enable.setChecked(i in params.plotted)
|
||||
elif params.mode == "Analog":
|
||||
widget.tabWidget.setCurrentIndex(Defines.adc.tabIndex)
|
||||
for i in range(Defines.adc.count):
|
||||
# check or uncheck enable/plot checkboxes
|
||||
enable = getattr(widget.adcTab.view, f"checkBoxADC{i}En")
|
||||
enable.setChecked(i in params.enabled)
|
||||
enable = getattr(widget.adcTab.view, f"checkBoxADC{i}Plot")
|
||||
enable.setChecked(i in params.plotted)
|
||||
|
||||
qtbot.wait_until(lambda: widget.plotTab.view.radioButtonImage.isChecked() == params.image)
|
||||
|
||||
qtbot.keyClicks(widget.plotTab.view.comboBoxPlot, params.detector)
|
||||
qtbot.wait_until(lambda: widget.plotTab.view.comboBoxPlot.currentText() == params.detector)
|
||||
|
||||
widget.acquisitionTab.view.checkBoxFileWriteNumpy.setChecked(params.numpy)
|
||||
|
||||
widget.acquisitionTab.view.comboBoxROMode.setCurrentIndex(-1)
|
||||
qtbot.keyClicks(widget.acquisitionTab.view.comboBoxROMode, params.mode)
|
||||
qtbot.wait_until(lambda: widget.acquisitionTab.view.comboBoxROMode.currentText() == params.mode)
|
||||
|
||||
widget.acquisitionTab.view.lineEditFilePath.setText(str(tmp_path))
|
||||
widget.acquisitionTab.setFilePath()
|
||||
|
||||
widget.acquisitionTab.view.lineEditFileName.setText(params.filename)
|
||||
widget.acquisitionTab.setFileName()
|
||||
|
||||
widget.acquisitionTab.view.spinBoxFrames.setValue(params.nFrames)
|
||||
widget.acquisitionTab.setFrames()
|
||||
|
||||
widget.plotTab.view.radioButtonPedestalRecord.setChecked(params.pedestalRecord)
|
||||
widget.plotTab.view.radioButtonPedestalApply.setChecked(not params.pedestalRecord)
|
||||
|
||||
qtbot.wait_until(lambda: widget.acquisitionTab.view.spinBoxFrames.value() == params.nFrames)
|
||||
|
||||
assert widget.acquisitionTab.view.comboBoxROMode.currentText() == params.mode
|
||||
assert widget.plotTab.view.comboBoxPlot.currentText() == params.detector
|
||||
assert widget.acquisitionTab.writeNumpy == params.numpy
|
||||
assert widget.acquisitionTab.view.spinBoxFrames.value() == params.nFrames
|
||||
assert widget.acquisitionTab.outputDir == Path(str(tmp_path))
|
129
pyctbgui/tests/unit/data/moench04_start_trigger.alias
Executable file
129
pyctbgui/tests/unit/data/moench04_start_trigger.alias
Executable file
@ -0,0 +1,129 @@
|
||||
BIT0 gHG
|
||||
BIT1 DGS6 1
|
||||
BIT2 pulse
|
||||
BIT3 DGS7 1
|
||||
BIT4 clearSSR
|
||||
BIT5 DGS8 1
|
||||
BIT6 inSSR
|
||||
BIT7 DGS9 1
|
||||
BIT8 clkSSR
|
||||
BIT9 clk_fb
|
||||
BIT10 prechargeConnect
|
||||
BIT11 clk
|
||||
BIT12 clear
|
||||
BIT13 shr_out_15
|
||||
BIT14 bypassCDS
|
||||
BIT15 Sto2
|
||||
BIT16 ENprechPre
|
||||
BIT17 Sto0_bot
|
||||
BIT18 pulseOFF
|
||||
BIT19 Sto1
|
||||
BIT20 BYPASS
|
||||
BIT21 connCDS
|
||||
BIT22 Dsg3
|
||||
BIT23 OutSSRbot
|
||||
BIT24 resCDS
|
||||
BIT25 res
|
||||
BIT26 shr_out_31
|
||||
BIT27 Dsg1
|
||||
BIT28 READ
|
||||
BIT29 Sto0_top
|
||||
BIT30 resDGS
|
||||
BIT31 shr_in
|
||||
BIT48 DGS23 1
|
||||
BIT49 DGS31 1
|
||||
BIT50 DGS22 1
|
||||
BIT51 DGS30 1
|
||||
BIT52 DGS21 1
|
||||
BIT53 DGS29 1
|
||||
BIT54 DGS20 1
|
||||
BIT55 DGS28 1
|
||||
BIT56 DGS19 1
|
||||
BIT57 DGS27 1
|
||||
BIT58 DGS18 1
|
||||
BIT59 DGS26 1
|
||||
BIT60 DGS17 1
|
||||
BIT61 DGS25 1
|
||||
BIT62 DGS16 1
|
||||
BIT63 DGS24 1
|
||||
|
||||
#BIT62 dbit_ena
|
||||
#BIT63 adc_ena
|
||||
|
||||
SENSE3 T_boa.(C)
|
||||
SENSE1 Va+
|
||||
SENSE6 Vdd_ps
|
||||
SENSE4 Vsh
|
||||
SENSE2 Vcc_int
|
||||
SENSE0 Vcc_iochip
|
||||
SENSE7 Vcc1.8A
|
||||
SENSE5 Vcc1.8D
|
||||
|
||||
DAC0 VprechPre
|
||||
DAC1 prechargeV
|
||||
DAC2 vb_sda
|
||||
DAC3 vbp_colbuf
|
||||
DAC4 vcasc_SFP
|
||||
DAC5 ibias_SFP
|
||||
DAC6 vIpreCDS
|
||||
DAC7 vin_com_bot
|
||||
DAC8 vIpre
|
||||
DAC9 s2dVinTest
|
||||
DAC10 VPH
|
||||
DAC11 vIpreDGS
|
||||
DAC12 vrefDGS
|
||||
DAC13 empty13
|
||||
DAC14 vin_com_top
|
||||
DAC15 VPL
|
||||
DAC16 vout_com
|
||||
DAC17 empty17
|
||||
|
||||
ADC0 SCOL9 1
|
||||
ADC1 SCOL8 1
|
||||
ADC2 SCOL11 1
|
||||
ADC3 SCOL10 1
|
||||
ADC4 SCOL13 1
|
||||
ADC5 SCOL12 1
|
||||
ADC6 SCOL15 1
|
||||
ADC7 SCOL14 1
|
||||
|
||||
ADC8 SCOL1 1
|
||||
ADC9 SCOL0 1
|
||||
ADC10 SCOL3 1
|
||||
ADC11 SCOL2 1
|
||||
ADC12 SCOL5 1
|
||||
ADC13 SCOL4 1
|
||||
ADC14 SCOL7 1
|
||||
ADC15 SCOL6 1
|
||||
|
||||
ADC16 SCOL23 1
|
||||
ADC17 SCOL22 1
|
||||
ADC18 SCOL21 1
|
||||
ADC19 SCOL20 1
|
||||
ADC20 SCOL19 1
|
||||
ADC21 SCOL18 1
|
||||
ADC22 SCOL17 1
|
||||
ADC23 SCOL16 1
|
||||
|
||||
ADC24 SCOL31 1
|
||||
ADC25 SCOL30 1
|
||||
ADC26 SCOL29 1
|
||||
ADC27 SCOL28 1
|
||||
ADC28 SCOL27 1
|
||||
ADC29 SCOL26 1
|
||||
ADC30 SCOL25 1
|
||||
ADC31 SCOL24 1
|
||||
|
||||
VA VddA
|
||||
VB VddPre
|
||||
VIO VddD
|
||||
|
||||
#location of the pattern compiler
|
||||
#PATCOMPILER /afs/psi.ch/project/sls_det_software/slsDetectorsPackage/slsDetectorSoftware/patternGenerator/generate.sh
|
||||
PATCOMPILER /afs/psi.ch/project/sls_det_software/sabina/slsDetectorPackage/ctbGui/patternGenerator/generate.sh
|
||||
#location of the pattern to run
|
||||
#PATFILE /afs/psi.ch/user/d/dinapoli/jctb/moench02_rob/patterns_newctb/moench02_pulsing_marco.p
|
||||
#PATFILE /afs/psi.ch/project/sls_det_software/sabina/moench04/patterns/moench04_readout_g4.p
|
||||
#PATFILE /afs/psi.ch/user/m/maliakal_d/setupfiles/ctb_julian.pat
|
||||
#PATFILE /tmp/bla.p
|
||||
#PATFILE /afs/psi.ch/project/mythen/Moench04/moench04_pulsing_readout_g4.p
|
63
pyctbgui/tests/unit/test_alias_file.py
Normal file
63
pyctbgui/tests/unit/test_alias_file.py
Normal file
@ -0,0 +1,63 @@
|
||||
import pytest
|
||||
from pathlib import Path
|
||||
from pyctbgui import alias_utility as at
|
||||
|
||||
|
||||
def test_read_non_existing_file_throws():
|
||||
with pytest.raises(FileNotFoundError):
|
||||
at.read_alias_file('saijvcaiewjrvijaerijvaeoirvjveiojroiajgv')
|
||||
|
||||
|
||||
def test_parse_sample_file():
|
||||
fpath = Path(__file__).parent / 'data/moench04_start_trigger.alias'
|
||||
bit_names, bit_plots, bit_colors, adc_names, adc_plots, adc_colors, dac_names, sense_names, power_names, \
|
||||
pat_file_name = at.read_alias_file(fpath)
|
||||
|
||||
assert len(bit_names) == 64
|
||||
|
||||
true_names = [
|
||||
'gHG', 'DGS6', 'pulse', 'DGS7', 'clearSSR', 'DGS8', 'inSSR', 'DGS9', 'clkSSR', 'clk_fb', 'prechargeConnect',
|
||||
'clk', 'clear', 'shr_out_15', 'bypassCDS', 'Sto2', 'ENprechPre', 'Sto0_bot', 'pulseOFF', 'Sto1', 'BYPASS',
|
||||
'connCDS', 'Dsg3', 'OutSSRbot', 'resCDS', 'res', 'shr_out_31', 'Dsg1', 'READ', 'Sto0_top', 'resDGS', 'shr_in',
|
||||
None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, 'DGS23',
|
||||
'DGS31', 'DGS22', 'DGS30', 'DGS21', 'DGS29', 'DGS20', 'DGS28', 'DGS19', 'DGS27', 'DGS18', 'DGS26', 'DGS17',
|
||||
'DGS25', 'DGS16', 'DGS24'
|
||||
]
|
||||
|
||||
true_plot = [
|
||||
None, True, None, True, None, True, None, True, None, None, None, None, None, None, None, None, None, None,
|
||||
None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None,
|
||||
None, None, None, None, None, None, None, None, None, None, None, None, True, True, True, True, True, True,
|
||||
True, True, True, True, True, True, True, True, True, True
|
||||
]
|
||||
|
||||
# Make sure we didn't mess up anything in this file
|
||||
assert len(true_names) == len(bit_names)
|
||||
for value, reference in zip(bit_names, true_names):
|
||||
assert value == reference
|
||||
|
||||
assert len(true_plot) == 64
|
||||
for value, reference in zip(bit_plots, true_plot):
|
||||
assert value == reference
|
||||
|
||||
# sense names
|
||||
true_sese = ['Vcc_iochip', 'Va+', 'Vcc_int', 'T_boa.(C)', 'Vsh', 'Vcc1.8D', 'Vdd_ps', 'Vcc1.8A']
|
||||
assert len(true_sese) == 8
|
||||
assert true_sese == sense_names
|
||||
|
||||
# ADC
|
||||
|
||||
true_adc = [
|
||||
'SCOL9', 'SCOL8', 'SCOL11', 'SCOL10', 'SCOL13', 'SCOL12', 'SCOL15', 'SCOL14', 'SCOL1', 'SCOL0', 'SCOL3',
|
||||
'SCOL2', 'SCOL5', 'SCOL4', 'SCOL7', 'SCOL6', 'SCOL23', 'SCOL22', 'SCOL21', 'SCOL20', 'SCOL19', 'SCOL18',
|
||||
'SCOL17', 'SCOL16', 'SCOL31', 'SCOL30', 'SCOL29', 'SCOL28', 'SCOL27', 'SCOL26', 'SCOL25', 'SCOL24'
|
||||
]
|
||||
|
||||
assert len(true_adc) == 32
|
||||
assert true_adc == adc_names
|
||||
|
||||
|
||||
def test_single_value_parse_gives_exception():
|
||||
# Check that we get the correct exception
|
||||
with pytest.raises(Exception, match=r'Alias file parsing failed'):
|
||||
at.parse_alias_lines(['hej'])
|
27
pyctbgui/tests/unit/test_bit_utils.py
Normal file
27
pyctbgui/tests/unit/test_bit_utils.py
Normal file
@ -0,0 +1,27 @@
|
||||
import numpy as np
|
||||
|
||||
from pyctbgui import bit_utils as bt
|
||||
|
||||
|
||||
def test_set_bit():
|
||||
num = np.int32(0)
|
||||
num = bt.set_bit(num, 5)
|
||||
assert num == 2**5
|
||||
|
||||
|
||||
def test_remove_bit():
|
||||
num = np.int32(2**5)
|
||||
num = bt.remove_bit(num, 5)
|
||||
assert num == 0
|
||||
|
||||
|
||||
def test_manipulate_bit():
|
||||
num = np.int32(0)
|
||||
num = bt.manipulate_bit(True, num, 5) # True means setting bit
|
||||
assert num == 2**5
|
||||
|
||||
|
||||
def test_manipulate_bit2():
|
||||
num = np.int32(2**8)
|
||||
num = bt.manipulate_bit(False, num, 8) # False means clearing the bit
|
||||
assert num == 0
|
42
pyctbgui/tests/unit/test_decoder.py
Normal file
42
pyctbgui/tests/unit/test_decoder.py
Normal file
@ -0,0 +1,42 @@
|
||||
import numpy as np
|
||||
import sys
|
||||
|
||||
from pyctbgui.utils import decoder
|
||||
from pyctbgui.utils.pixelmap import moench04_analog, matterhorn_transceiver
|
||||
|
||||
|
||||
def test_simple_decode():
|
||||
pixel_map = np.zeros((2, 2), dtype=np.uint32)
|
||||
pixel_map.flat = [0, 1, 2, 3]
|
||||
|
||||
raw_data = np.zeros(4, dtype=np.uint16)
|
||||
raw_data.flat = [8, 9, 10, 11]
|
||||
data = decoder.decode(raw_data, pixel_map)
|
||||
|
||||
assert data[0, 0] == 8
|
||||
assert data[0, 1] == 9
|
||||
assert data[1, 0] == 10
|
||||
assert data[1, 1] == 11
|
||||
|
||||
# Make sure we didn't mess up the reference counts
|
||||
assert sys.getrefcount(data) == 2
|
||||
assert sys.getrefcount(raw_data) == 2
|
||||
assert sys.getrefcount(pixel_map) == 2
|
||||
|
||||
|
||||
def test_compare_python_and_c_decoding():
|
||||
"""
|
||||
Check that the python and C implementation give the same results
|
||||
provides a regression test in case we change the C implementation
|
||||
"""
|
||||
pixel_map = moench04_analog()
|
||||
raw_data = np.arange(400 * 400, dtype=np.uint16)
|
||||
c_data = decoder.decode(raw_data, pixel_map)
|
||||
py_data = decoder.moench04(raw_data)
|
||||
assert (c_data == py_data).all()
|
||||
|
||||
pixel_map = matterhorn_transceiver()
|
||||
raw_data = np.arange(48 * 48, dtype=np.uint16)
|
||||
c_data = decoder.decode(raw_data, pixel_map)
|
||||
py_data = decoder.matterhorn(raw_data)
|
||||
assert (c_data == py_data).all()
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user