mirror of
https://github.com/slsdetectorgroup/slsDetectorPackage.git
synced 2025-04-24 15:20:02 +02:00
Merge branch 'developer' into jf_h5reader
This commit is contained in:
commit
f3a3fb09bf
@ -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/"
|
||||
@ -318,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
|
||||
|
@ -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';
|
||||
}
|
||||
|
@ -9,4 +9,6 @@ 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()
|
160
pyctbgui/tests/unit/test_npy_writer.py
Normal file
160
pyctbgui/tests/unit/test_npy_writer.py
Normal file
@ -0,0 +1,160 @@
|
||||
import filecmp
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
from pyctbgui.utils.numpyWriter.npy_writer import NumpyFileManager
|
||||
import numpy as np
|
||||
|
||||
|
||||
def test_create_new_file(tmp_path):
|
||||
npw = NumpyFileManager(tmp_path / 'tmp.npy', 'w', (400, 400), np.int32)
|
||||
npw.writeOneFrame(np.ones([400, 400], dtype=np.int32))
|
||||
npw.writeOneFrame(np.ones([400, 400], dtype=np.int32))
|
||||
npw.writeOneFrame(np.ones([400, 400], dtype=np.int32))
|
||||
npw.writeOneFrame(np.ones([400, 400], dtype=np.int32))
|
||||
npw.close()
|
||||
|
||||
arr = np.load(tmp_path / 'tmp.npy')
|
||||
|
||||
assert arr.dtype == np.int32
|
||||
assert arr.shape == (4, 400, 400)
|
||||
assert np.array_equal(arr, np.ones([4, 400, 400], dtype=np.int32))
|
||||
|
||||
np.save(tmp_path / 'tmp2.npy', np.ones([4, 400, 400], dtype=np.int32))
|
||||
assert filecmp.cmp(tmp_path / 'tmp.npy', tmp_path / 'tmp2.npy')
|
||||
|
||||
|
||||
def test_open_old_file(tmp_path):
|
||||
npw = NumpyFileManager(tmp_path / 'tmp.npy', 'w', (4000, ), np.float32)
|
||||
npw.writeOneFrame(np.ones(4000, dtype=np.float32))
|
||||
npw.writeOneFrame(np.ones(4000, dtype=np.float32))
|
||||
npw.close()
|
||||
npw2 = NumpyFileManager(tmp_path / 'tmp.npy', 'r+')
|
||||
assert npw2.frameCount == 2
|
||||
assert npw2.frameShape == (4000, )
|
||||
assert npw2.dtype == np.float32
|
||||
npw2.writeOneFrame(np.ones(4000, dtype=np.float32))
|
||||
del npw2
|
||||
np.save(tmp_path / 'tmp2.npy', np.ones([3, 4000], dtype=np.float32))
|
||||
assert filecmp.cmp(tmp_path / 'tmp.npy', tmp_path / 'tmp2.npy')
|
||||
|
||||
|
||||
@pytest.mark.parametrize('mode', ['w', 'x'])
|
||||
def test_init_parameters2(mode, tmp_path):
|
||||
# test opening files with missing parameters for write
|
||||
with pytest.raises(AssertionError):
|
||||
NumpyFileManager(tmp_path / 'abaababababa.npyx', mode)
|
||||
with pytest.raises(AssertionError):
|
||||
NumpyFileManager(tmp_path / 'abaababababa.npyx2', mode, frameShape=(12, 34))
|
||||
with pytest.raises(AssertionError):
|
||||
NumpyFileManager(tmp_path / 'abaababababa.npyx3', mode, dtype=np.int64)
|
||||
|
||||
# opening new file with required parameters (this should work)
|
||||
NumpyFileManager(tmp_path / 'abaababababa.npyx3', mode, dtype=np.int64, frameShape=(6, 6))
|
||||
assert Path.is_file(tmp_path / 'abaababababa.npyx3')
|
||||
|
||||
|
||||
def test_init_parameters(tmp_path):
|
||||
with pytest.raises(TypeError):
|
||||
NumpyFileManager()
|
||||
|
||||
# test opening file that does not exist
|
||||
with pytest.raises(FileNotFoundError):
|
||||
NumpyFileManager(tmp_path / 'abaababababa.npyx')
|
||||
with pytest.raises(FileNotFoundError):
|
||||
NumpyFileManager(tmp_path / 'abaababababa.npyx2', frameShape=(12, 34))
|
||||
with pytest.raises(FileNotFoundError):
|
||||
NumpyFileManager(tmp_path / 'abaababababa.npyx3', dtype=np.int64)
|
||||
with pytest.raises(FileNotFoundError):
|
||||
NumpyFileManager(tmp_path / 'abaababababa.npyx3', dtype=np.int64, frameShape=(6, 6))
|
||||
|
||||
# re-opening the same file
|
||||
NumpyFileManager(tmp_path / 'abaababababa.npyx3', 'w', dtype=np.int64, frameShape=(6, 6))
|
||||
NumpyFileManager(tmp_path / 'abaababababa.npyx3')
|
||||
|
||||
# re-opening the file with wrong parameters
|
||||
with pytest.raises(AssertionError):
|
||||
NumpyFileManager(tmp_path / 'abaababababa.npyx3', frameShape=(6, 2))
|
||||
with pytest.raises(AssertionError):
|
||||
NumpyFileManager(tmp_path / 'abaababababa.npyx3', dtype=np.int32)
|
||||
with pytest.raises(AssertionError):
|
||||
NumpyFileManager(tmp_path / 'abaababababa.npyx3', dtype=np.float32, frameShape=(5, 5))
|
||||
|
||||
# test resetting an existing file
|
||||
npw = NumpyFileManager(tmp_path / 'tmp4.npy', 'w', dtype=np.float32, frameShape=(5, 5))
|
||||
npw.writeOneFrame(np.ones((5, 5), dtype=np.float32))
|
||||
npw.close()
|
||||
assert np.load(tmp_path / 'tmp4.npy').shape == (1, 5, 5)
|
||||
npw = NumpyFileManager(tmp_path / 'tmp4.npy', 'w', dtype=np.int64, frameShape=(7, 7))
|
||||
npw.flush()
|
||||
assert np.load(tmp_path / 'tmp4.npy').shape == (0, 7, 7)
|
||||
|
||||
# test adding frames with the wrong shape to an existing file
|
||||
with pytest.raises(ValueError, match=r'frame shape given \(9, 4, 4\) '):
|
||||
npw.writeOneFrame(np.ones((9, 4, 4)))
|
||||
|
||||
|
||||
def test_get_item(tmp_path):
|
||||
rng = np.random.default_rng(seed=42)
|
||||
arr = rng.random((1000, 20, 20))
|
||||
npw = NumpyFileManager(tmp_path / 'tmp.npy', 'w', frameShape=(20, 20), dtype=arr.dtype)
|
||||
for frame in arr:
|
||||
npw.writeOneFrame(frame)
|
||||
|
||||
assert np.array_equal(npw[50:100], arr[50:100])
|
||||
assert np.array_equal(npw[0:1], arr[0:1])
|
||||
assert np.array_equal(npw[0:10000], arr)
|
||||
assert np.array_equal(npw[999:1000], arr[999:1000])
|
||||
assert np.array_equal(npw[999:1005], arr[999:1000])
|
||||
assert np.array_equal(npw[49:300], arr[49:300])
|
||||
assert np.array_equal(npw[88:88], arr[88:88])
|
||||
assert np.array_equal(npw[0:0], arr[0:0])
|
||||
assert np.array_equal(npw[0:77], arr[0:77])
|
||||
assert np.array_equal(npw[77:0], arr[77:0])
|
||||
|
||||
with pytest.raises(NotImplementedError):
|
||||
npw[-1:-3]
|
||||
with pytest.raises(NotImplementedError):
|
||||
npw[10:20:2]
|
||||
with pytest.raises(NotImplementedError):
|
||||
npw[-5:-87:5]
|
||||
with pytest.raises(NotImplementedError):
|
||||
npw[-5:-87:-5]
|
||||
|
||||
with pytest.raises(NotImplementedError):
|
||||
npw.readFrames(-1, -4)
|
||||
with pytest.raises(NotImplementedError):
|
||||
npw.readFrames(0, -77)
|
||||
with pytest.raises(NotImplementedError):
|
||||
npw.readFrames(-5, -5)
|
||||
|
||||
|
||||
def test_file_functions(tmp_path):
|
||||
rng = np.random.default_rng(seed=42)
|
||||
arr = rng.random((1000, 20, 20))
|
||||
npw = NumpyFileManager(tmp_path / 'tmp.npy', 'w', frameShape=(20, 20), dtype=arr.dtype)
|
||||
for frame in arr:
|
||||
npw.writeOneFrame(frame)
|
||||
assert np.array_equal(npw.read(10), arr[:10])
|
||||
assert np.array_equal(npw.read(10), arr[10:20])
|
||||
assert np.array_equal(npw.read(10), arr[20:30])
|
||||
npw.readFrames(500, 600)
|
||||
assert np.array_equal(npw.read(10), arr[30:40])
|
||||
npw.readFrames(0, 2)
|
||||
assert np.array_equal(npw.read(100), arr[40:140])
|
||||
npw.writeOneFrame(arr[700])
|
||||
assert np.array_equal(npw.read(5), arr[140:145])
|
||||
npw.seek(900)
|
||||
assert np.array_equal(npw.read(20), arr[900:920])
|
||||
npw.seek(5)
|
||||
npw.readFrames(500, 600)
|
||||
assert np.array_equal(npw.read(10), arr[5:15])
|
||||
|
||||
|
||||
def test_with_statement(tmp_path):
|
||||
arr = np.ones((5, 5))
|
||||
with NumpyFileManager(tmp_path / 'tmp.npy', 'w', (5, 5), arr.dtype) as npw:
|
||||
npw.writeOneFrame(arr)
|
||||
np.save(tmp_path / 'tmp2.npy', np.expand_dims(arr, 0))
|
||||
assert filecmp.cmp(tmp_path / 'tmp2.npy', tmp_path / 'tmp.npy')
|
194
pyctbgui/tests/unit/test_npz_writer.py
Normal file
194
pyctbgui/tests/unit/test_npz_writer.py
Normal file
@ -0,0 +1,194 @@
|
||||
import filecmp
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
from pyctbgui.utils.numpyWriter.npy_writer import NumpyFileManager
|
||||
import numpy as np
|
||||
|
||||
from pyctbgui.utils.numpyWriter.npz_writer import NpzFileWriter
|
||||
|
||||
|
||||
@pytest.mark.parametrize('compressed', [True, False])
|
||||
def test_incremental_npz(compressed, tmp_path):
|
||||
arr1 = np.ones((10, 5, 5))
|
||||
arr2 = np.zeros((10, 5, 5), dtype=np.int32)
|
||||
arr3 = np.ones((10, 5, 5), dtype=np.float32)
|
||||
with NpzFileWriter(tmp_path / 'tmp.npz', 'w', compress_file=compressed) as npz:
|
||||
npz.writeArray('adc', arr1)
|
||||
npz.writeArray('tx', arr2)
|
||||
npz.writeArray('signal', arr3)
|
||||
|
||||
npzFile = np.load(tmp_path / 'tmp.npz')
|
||||
assert sorted(npzFile.files) == sorted(('adc', 'tx', 'signal'))
|
||||
assert np.array_equal(npzFile['adc'], np.ones((10, 5, 5)))
|
||||
assert np.array_equal(npzFile['tx'], np.zeros((10, 5, 5), dtype=np.int32))
|
||||
assert np.array_equal(npzFile['signal'], np.ones((10, 5, 5), dtype=np.float32))
|
||||
if compressed:
|
||||
np.savez_compressed(tmp_path / 'tmp2.npz', adc=arr1, tx=arr2, signal=arr3)
|
||||
else:
|
||||
np.savez(tmp_path / 'tmp2.npz', adc=arr1, tx=arr2, signal=arr3)
|
||||
|
||||
assert filecmp.cmp(tmp_path / 'tmp2.npz', tmp_path / 'tmp.npz')
|
||||
|
||||
|
||||
@pytest.mark.parametrize('compressed', [True, False])
|
||||
def test_zipping_npy_files(compressed, tmp_path):
|
||||
data = {
|
||||
'arr1': np.ones((10, 5, 5)),
|
||||
'arr2': np.zeros((10, 5, 5), dtype=np.int32),
|
||||
'arr3': np.ones((10, 5, 5), dtype=np.float32)
|
||||
}
|
||||
filePaths = [tmp_path / (file + '.npy') for file in data.keys()]
|
||||
for file in data:
|
||||
np.save(tmp_path / (file + '.npy'), data[file])
|
||||
NpzFileWriter.zipNpyFiles(tmp_path / 'file.npz', filePaths, list(data.keys()), compressed=compressed)
|
||||
npz = np.load(tmp_path / 'file.npz')
|
||||
assert npz.files == list(data.keys())
|
||||
for file in data:
|
||||
assert np.array_equal(npz[file], data[file])
|
||||
|
||||
if compressed:
|
||||
np.savez_compressed(tmp_path / 'numpy.npz', **data)
|
||||
else:
|
||||
np.savez(tmp_path / 'numpy.npz', **data)
|
||||
|
||||
numpyz = np.load(tmp_path / 'numpy.npz')
|
||||
for file in data:
|
||||
assert np.array_equal(numpyz[file], npz[file])
|
||||
assert npz.files == numpyz.files
|
||||
|
||||
# different files :(
|
||||
# for some reason numpy savez (most likely a trick with zipfile library) doesn't write the time
|
||||
# of last modification
|
||||
# assert filecmp.cmp(prefix / 'numpy.npz', prefix / 'file.npz')
|
||||
|
||||
|
||||
@pytest.mark.parametrize('compressed', [True, False])
|
||||
def test_npy_writer_with_zipfile_in_init(compressed, tmp_path):
|
||||
npz = NpzFileWriter(tmp_path / 'tmp.npz', 'w', compress_file=compressed)
|
||||
|
||||
rng = np.random.default_rng(42)
|
||||
arr = rng.random((8000, 5, 5))
|
||||
npz.writeArray('adc', arr)
|
||||
with npz.file.open('adc.npy', mode='r') as outfile:
|
||||
npw = NumpyFileManager(outfile)
|
||||
assert np.array_equal(npw.readFrames(720, 7999), arr[720:7999])
|
||||
|
||||
|
||||
def test_compression(tmp_path):
|
||||
arr = np.zeros((1000, 5, 5), dtype=np.int32)
|
||||
with NpzFileWriter(tmp_path / 'tmp.npz', 'w', compress_file=True) as npz:
|
||||
npz.writeArray('adc', arr)
|
||||
|
||||
np.savez(tmp_path / 'tmp2.npz', adc=arr)
|
||||
|
||||
assert Path(tmp_path / 'tmp2.npz').stat().st_size > Path(tmp_path / 'tmp.npz').stat().st_size
|
||||
|
||||
|
||||
@pytest.mark.parametrize('compressed', [True, False])
|
||||
@pytest.mark.parametrize('isPath', [True, False])
|
||||
@pytest.mark.parametrize('deleteOriginals', [True, False])
|
||||
def test_delete_files(compressed, isPath, deleteOriginals, tmp_path):
|
||||
data = {
|
||||
'arr1': np.ones((10, 5, 5)),
|
||||
'arr2': np.zeros((10, 5, 5), dtype=np.int32),
|
||||
'arr3': np.ones((10, 5, 5), dtype=np.float32)
|
||||
}
|
||||
filePaths = [tmp_path / (file + '.npy') for file in data.keys()]
|
||||
for file in data:
|
||||
np.save(tmp_path / (file + '.npy'), data[file])
|
||||
path = tmp_path / 'file.npz'
|
||||
path = str(path) if isPath else path
|
||||
NpzFileWriter.zipNpyFiles(path,
|
||||
filePaths,
|
||||
list(data.keys()),
|
||||
deleteOriginals=deleteOriginals,
|
||||
compressed=compressed)
|
||||
if deleteOriginals:
|
||||
for file in filePaths:
|
||||
assert not Path.exists(file)
|
||||
else:
|
||||
for file in filePaths:
|
||||
assert Path.exists(file)
|
||||
|
||||
|
||||
def test_npz_read_frames(tmp_path):
|
||||
rng = np.random.default_rng(seed=42)
|
||||
arr1 = rng.random((10, 5, 5))
|
||||
|
||||
with NpzFileWriter(tmp_path / 'tmp.npz', 'w') as npz:
|
||||
npz.writeArray('adc', arr1)
|
||||
|
||||
with NpzFileWriter(tmp_path / 'tmp.npz', 'r') as npz:
|
||||
frames = npz.readFrames('adc', 5, 8)
|
||||
assert np.array_equal(frames, arr1[5:8])
|
||||
|
||||
|
||||
def test_file_modes(tmp_path):
|
||||
rng = np.random.default_rng(seed=42)
|
||||
arr1 = rng.random((10, 5, 5))
|
||||
|
||||
# check reopening with mode w
|
||||
with NpzFileWriter(tmp_path / 'tmp.npz', 'w') as npz:
|
||||
npz.writeArray('adc', arr1)
|
||||
|
||||
with NpzFileWriter(tmp_path / 'tmp.npz', 'w') as npz:
|
||||
assert npz.file.namelist() == []
|
||||
|
||||
# check reopening with mode x
|
||||
with NpzFileWriter(tmp_path / 'tmp.npz', 'w') as npz:
|
||||
npz.writeArray('adc', arr1)
|
||||
|
||||
with pytest.raises(FileExistsError):
|
||||
with NpzFileWriter(tmp_path / 'tmp.npz', 'x'):
|
||||
pass
|
||||
# check reopening with mode r
|
||||
with NpzFileWriter(tmp_path / 'tmp.npz', 'r') as npz:
|
||||
assert np.array_equal(npz.readFrames('adc', 4, 6), arr1[4:6])
|
||||
with pytest.raises(ValueError, match=r'write\(\) requires mode \'w\'\, \'x\'\, or \'a\''):
|
||||
npz.writeArray('adc2', arr1)
|
||||
|
||||
|
||||
@pytest.mark.filterwarnings('ignore::UserWarning')
|
||||
def test_file_mode_a(tmp_path):
|
||||
rng = np.random.default_rng(seed=42)
|
||||
arr1 = rng.random((10, 5, 5))
|
||||
# check reopening with mode a
|
||||
with NpzFileWriter(tmp_path / 'tmp.npz', 'w') as npz:
|
||||
npz.writeArray('adc', arr1)
|
||||
|
||||
with NpzFileWriter(tmp_path / 'tmp.npz', 'a') as npz:
|
||||
npz.writeArray('adc2', arr1)
|
||||
npz.writeArray('adc', arr1)
|
||||
|
||||
|
||||
@pytest.mark.parametrize('compressed', [True, False])
|
||||
def test_get_item(compressed, tmp_path):
|
||||
rng = np.random.default_rng(seed=42)
|
||||
arr1 = rng.random((10, 5, 5))
|
||||
arr2 = rng.random((3, 2, 2))
|
||||
# check reopening with mode a
|
||||
npz = NpzFileWriter(tmp_path / 'tmp.npz', 'w', compress_file=compressed)
|
||||
npz.writeArray('adc1', arr1)
|
||||
npz.writeArray('adc2', arr2)
|
||||
npz.writeArray('adc3', arr1)
|
||||
assert np.array_equal(npz['adc1'].read(3), arr1[:3])
|
||||
assert np.array_equal(npz['adc2'].read(1), arr2[:1])
|
||||
assert np.array_equal(npz['adc2'].read(1), arr2[1:2])
|
||||
assert np.array_equal(npz['adc2'].read(1), arr2[2:3])
|
||||
assert np.array_equal(npz['adc1'].read(3), arr1[3:6])
|
||||
assert np.array_equal(npz['adc1'].read(3), arr1[6:9])
|
||||
|
||||
|
||||
@pytest.mark.parametrize('compressed', [True, False])
|
||||
def test_namelist(compressed, tmp_path):
|
||||
rng = np.random.default_rng(seed=42)
|
||||
arr1 = rng.random((10, 5, 5))
|
||||
arr2 = rng.random((3, 2, 2))
|
||||
# check reopening with mode a
|
||||
npz = NpzFileWriter(tmp_path / 'tmp.npz', 'w', compress_file=compressed)
|
||||
npz.writeArray('adc1', arr1)
|
||||
npz.writeArray('adc2', arr2)
|
||||
npz.writeArray('adc3', arr1)
|
||||
assert npz.namelist() == ['adc1', 'adc2', 'adc3']
|
@ -10,7 +10,14 @@ import sys
|
||||
from setuptools import setup, find_packages
|
||||
from pybind11.setup_helpers import Pybind11Extension, build_ext
|
||||
|
||||
__version__ = os.environ.get('GIT_DESCRIBE_TAG', 'developer')
|
||||
|
||||
import subprocess
|
||||
def get_git_tag():
|
||||
try:
|
||||
return subprocess.check_output(['git', 'describe', '--tags', '--abbrev=0']).strip().decode('utf-8')
|
||||
except subprocess.CalledProcessError:
|
||||
return 'developer'
|
||||
__version__ = get_git_tag()
|
||||
|
||||
|
||||
def get_conda_path():
|
||||
|
@ -28,3 +28,13 @@ scanParameters = _slsdet.scanParameters
|
||||
currentSrcParameters = _slsdet.currentSrcParameters
|
||||
DurationWrapper = _slsdet.DurationWrapper
|
||||
pedestalParameters = _slsdet.pedestalParameters
|
||||
|
||||
|
||||
import subprocess
|
||||
def get_git_tag():
|
||||
try:
|
||||
return subprocess.check_output(['git', 'describe', '--tags', '--abbrev=0']).strip().decode('utf-8')
|
||||
except subprocess.CalledProcessError:
|
||||
return 'developer'
|
||||
__version__ = get_git_tag()
|
||||
|
||||
|
@ -743,7 +743,7 @@ class Detector(CppDetectorApi):
|
||||
@property
|
||||
@element
|
||||
def nextframenumber(self):
|
||||
"""[Eiger][Jungfrau][Moench][CTB][Xilinx CTB] Next frame number. Stopping acquisition might result in different frame numbers for different modules. """
|
||||
"""[Eiger][Jungfrau][Moench][CTB][Xilinx CTB][Gotthard2] Next frame number. Stopping acquisition might result in different frame numbers for different modules. So, after stopping, next frame number (max + 1) is set for all the modules afterwards."""
|
||||
return self.getNextFrameNumber()
|
||||
|
||||
@nextframenumber.setter
|
||||
@ -1043,7 +1043,7 @@ class Detector(CppDetectorApi):
|
||||
|
||||
Note
|
||||
----
|
||||
If path does not exist, it will try to create it.
|
||||
If path does not exist and fwrite enabled, it will try to create it at start of acquisition.
|
||||
|
||||
Example
|
||||
--------
|
||||
@ -1059,7 +1059,7 @@ class Detector(CppDetectorApi):
|
||||
@property
|
||||
@element
|
||||
def fwrite(self):
|
||||
"""Enable or disable receiver file write. Default is enabled. """
|
||||
"""Enable or disable receiver file write. Default is disabled. """
|
||||
return self.getFileWrite()
|
||||
|
||||
@fwrite.setter
|
||||
@ -1210,31 +1210,6 @@ class Detector(CppDetectorApi):
|
||||
else:
|
||||
raise ValueError("Unknown argument type")
|
||||
|
||||
@property
|
||||
@element
|
||||
def rx_zmqip(self):
|
||||
"""
|
||||
Zmq Ip Address from which data is to be streamed out of the receiver.
|
||||
|
||||
Note
|
||||
-----
|
||||
Also restarts receiver zmq streaming if enabled. \n
|
||||
Default is from rx_hostname. \n
|
||||
Modified only when using an intermediate process after receiver.
|
||||
|
||||
Example
|
||||
-------
|
||||
>>> d.rx_zmqip
|
||||
192.168.0.101
|
||||
>>> d.rx_zmqip = '192.168.0.101'
|
||||
"""
|
||||
return self.getRxZmqIP()
|
||||
|
||||
@rx_zmqip.setter
|
||||
def rx_zmqip(self, ip):
|
||||
ip = ut.make_ip(ip) #Convert from int or string to IpAddr
|
||||
ut.set_using_dict(self.setRxZmqIP, ip)
|
||||
|
||||
@property
|
||||
@element
|
||||
def zmqip(self):
|
||||
@ -2014,23 +1989,59 @@ class Detector(CppDetectorApi):
|
||||
|
||||
@property
|
||||
def versions(self):
|
||||
version_list = {'type': self.type,
|
||||
'package': self.packageversion,
|
||||
'client': self.clientversion}
|
||||
type = "Unknown"
|
||||
firmware = "Unknown"
|
||||
detectorserver = "Unknown"
|
||||
kernel = "Unknown"
|
||||
hardware = "Unknown"
|
||||
receiverversion = "Unknown"
|
||||
eiger = False
|
||||
firmware_febl = "Unknown"
|
||||
firmware_febr = "Unknown"
|
||||
firmware_beb = "Unknown"
|
||||
receiver_in_shm = False
|
||||
|
||||
if self.type == detectorType.EIGER:
|
||||
version_list ['firmware (Beb)'] = self.firmwareversion
|
||||
version_list ['firmware(Febl)'] = self.getFrontEndFirmwareVersion(slsDetectorDefs.fpgaPosition.FRONT_LEFT)
|
||||
version_list ['firmware (Febr)'] = self.getFrontEndFirmwareVersion(slsDetectorDefs.fpgaPosition.FRONT_RIGHT)
|
||||
release = self.packageversion
|
||||
client = self.clientversion
|
||||
|
||||
if self.nmod != 0:
|
||||
# shared memory has detectors
|
||||
type = self.type
|
||||
eiger = (self.type == detectorType.EIGER)
|
||||
receiver_in_shm = self.use_receiver
|
||||
if receiver_in_shm:
|
||||
# cannot connect to receiver
|
||||
try:
|
||||
receiverversion = self.rx_version
|
||||
except Exception as e:
|
||||
pass
|
||||
# cannot connect to Detector
|
||||
try:
|
||||
firmware = self.firmwareversion
|
||||
detectorserver = self.detectorserverversion
|
||||
kernel = self.kernelversion
|
||||
hardware = self.hardwareversion
|
||||
if eiger:
|
||||
firmware_beb = self.firmwareversion
|
||||
firmware_febl = self.getFrontEndFirmwareVersion(slsDetectorDefs.fpgaPosition.FRONT_LEFT)
|
||||
firmware_febr = self.getFrontEndFirmwareVersion(slsDetectorDefs.fpgaPosition.FRONT_RIGHT)
|
||||
except Exception as e:
|
||||
pass
|
||||
|
||||
version_list = {'type': {type},
|
||||
'package': {release},
|
||||
'client': {client}}
|
||||
if eiger:
|
||||
version_list ['firmware (Beb)'] = {firmware_beb}
|
||||
version_list ['firmware(Febl)'] = {firmware_febl}
|
||||
version_list ['firmware (Febr)'] = {firmware_febr}
|
||||
else:
|
||||
version_list ['firmware'] = self.firmwareversion
|
||||
|
||||
version_list ['detectorserver'] = self.detectorserverversion
|
||||
version_list ['kernel'] = self.kernelversion
|
||||
version_list ['hardware'] = self.hardwareversion
|
||||
|
||||
if self.use_receiver:
|
||||
version_list ['receiver'] = self.rx_version
|
||||
version_list ['firmware'] = {firmware}
|
||||
version_list ['detectorserver'] = {detectorserver}
|
||||
version_list ['kernel'] = kernel
|
||||
version_list ['hardware'] = hardware
|
||||
if receiver_in_shm:
|
||||
version_list ['receiver'] = {receiverversion}
|
||||
|
||||
return version_list
|
||||
|
||||
@ -2100,7 +2111,7 @@ class Detector(CppDetectorApi):
|
||||
|
||||
Note
|
||||
-----
|
||||
[Jungfrau][Moench] FULL_SPEED, HALF_SPEED (Default), QUARTER_SPEED
|
||||
[Jungfrau][Moench][Mythen3] FULL_SPEED, HALF_SPEED (Default), QUARTER_SPEED
|
||||
[Eiger] FULL_SPEED (Default), HALF_SPEED, QUARTER_SPEED
|
||||
[Moench] FULL_SPEED (Default), HALF_SPEED, QUARTER_SPEED
|
||||
[Gottthard2] G2_108MHZ (Default), G2_144MHZ
|
||||
@ -2899,10 +2910,36 @@ class Detector(CppDetectorApi):
|
||||
def pedestalmode(self, value):
|
||||
ut.set_using_dict(self.setPedestalMode, value)
|
||||
|
||||
@property
|
||||
@element
|
||||
def timing_info_decoder(self):
|
||||
"""[Jungfrau] [Jungfrau] Advanced Command and only for SWISSFEL and SHINE. Sets the bunch id or timing info decoder. Default is SWISSFEL.
|
||||
Enum: timingInfoDecoder
|
||||
"""
|
||||
return self.getTimingInfoDecoder()
|
||||
|
||||
@timing_info_decoder.setter
|
||||
def timing_info_decoder(self, value):
|
||||
ut.set_using_dict(self.setTimingInfoDecoder, value)
|
||||
|
||||
@property
|
||||
@element
|
||||
def collectionmode(self):
|
||||
"""[Jungfrau] Sets collection mode to HOLE or ELECTRON. Default is HOLE.
|
||||
Enum: collectionMode
|
||||
"""
|
||||
return self.getCollectionMode()
|
||||
|
||||
@collectionmode.setter
|
||||
def collectionmode(self, value):
|
||||
ut.set_using_dict(self.setCollectionMode, value)
|
||||
|
||||
@property
|
||||
def maxclkphaseshift(self):
|
||||
"""
|
||||
[Gotthard2][Mythen3] Absolute maximum Phase shift of clocks.
|
||||
[Gotthard2][Mythen3] Absolute maximum Phase shift of clocks.\n
|
||||
[Gotthard2] Clock index range: 0-5\n
|
||||
[Mythen3] Clock index range: 0
|
||||
|
||||
:setter: Not Implemented
|
||||
|
||||
@ -3963,7 +4000,9 @@ class Detector(CppDetectorApi):
|
||||
@property
|
||||
def clkphase(self):
|
||||
"""
|
||||
[Gotthard2][Mythen3] Phase shift of all clocks.
|
||||
[Gotthard2][Mythen3] Phase shift of all clocks.\n
|
||||
[Gotthard2] Clock index range: 0-5\n
|
||||
[Mythen3] Clock index range: 0
|
||||
|
||||
Example
|
||||
-------
|
||||
@ -3981,7 +4020,9 @@ class Detector(CppDetectorApi):
|
||||
@property
|
||||
def clkdiv(self):
|
||||
"""
|
||||
[Gotthard2][Mythen3] Clock Divider of all clocks. Must be greater than 1.
|
||||
[Gotthard2][Mythen3] Clock Divider of all clocks. Must be greater than 1.\n
|
||||
[Gotthard2] Clock index range: 0-5\n
|
||||
[Mythen3] Clock index range: 0
|
||||
|
||||
Example
|
||||
-------
|
||||
@ -4037,7 +4078,10 @@ class Detector(CppDetectorApi):
|
||||
@property
|
||||
def clkfreq(self):
|
||||
"""
|
||||
[Gotthard2][Mythen3] Frequency of clock in Hz.
|
||||
[Gotthard2][Mythen3] Frequency of clock in Hz.\n
|
||||
[Gotthard2] Clock index range: 0-5\n
|
||||
[Mythen3] Clock index range: 0
|
||||
|
||||
|
||||
:setter: Not implemented. Use clkdiv to set frequency
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user