diff --git a/CMakeLists.txt b/CMakeLists.txt index d7d325436..6124fd40f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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 diff --git a/ctbGui/CMakeLists.txt b/ctbGui/CMakeLists.txt deleted file mode 100644 index 1799bddc5..000000000 --- a/ctbGui/CMakeLists.txt +++ /dev/null @@ -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 - -) - diff --git a/ctbGui/Makefile.root5 b/ctbGui/Makefile.root5 deleted file mode 100644 index 050acbc17..000000000 --- a/ctbGui/Makefile.root5 +++ /dev/null @@ -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) - diff --git a/ctbGui/Makefile.root6 b/ctbGui/Makefile.root6 deleted file mode 100644 index 338949617..000000000 --- a/ctbGui/Makefile.root6 +++ /dev/null @@ -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) - diff --git a/ctbGui/ctbAcquisition.cpp b/ctbGui/ctbAcquisition.cpp deleted file mode 100644 index 8de365271..000000000 --- a/ctbGui/ctbAcquisition.cpp +++ /dev/null @@ -1,2277 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-other -// Copyright (C) 2021 Contributors to the SLS Detector Package -//#define TESTADC - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -#include -#include -#include -#include - -#include "ctbAcquisition.h" -#include "ctbDefs.h" -#include "sls/Detector.h" -#include "sls/sls_detector_defs.h" -#include "ctbMain.h" -#include "moench03CtbData.h" -//#include "moench03TCtbData.h" -//#include "moench03T1CtbData.h" -#include "moench03CommonMode.h" -#include "moench03T1ZmqDataNew.h" -#include "moench02CtbData.h" -//#include "jungfrau10ModuleData.h" -#include "moenchCommonMode.h" -#include "singlePhotonDetector.h" -#include "Mythen3_01_jctbData.h" -#include "Mythen3_02_jctbData.h" -#include "adcSar2_jctbData.h" -#include "moench04CtbZmqData.h" -#include "moench04CtbZmq10GbData.h" -#include "deserializer.h" -#include "sls/detectorData.h" -#include "imageZmq16bit.h" -#include "imageZmq32bit.h" - - -using namespace std; - - - - -ctbAcquisition::ctbAcquisition(TGVerticalFrame *page, sls::Detector *det) : TGGroupFrame(page,"Acquisition",kVerticalFrame), myDet(det), myCanvas(NULL), globalPlot(0), tenG(0), nAnalogSamples(1), nDigitalSamples(1), dataStructure(NULL), photonFinder(NULL), cmSub(0), dBitMask(0xffffffffffffffff), deserializer(0) { - - adcFit=NULL; - bitPlot=NULL; - countsFit=NULL; - - page->AddFrame(this,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 10,10,10,10)); - MapWindow(); - - TGHorizontalFrame *hframe=new TGHorizontalFrame(this, 800,50); - AddFrame(hframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 10,10,10,10)); - hframe->MapWindow(); - - char tit[100]; - - cout << "outfile "<< endl; - - cFileSave= new TGCheckButton(hframe, "Output file: "); - hframe->AddFrame(cFileSave,new TGLayoutHints(kLHintsTop | kLHintsLeft | kLHintsExpandX, 5, 5, 5, 5)); - cFileSave->MapWindow(); - cFileSave->SetTextJustify(kTextRight); - cFileSave->Connect("Toggled(Bool_t)","ctbAcquisition",this,"setFsave(Bool_t)"); - - std::string temp = "run"; - try { - temp = myDet->getFileNamePrefix().tsquash("Different values"); - } CATCH_DISPLAY ("Could not get file name prefix.", "ctbAcquisition::ctbAcquisition") - eFname = new TGTextEntry(hframe, temp.c_str()); - - hframe->AddFrame(eFname,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 5, 5, 5, 5)); - eFname->MapWindow(); - eFname->Resize(150,30); - - eFname->Connect("ReturnPressed()","ctbAcquisition",this,"setFname()"); - - - TGLabel *label=new TGLabel(hframe,"index: "); - hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 5, 5, 5, 5)); - label->MapWindow(); - label->SetTextJustify(kTextRight); - - - eFindex = new TGNumberEntry(hframe, 0, 9,999, TGNumberFormat::kNESInteger, - TGNumberFormat::kNEANonNegative, - TGNumberFormat::kNELNoLimits); - hframe->AddFrame( eFindex,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 1, 1, 1, 1)); - eFindex->MapWindow(); - eFindex->Resize(150,30); - TGTextEntry *e= eFindex->TGNumberEntry::GetNumberEntry(); - e->Connect("ReturnPressed()","ctbAcquisition",this,"setFindex()"); - - - - - cout << "outdir "<< endl; - - - hframe=new TGHorizontalFrame(this, 800,50); - AddFrame(hframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 10,10,10,10)); - hframe->MapWindow(); - - label=new TGLabel(hframe,"Output directory: "); - hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 5, 5, 5, 5)); - label->MapWindow(); - label->SetTextJustify(kTextRight); - - - - temp = "/tmp/"; - try { - temp = myDet->getFilePath().tsquash("Different values"); - } CATCH_DISPLAY ("Could not get file path.", "ctbAcquisition::ctbAcquisition") - eOutdir = new TGTextEntry(hframe, temp.c_str()); - - hframe->AddFrame(eOutdir,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 5, 5, 5, 5)); - eOutdir->MapWindow(); - eOutdir->Resize(150,30); - - - eOutdir->Connect("ReturnPressed()","ctbAcquisition",this,"setOutdir()"); - - hframe=new TGHorizontalFrame(this, 800,50); - AddFrame(hframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 10,10,10,10)); - hframe->MapWindow(); - - - cout << "meas "<< endl; -label=new TGLabel(hframe,"Number of Measurements (fake): "); - hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 5, 5, 5, 5)); - label->MapWindow(); - label->SetTextJustify(kTextRight); - - - eMeasurements = new TGNumberEntry(hframe, 0, 9,999, TGNumberFormat::kNESInteger, - TGNumberFormat::kNEANonNegative, - TGNumberFormat::kNELNoLimits); - hframe->AddFrame( eMeasurements,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 1, 1, 1, 1)); - eMeasurements->MapWindow(); - eMeasurements->Resize(150,30); - eMeasurements->SetNumber(1); - e= eMeasurements->TGNumberEntry::GetNumberEntry(); - e->Connect("ReturnPressed()","ctbAcquisition",this,"setMeasurements()"); - - - - -hframe=new TGHorizontalFrame(this, 800,50); - AddFrame(hframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 10,10,10,10)); - hframe->MapWindow(); - - - - - cout << "pattern "<< endl; - - - - - cCompile= new TGCheckButton(hframe, "Compile"); - hframe->AddFrame(cCompile,new TGLayoutHints(kLHintsTop | kLHintsLeft | kLHintsExpandX, 5, 5, 5, 5)); - cCompile->MapWindow(); - cCompile->SetOn(); - // cCompile->Connect("Toggled(Bool_t)","ctbAcquisition",this,"setFsave(Bool_t)"); - - - cLoad= new TGTextButton(hframe, "Load"); - hframe->AddFrame(cLoad,new TGLayoutHints(kLHintsTop | kLHintsLeft | kLHintsExpandX, 5, 5, 5, 5)); - cLoad->MapWindow(); - cLoad->Connect("Clicked()","ctbAcquisition",this,"loadPattern()"); - - -// cRun= new TGCheckButton(hframe, "Run"); -// hframe->AddFrame(cRun,new TGLayoutHints(kLHintsTop | kLHintsLeft | kLHintsExpandX, 5, 5, 5, 5)); -// cRun->MapWindow(); -// // cCompile->Connect("Toggled(Bool_t)","ctbAcquisition",this,"setFsave(Bool_t)"); - - - - - - - bStatus=new TGTextButton(hframe, "Start"); - hframe->AddFrame(bStatus,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 5, 5, 5, 5)); - bStatus->MapWindow(); - bStatus->Connect("Clicked()","ctbAcquisition",this,"toggleAcquisition()"); - - - - - - cout << "plot "<< endl; - - hframe=new TGHorizontalFrame(this, 800,50); - AddFrame(hframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 10,10,10,10)); - hframe->MapWindow(); - - - - - label=new TGLabel(hframe,"Plot: "); - hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 5, 5, 5, 5)); - label->MapWindow(); - label->SetTextJustify(kTextRight); - - - - - - - TGButtonGroup *bgPlot = new TGButtonGroup(hframe); - // horizontal->SetTitlePos(TGGroupFrame::kCenter); - rbPlotOff=new TGRadioButton(hframe, "No plot"); - rbWaveform=new TGRadioButton(hframe, "Waveform"); - rbDistribution=new TGRadioButton(hframe, "Distribution"); - rb2D=new TGRadioButton(hframe, "Image"); - // rbScan=new TGRadioButton(hframe, "Scan"); - - cbDetType=new TGComboBox(hframe); - // enum {DESERIALIZER, MOENCH04, MOENCH02, ADCSAR2, MYTHEN301, MYTHEN302, MAXDET}; - cbDetType->AddEntry("Deserializer", DESERIALIZER); - cbDetType->AddEntry("MOENCH02", MOENCH02); - cbDetType->AddEntry("MOENCH04", MOENCH04); - // cbDetType->AddEntry("JUNGFRAU1.0", 2); - cbDetType->AddEntry("MOENCH03",MOENCH03); - cbDetType->AddEntry("IMAGE32BIT",IMAGE32B); - cbDetType->AddEntry("IMAGE16BIT",IMAGE16B); - - //cbDetType->AddEntry("MOENCH03", iiii++); - // cbDetType->AddEntry("MYTHEN3 0.1", MYTHEN301); - // cbDetType->AddEntry("ADCSAR2", ADCSAR2); - // cbDetType->AddEntry("MYTHEN3 0.2", MYTHEN302); - - cbDetType->SetHeight(20); - cbDetType->Select(0); - - bgPlot->Insert(rbPlotOff,0); - bgPlot->Insert(rbWaveform,1); - bgPlot->Insert(rbDistribution,2); - bgPlot->Insert(rb2D,3); - // bgPlot->Insert(rbScan,4); - - bgPlot->Connect("Clicked(Int_t)", "ctbAcquisition", this, "changePlot(Int_t)"); - // hframe->AddFrame(bgPlot, new TGLayoutHints(kLHintsExpandX)); - - cbDetType->Connect("Selected(Int_t)", "ctbAcquisition",this, "changeDetector(Int_t)"); - hframe->AddFrame(rbPlotOff, new TGLayoutHints(kLHintsTop | kLHintsExpandX)); - hframe->AddFrame(rbWaveform, new TGLayoutHints(kLHintsTop | kLHintsExpandX)); - hframe->AddFrame(rbDistribution, new TGLayoutHints(kLHintsTop | kLHintsExpandX)); - hframe->AddFrame(rb2D, new TGLayoutHints(kLHintsTop | kLHintsExpandX)); - // hframe->AddFrame(rbScan, new TGLayoutHints(kLHintsTop | kLHintsExpandX)); - hframe->AddFrame(cbDetType, new TGLayoutHints(kLHintsTop | kLHintsExpandX| kLHintsExpandY)); - - - bgPlot->SetExclusive(kTRUE); - rbWaveform->SetOn(); - rbPlotOff->MapWindow(); - rbWaveform->MapWindow(); - rbDistribution->MapWindow(); - rb2D->MapWindow(); - // rbScan->MapWindow(); - cbDetType->MapWindow(); - - - - - // cout << "off "<< endl; - - - hframe=new TGHorizontalFrame(this, 800,50); - AddFrame(hframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 10,10,10,10)); - hframe->MapWindow(); - - - - label=new TGLabel(hframe,"Serial offset:"); - hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 5, 5, 5, 5)); - label->MapWindow(); - label->SetTextJustify(kTextRight); - - - eSerOff=new TGNumberEntry(hframe, 0, 9,999, TGNumberFormat::kNESInteger, - TGNumberFormat::kNEANonNegative, - TGNumberFormat::kNELLimitMinMax,0,16535); - hframe->AddFrame(eSerOff,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 1, 1, 1, 1)); - eSerOff->MapWindow(); - eSerOff->SetNumber(0); - e= eSerOff->TGNumberEntry::GetNumberEntry(); - eSerOff->Connect("ValueSet(Long_t)","ctbAcquisition",this,"ChangeSerialOffset(Long_t)"); - e->Connect("ReturnPressed()","ctbAcquisition",this,"ChangeSerialOffset()"); - - - label=new TGLabel(hframe,"N counters:"); - hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 5, 5, 5, 5)); - label->MapWindow(); - label->SetTextJustify(kTextRight); - - - eNumCount=new TGNumberEntry(hframe, 0, 9,999, TGNumberFormat::kNESInteger, - TGNumberFormat::kNEANonNegative, - TGNumberFormat::kNELLimitMinMax,0,16535); - hframe->AddFrame(eNumCount,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 1, 1, 1, 1)); - eNumCount->MapWindow();; - eNumCount->SetNumber(128*3); - e= eNumCount->TGNumberEntry::GetNumberEntry(); - eNumCount->Connect("ValueSet(Long_t)","ctbAcquisition",this,"ChangeNumberOfChannels(Long_t)"); - e->Connect("ReturnPressed()","ctbAcquisition",this,"ChangeNumberOfChannels()"); - - - - cout << "dr "<< endl; - - label=new TGLabel(hframe,"Dynamic Range:"); - hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 5, 5, 5, 5)); - label->MapWindow(); - label->SetTextJustify(kTextRight); - - - eDynRange=new TGNumberEntry(hframe, 0, 9,999, TGNumberFormat::kNESInteger, - TGNumberFormat::kNEANonNegative, - TGNumberFormat::kNELLimitMinMax,0,16535); - hframe->AddFrame(eDynRange,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 1, 1, 1, 1)); - eDynRange->MapWindow();; - eDynRange->SetNumber(24); - e= eDynRange->TGNumberEntry::GetNumberEntry(); - eDynRange->Connect("ValueSet(Long_t)","ctbAcquisition",this,"ChangeDynamicRange(Long_t)"); - e->Connect("ReturnPressed()","ctbAcquisition",this,"ChangeDynamicRange()"); - - - - - - hframe=new TGHorizontalFrame(this, 800,50); - AddFrame(hframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 10,10,10,10)); - hframe->MapWindow(); - - - - label=new TGLabel(hframe,"Image Pixels"); - hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 5, 5, 5, 5)); - label->MapWindow(); - label->SetTextJustify(kTextLeft); - - - label=new TGLabel(hframe,"X: "); - hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 5, 5, 5, 5)); - label->MapWindow(); - label->SetTextJustify(kTextRight); - - - ePixX=new TGNumberEntry(hframe, 0, 9,999, TGNumberFormat::kNESInteger, - TGNumberFormat::kNEANonNegative, - TGNumberFormat::kNELLimitMinMax,0,16535); - hframe->AddFrame(ePixX,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 1, 1, 1, 1)); - ePixX->MapWindow(); - ePixX->SetNumber(400); - e= ePixX->TGNumberEntry::GetNumberEntry(); - ePixX->Connect("ValueSet(Long_t)","ctbAcquisition",this,"ChangeImagePixels(Long_t)"); - e->Connect("ReturnPressed()","ctbAcquisition",this,"ChangeImagePixels()"); - - - - label=new TGLabel(hframe,"Y: "); - hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 5, 5, 5, 5)); - label->MapWindow(); - label->SetTextJustify(kTextRight); - - - ePixY=new TGNumberEntry(hframe, 0, 9,999, TGNumberFormat::kNESInteger, - TGNumberFormat::kNEANonNegative, - TGNumberFormat::kNELLimitMinMax,0,16535); - hframe->AddFrame(ePixY,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 1, 1, 1, 1)); - ePixY->MapWindow(); - ePixY->SetNumber(400); - e= ePixY->TGNumberEntry::GetNumberEntry(); - ePixY->Connect("ValueSet(Long_t)","ctbAcquisition",this,"ChangeImagePixels(Long_t)"); - e->Connect("ReturnPressed()","ctbAcquisition",this,"ChangeImagePixels()"); - - - - - hframe=new TGHorizontalFrame(this, 800,50); - AddFrame(hframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 10,10,10,10)); - hframe->MapWindow(); - - - - label=new TGLabel(hframe,"Pedestal "); - hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 5, 5, 5, 5)); - label->MapWindow(); - label->SetTextJustify(kTextRight); - - - - cbGetPedestal= new TGCheckButton(hframe, "Acquire"); - hframe->AddFrame(cbGetPedestal,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 5, 5, 5, 5)); - cbGetPedestal->MapWindow(); - - cbSubtractPedestal= new TGCheckButton(hframe, "Subtract"); - hframe->AddFrame(cbSubtractPedestal,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 5, 5, 5, 5)); - cbSubtractPedestal->MapWindow(); - - - cbSubtractPedestal->Connect("Toggled(Bool_t)","ctbAcquisition",this,"TogglePedSub(Bool_t)"); - - cbCommonMode= new TGCheckButton(hframe, "Common Mode"); - hframe->AddFrame(cbCommonMode,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 5, 5, 5, 5)); - cbCommonMode->MapWindow(); - - - cbCommonMode->Connect("Toggled(Bool_t)","ctbAcquisition",this,"ToggleCommonMode(Bool_t)"); - - - bResetPedestal= new TGTextButton(hframe, "Reset"); - hframe->AddFrame(bResetPedestal,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 5, 5, 5, 5)); - bResetPedestal->MapWindow(); - - - bResetPedestal->Connect("Clicked()","ctbAcquisition",this,"resetPedestal()"); - - - - - - hframe=new TGHorizontalFrame(this, 800,50); - AddFrame(hframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 10,10,10,10)); - hframe->MapWindow(); - - - cMinMaxRaw=new TGCheckButton(hframe,"Raw data "); - hframe->AddFrame(cMinMaxRaw,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 5, 5, 5, 5)); - cMinMaxRaw->MapWindow(); - cMinMaxRaw->Connect("Toggled(Bool_t)","ctbAcquisition",this,"ChangeHistoLimitsRaw(Bool_t)"); - - - - - label=new TGLabel(hframe,"Min: "); - hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 5, 5, 5, 5)); - label->MapWindow(); - label->SetTextJustify(kTextRight); - - - eMinRaw=new TGNumberEntry(hframe, 0, 9,999, TGNumberFormat::kNESInteger, - TGNumberFormat::kNEANonNegative, - TGNumberFormat::kNELLimitMinMax,0,16535); - hframe->AddFrame(eMinRaw,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 1, 1, 1, 1)); - eMinRaw->MapWindow();; - eMinRaw->SetNumber(0); - e= eMinRaw->TGNumberEntry::GetNumberEntry(); - eMinRaw->Connect("ValueSet(Long_t)","ctbAcquisition",this,"ChangeHistoLimitsRaw(Long_t)"); - e->Connect("ReturnPressed()","ctbAcquisition",this,"ChangeHistoLimitsRaw()"); - - - label=new TGLabel(hframe,"Max: "); - hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 5, 5, 5, 5)); - label->MapWindow(); - label->SetTextJustify(kTextRight); - - - - - eMaxRaw=new TGNumberEntry(hframe, 0, 9,999, TGNumberFormat::kNESInteger, - TGNumberFormat::kNEANonNegative, - TGNumberFormat::kNELLimitMinMax,0,16535); - hframe->AddFrame(eMaxRaw,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 1, 1, 1, 1)); - eMaxRaw->MapWindow();; - eMaxRaw->SetNumber(16535); - - e= eMaxRaw->TGNumberEntry::GetNumberEntry(); - eMaxRaw->Connect("ValueSet(Long_t)","ctbAcquisition",this,"ChangeHistoLimitsRaw(Long_t)"); - e->Connect("ReturnPressed()","ctbAcquisition",this,"ChangeHistoLimitsRaw()"); - - - hframe=new TGHorizontalFrame(this, 800,50); - AddFrame(hframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 10,10,10,10)); - hframe->MapWindow(); - - - - cMinMaxPedSub=new TGCheckButton(hframe,"Pedestal Subtracted "); - hframe->AddFrame(cMinMaxPedSub,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 5, 5, 5, 5)); - cMinMaxPedSub->MapWindow(); - cMinMaxPedSub->Connect("Toggled(Bool_t)","ctbAcquisition",this,"ChangeHistoLimitsPedSub(Bool_t)"); - - - label=new TGLabel(hframe,"Min: "); - hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 5, 5, 5, 5)); - label->MapWindow(); - label->SetTextJustify(kTextRight); - - - eMinPedSub=new TGNumberEntry(hframe, 0, 9,999, TGNumberFormat::kNESInteger, - TGNumberFormat::kNEAAnyNumber, - TGNumberFormat::kNELLimitMinMax,-16535,16535); - hframe->AddFrame(eMinPedSub,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 1, 1, 1, 1)); - eMinPedSub->MapWindow();; - eMinPedSub->SetNumber(-100); - - e= eMinPedSub->TGNumberEntry::GetNumberEntry(); - - eMinPedSub->Connect("ValueSet(Long_t)","ctbAcquisition",this,"ChangeHistoLimitsPedSub(Long_t)"); - e->Connect("ReturnPressed()","ctbAcquisition",this,"ChangeHistoLimitsPedSub()"); - - - label=new TGLabel(hframe,"Max: "); - hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 5, 5, 5, 5)); - label->MapWindow(); - label->SetTextJustify(kTextRight); - - - eMaxPedSub=new TGNumberEntry(hframe,0, 9,999, TGNumberFormat::kNESInteger, - TGNumberFormat::kNEAAnyNumber, - TGNumberFormat::kNELLimitMinMax,-16535,16535); - hframe->AddFrame(eMaxPedSub,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 1, 1, 1, 1)); - eMaxPedSub->MapWindow();; - eMaxPedSub->SetNumber(100); - - - e= eMaxPedSub->TGNumberEntry::GetNumberEntry(); - eMaxPedSub->Connect("ValueSet(Long_t)","ctbAcquisition",this,"ChangeHistoLimitsPedSub(Long_t)"); - e->Connect("ReturnPressed()","ctbAcquisition",this,"ChangeHistoLimitsPedSub()"); - - - hframe=new TGHorizontalFrame(this, 800,50); - AddFrame(hframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 10,10,10,10)); - hframe->MapWindow(); - - - - - - TGTextButton *b= new TGTextButton(hframe, "Fit Panel ADC:"); - hframe->AddFrame(b,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 5, 5, 5, 5)); - b->MapWindow(); - - - b->Connect("Clicked()","ctbAcquisition",this,"FitADC()"); - - - eFitADC=new TGNumberEntry(hframe, 0, 9,999, TGNumberFormat::kNESInteger, - TGNumberFormat::kNEANonNegative, - TGNumberFormat::kNELLimitMinMax,0,31); - hframe->AddFrame( eFitADC,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 1, 1, 1, 1)); - eFitADC->MapWindow();; - - - - hframe=new TGHorizontalFrame(this, 800,50); - AddFrame(hframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 10,10,10,10)); - hframe->MapWindow(); - - - - - - b= new TGTextButton(hframe, "Plot bit:"); - hframe->AddFrame(b,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 5, 5, 5, 5)); - b->MapWindow(); - - - b->Connect("Clicked()","ctbAcquisition",this,"plotBit()"); - - - eBitPlot=new TGNumberEntry(hframe, 0, 9,999, TGNumberFormat::kNESInteger, - TGNumberFormat::kNEANonNegative, - TGNumberFormat::kNELLimitMinMax,0,64); - hframe->AddFrame( eBitPlot,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 1, 1, 1, 1)); - eBitPlot->MapWindow();; - - - - - - hframe=new TGHorizontalFrame(this, 800,50); - AddFrame(hframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 10,10,10,10)); - hframe->MapWindow(); - - - - label=new TGLabel(hframe,"X "); - hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 5, 5, 5, 5)); - label->MapWindow(); - label->SetTextJustify(kTextRight); - - - label=new TGLabel(hframe," "); - hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 5, 5, 5, 5)); - label->MapWindow(); - label->SetTextJustify(kTextLeft); - lClickX=label; - - - - label=new TGLabel(hframe,"Y "); - hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 5, 5, 5, 5)); - label->MapWindow(); - label->SetTextJustify(kTextRight); - - - - label=new TGLabel(hframe," "); - hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 5, 5, 5, 5)); - label->MapWindow(); - label->SetTextJustify(kTextLeft); - lClickY=label; - - - label=new TGLabel(hframe,"Value "); - hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 5, 5, 5, 5)); - label->MapWindow(); - label->SetTextJustify(kTextRight); - - - - - - label=new TGLabel(hframe," "); - hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 5, 5, 5, 5)); - label->MapWindow(); - label->SetTextJustify(kTextLeft); - lClickValue=label; - - - - - - - - b= new TGTextButton(hframe, "Refresh"); - hframe->AddFrame(b,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 5, 5, 5, 5)); - b->MapWindow(); - - - b->Connect("Clicked()","ctbAcquisition",this,"Draw()"); - - - - - - - - - - - acqThread = new TThread("acqThread", - ctbAcquisition::ThreadHandle,(void*)this); - - cout <<"Registering data callback" << endl; - try { - myDet->registerDataCallback(&dataCallback, (void*)this); - } CATCH_DISPLAY ("Could not get register call back.", "ctbAcquisition::ctbAcquisition") - try { - myDet->setRxZmqDataStream(true); - } CATCH_DISPLAY ("Could not get set RxZmqDataStream.", "ctbAcquisition::ctbAcquisition") - cout <<"Done" << endl; - - // mgAdcs=new TMultiGraph(); - adcStack=new THStack(); - TH1F *h; - int nSamples=nAnalogSamples; - - for (int i=0; iSetLineColor(i+1); - h->SetLineWidth(2); - adcStack->Add(h); - adcHisto[i]=h; - plotFlag[i]=0; - // h->SetMinimum(-1); - // h->SetMaximum(16385); - } - - - // mgAdcs=new TMultiGraph(); - bitStack=new THStack(); - // bitStack=adcStack; - TH1F *hb; - for (int i=0; iSetLineColor(i+1); - hb->SetLineWidth(2); - bitStack->Add(hb); - bitHisto[i]=hb; - bitOffset[i]=0; - bitPlotFlag[i]=0; - // h->SetMinimum(-1); - // h->SetMaximum(16385); - } - - - countsStack=new THStack(); - TH1F *h1; - for (int i=0; iSetLineColor(i+1); - h1->SetFillColor(i+1); - h1->SetLineWidth(2); - countsStack->Add(h1); - countsHisto[i]=h1; - } - - dataStructure=NULL; - commonMode=NULL; - photonFinder=NULL; - h2DMapAn=NULL; - h2DMapDig=NULL; - //h2Scan=NULL; - h1DMap=NULL; - - changeDetector(cbDetType->GetSelected()); - - - - // display could be updated with TTimer instead of with histogramfillthread: - // plotTimer= new TTimer("ctbAcquisition::Draw()",100); - - - // plotTimer->Connect("TurnOff()", "ctbAcquisition", this, "Draw()"); -} - - - - -void ctbAcquisition::canvasClicked() { - int event = gPad->GetEvent(); - if (event != 11) return; - TObject *select = gPad->GetSelected(); - if (!select) return; - - if (select->InheritsFrom("TH2")) { - TH2* hh=(TH2*)select; - - - - - int px = gPad->GetEventX(); - int py = gPad->GetEventY(); - Float_t upy = gPad->AbsPixeltoY(py); - Float_t y = gPad->PadtoY(upy); - Float_t upx = gPad->AbsPixeltoX(px); - Float_t x = gPad->PadtoY(upx); - - - // cout << "x: " << x << " y: " << y << " " << hh->GetBinContent(hh->GetXaxis()->FindBin(x), hh->GetYaxis()->FindBin(y)) << endl; - - - lClickX->SetText(hh->GetXaxis()->FindBin(x)-1); - lClickY->SetText( hh->GetYaxis()->FindBin(y)-1); - lClickValue->SetText(hh->GetBinContent(hh->GetXaxis()->FindBin(x), hh->GetYaxis()->FindBin(y))); - - - - - - - } else if (select->InheritsFrom("TH1")) { - - TH1* h1=(TH1*)select; - int px = gPad->GetEventX(); - Float_t upx = gPad->AbsPixeltoX(px); - Float_t x = gPad->PadtoY(upx); - - - // cout << "x: " << x << " y: " << y << " " << hh->GetBinContent(hh->GetXaxis()->FindBin(x), hh->GetYaxis()->FindBin(y)) << endl; - - - lClickX->SetText(h1->GetXaxis()->FindBin(x)-1); - lClickY->SetText(" "); - lClickValue->SetText(h1->GetBinContent(h1->GetXaxis()->FindBin(x))); - - - - - - } else// if ((select->ClassName())=="THStack") { - { - - - int px = gPad->GetEventX(); - int py = gPad->GetEventY(); - Float_t upy = gPad->AbsPixeltoY(py); - Float_t y = gPad->PadtoY(upy); - Float_t upx = gPad->AbsPixeltoX(px); - Float_t x = gPad->PadtoY(upx); - - - lClickX->SetText(x); - lClickY->SetText(y); - lClickValue->SetText(""); - - - - } - -} - - - - - - -void ctbAcquisition::setCanvas(TCanvas* c) { - myCanvas=c; - myCanvas->cd(); - myCanvas->AddExec("dynamic",Form("((ctbAcquisition*)%p)->canvasClicked()",this)); - // myCanvas->AddExec("ex","canvasClicked()"); -} -void ctbAcquisition::dataCallback(sls::detectorData *data, long unsigned int index, unsigned int dum, void* pArgs) { - - // return - ((ctbAcquisition*)pArgs)->plotData(data,index); -} - - -int ctbAcquisition::plotData(sls::detectorData *data, int index) { - - /* -****************************************************************** -When selecting dbit -amount of data is nadc * nasamples * 16 bit + ndbitlist * ndsamples (bits) -order of data -analog: -sample0 (adc0 + adc1 +...) -sample1 (adc0 + adc1 +...) -digital: -dbit0 (sample0 + sample1 ...) -dbit1 (sample0 + sample1..) - -when setting dbit to all -amount of data: nadc * nasamples * 16 bit + 8 * ndsamples * 64 bit -what you had before.. -except analog first, then digital -analog: -sample0 (adc0 + adc1 +...) -sample1 (adc0 + adc1 +...) -digital: -sample0 (dbit0 + dbit1 +...) -sample1 (dbit0 + dbit1 +...)if (cmd == "rx_dbitlist") { - - if (action == PUT_ACTION) { - std::vector dbitlist; - - // if not all digital bits enabled - if (std::string(args[1]) != "all") { - for (int i = 1; i < narg; ++i) { - int temp = 0; - if (!sscanf(args[i], "%d", &temp)) - return std::string("Could not scan dbitlist value ") + - std::string(args[i]); - if (temp < 0 || temp > 63) - return std::string("dbitlist value should be between 0 and 63 ") + - std::string(args[i]); - dbitlist.push_back(temp); - } - if (dbitlist.size() > 64) { - return std::string("Max number of values for dbitlist is 64 "); - } - } - - myDet->setReceiverDbitList(dbitlist, detPos); - } - -****************************************************************** -*/ - - // cout << "plot data" << endl; - - - // cout <<"global plot is " << globalPlot << endl; - // cout << "*******************************************" <progressIndex << " nx:" << data->nx << " ny: " << data->ny << " " << data->fileName << " bytes: " << data->databytes << " dr:"<< data->dynamicRange << " fi: " << data ->fileIndex << endl; - if (globalPlot || cbGetPedestal->IsOn()) { - //#ifdef TESTADC - // cout <<"------"<< index << " " << ip << " " << data->npoints << endl; - //#endif - int ig=0; - int i, ii, ib; - // TList *l= adcStack->GetHists(); - // TList *l1= countsStack->GetHists(); - TH1F *h; - TH1F *h1; - TH1F *hb; - int x; - double ped=0; - int dsize=-1; - int *val=NULL; - int nx=1, ny=1; - - if (dataStructure) { - dataStructure->getDetectorSize(nx,ny); - cout << "Data structure: " << dataStructure << " size " << nx << " " << ny << endl; - } - int dr=24, soff=2; - if (deserializer) { - nx=eNumCount->GetIntNumber(); - dr=eDynRange->GetIntNumber(); - soff=eSerOff->GetIntNumber(); - // cout <<"deserializer: " << endl; - // cout << "Number of chans:\t" << nx << endl; - // cout << "Serial Offset:\t" << soff << endl; - // cout << "Dynamic range:\t" << dr << endl; - - } - - i=0; - int nadc; - int ndbit; - - tenG = 0; - - - - - if (adclist.empty()) - nadc=32; - else - nadc=adclist.size(); - - std::vector plotlist; - if (dbitlist.empty()) { - ndbit=64; - dBitOffset=0; - for (ib=0; ib<64; ib++){ - if (bitPlotFlag[ib]) { - plotlist.push_back(ib); - } - } - } else - ndbit=dbitlist.size(); - if (tenG){ - - if (nDigitalSamples && nAnalogSamples){ - if (nDigitalSamples>nAnalogSamples) - dsize=nDigitalSamples*(32*2+8); - else - dsize=nAnalogSamples*(32*2+8); - } else - dsize=32*2*nAnalogSamples+8*nDigitalSamples; - - } else - dsize=nadc*2*nAnalogSamples+ndbit*(nDigitalSamples-dBitOffset/8)/8; - - cout << "dataBytes is " << data->databytes << " expected " << dsize << endl; - - cout << "*******************************************" <data; - else - d_data = data->data+2*nadc*nAnalogSamples; - char dval; - - - if (dataStructure) { - - - for (int x=0; xgetValue(data->data,x,y); - //aval=dataStructure->getChannel(data->data,x,y); - // cout << x << " " <IsOn()) { - if (photonFinder) { - photonFinder->addToPedestal(aval,x,y); - } - } - - if (cbSubtractPedestal->IsOn()) { - if (photonFinder) { - ped=photonFinder->getPedestal(x,y,cmSub); - } - } - if (h2DMapAn) - h2DMapAn->SetBinContent(x+1,y+1,aval-ped); - - - - - if (h2DMapDig) - h2DMapDig->SetBinContent(x+1,y+1,dataStructure->getGain(data->data,x,y)); - - - } - } - } else - if (deserializer) { - cout << "deserializer"<< endl; - if (dbitlist.empty()) - val=deserializer::deserializeAll(d_data,plotlist,dr,nx,soff);//dataStructure->getData(d_data); - else - val=deserializer::deserializeList(d_data,dbitlist,dr,nx,soff);//dataStructure->getData(d_data); - - - if (val) { - if (h1DMap){ - for (x=0; xSetBinContent(x+1,val[x]); - } - } - delete [] val; - } else - cout << "get val did not succeed"<getChannel(i); - // else - aval=data->getChannel(i);//*((uint16_t*)(data->cvalues+i*2));// - - if (plotFlag[ig]) { - - //if (enableFlag[ig]) { - h=adcHisto[ig]; - h1=countsHisto[ig]; - //} - - // cout << data->getChannel(i) << endl; - h->SetBinContent(ip+1,aval); - h1->Fill(aval); - } - - i++; - } - if (tenG) i+=4; - - } - - - cout << "bit histo"<< endl; - - if (dbitlist.empty()) { - for (ip=0; ipSetBinContent(ip+1,1+bitOffset[ib]); - else - hb->SetBinContent(ip+1,bitOffset[ib]); - } - } - - } - } - } else { - ii=0; - int iii=0; - for (const auto &value : dbitlist) { - ib=value; - hb=bitHisto[ib]; - // cout << dec <SetBinContent(iii,1+bitOffset[ib]); - else - hb->SetBinContent(iii,bitOffset[ib]); - iii++; - } - } - } - ii++; - } - } - } - Draw(); - // iScanStep++; - if (photonFinder) - photonFinder->newFrame(); - } - return 0; - -} - - - -void ctbAcquisition::Draw(){ - if (globalPlot) { - // TThread::Lock(); - cout << "Draw" << endl; - if (myCanvas) { - if (adcPlot && dbitPlot) { - - myCanvas->cd(1); - // myCanvas->Modified(); - // myCanvas->Update(); - gPad->Modified(); - gPad->Update(); - - myCanvas->cd(2); - // myCanvas->Modified(); - // myCanvas->Update(); - gPad->Modified(); - gPad->Update(); - - } else { - - myCanvas->cd(); - myCanvas->Modified(); - myCanvas->Update(); - - } - } - // TThread::UnLock(); - } - -} - - -//here!! -void ctbAcquisition::changePlot(){ - if (rbPlotOff->IsOn()) { - adcPlot=0; - dbitPlot=0; - try { - myDet->registerDataCallback(nullptr, this); - } CATCH_DISPLAY ("Could not get unregister call back.", "ctbAcquisition::ctbAcquisition") - try { - myDet->setRxZmqDataStream(false); - } CATCH_DISPLAY ("Could not get unset RxZmqDataStream.", "ctbAcquisition::ctbAcquisition") - } else { - try { - myDet->registerDataCallback(&dataCallback, (void*)this); - } CATCH_DISPLAY ("Could not get register call back.", "ctbAcquisition::ctbAcquisition") - try { - myDet->setRxZmqDataStream(true); - } CATCH_DISPLAY ("Could not get set RxZmqDataStream.", "ctbAcquisition::ctbAcquisition") - adcPlot=0; - dbitPlot=0; - for (int ii=0; iiGetPad(1)==NULL || myCanvas->GetPad(2)==NULL) { - myCanvas->Clear(); - myCanvas->Divide(1,2); - } else - cout << "Pad already there" << endl; - myCanvas->cd(1); - } else { - myCanvas->Clear(); - // myCanvas->Divide(1,1); - myCanvas->cd(); - } - - if (adcPlot) { - if (rbWaveform->IsOn()) - if (adcStack) - adcStack->Draw("NOSTACK"); - else - cout << "adcStack is NULL" << endl; - else if (rbDistribution->IsOn()) - if (countsStack) - countsStack->Draw("NOSTACK"); - else - cout << "countsStack is NULL" << endl; - else if (rb2D->IsOn()) { - if (h2DMapAn) - h2DMapAn->Draw("colz"); - else if (h1DMap) - h1DMap->Draw(); - else - cout << "h2DMap and h1DMap are NULL" << endl; - } - } - - if (dbitPlot) { - if (adcPlot) - myCanvas->cd(2); - if (rb2D->IsOn()) { - if (h2DMapDig) - h2DMapDig->Draw("colz"); - else if (h1DMap) - h1DMap->Draw(); - } else if (bitStack) - bitStack->Draw("NOSTACK"); - else - cout << "bitStack is NULL" << endl; - } - - - // else if (rbScan->IsOn()) { - // if (h2Scan) - // h2Scan->Draw("colz"); - // else - // cout << "h2Scan is NULL" << endl; - // } - - Draw(); - - } -} - - - - - -void ctbAcquisition::changeDetector(){ - // cout << "change detector " << i << " old " << cbDetType->GetSelected() << endl; - - if (dataStructure) delete dataStructure; - if (commonMode) delete commonMode; - if (photonFinder) delete photonFinder; - if (h2DMapAn) delete h2DMapAn; - if (h2DMapDig) delete h2DMapDig; - if (h1DMap) delete h1DMap; - // if (h2Scan) delete h2Scan; - h2DMapAn=NULL; - h2DMapDig=NULL; - h1DMap=NULL; - // h2Scan=NULL; - photonFinder=NULL; - dataStructure=NULL; - commonMode=NULL; - - // TH2F *h2ScanOld=h2Scan; - - - int nx,ny; - int csize=3; - int nsigma=5; - commonModeSubtraction* cm=0; - eNumCount->SetState(kFALSE); - eDynRange->SetState(kFALSE); - eSerOff->SetState(kFALSE); - ePixX->SetState(kFALSE); - ePixY->SetState(kFALSE); - - deserializer=0; - if (rb2D->IsOn() ) {//|| rbScan->IsOn() - switch (cbDetType->GetSelected()) { - case DESERIALIZER: - deserializer=1; - cout << "DESERIALIZER!" << endl; - // dataStructure=new moench03T1CtbData(); - // commonMode=new moench03CommonMode(); - break; - case MOENCH04: - try { - auto retval = myDet->getTenGiga().tsquash("Different values"); - if (retval) { - dataStructure=new moench04CtbZmq10GbData(nAnalogSamples, nDigitalSamples); - } else { - dataStructure=new moench04CtbZmqData(nAnalogSamples, nDigitalSamples); - } - } CATCH_DISPLAY ("Could not get ten giga enable.", "ctbAcquisition::changeDetector") - - cout << "MOENCH 0.4!" << endl; - commonMode=new moench03CommonMode(); - break; - case MOENCH03: - //try { - // auto retval = myDet->getTenGiga().tsquash("Different values"); - // if (retval) { - dataStructure=new moench03T1ZmqDataNew(nAnalogSamples); - // } else { - // dataStructure=new moench04CtbZmqData(nAnalogSamples, nDigitalSamples); - // } - //} CATCH_DISPLAY ("Could not get ten giga enable.", "ctbAcquisition::changeDetector") - - cout << "MOENCH 0.3! USE JUNGFRAU MODULE!" << endl; - commonMode=new moench03CommonMode(); - break; - case IMAGE32B: - //try { - // auto retval = myDet->getTenGiga().tsquash("Different values"); - // if (retval) { - // if (deserializer) { - ePixX->SetState(kTRUE); - ePixY->SetState(kTRUE); - // } - dataStructure=new imageZmq32bit(ePixX->GetIntNumber(),ePixY->GetIntNumber()); - // } else { - // dataStructure=new moench04CtbZmqData(nAnalogSamples, nDigitalSamples); - // } - //} CATCH_DISPLAY ("Could not get ten giga enable.", "ctbAcquisition::changeDetector") - - cout << "Image 32bit, no channel shuffling" << endl; - commonMode=NULL; - break; - - case IMAGE16B: - //try { - // auto retval = myDet->getTenGiga().tsquash("Different values"); - // if (retval) { - // if (deserializer) { - ePixX->SetState(kTRUE); - ePixY->SetState(kTRUE); - // } - dataStructure=new imageZmq16bit(ePixX->GetIntNumber(),ePixY->GetIntNumber()); - // } else { - // dataStructure=new moench04CtbZmqData(nAnalogSamples, nDigitalSamples); - // } - //} CATCH_DISPLAY ("Could not get ten giga enable.", "ctbAcquisition::changeDetector") - - cout << "Image 16bit, no channel shuffling" << endl; - commonMode=NULL; - break; - - // case 1: - // cout << "************** T!!!!!!!!!!" << endl; - // dataStructure=new moench03TCtbData(); - // commonMode=new moench03CommonMode(); - // break; - case MOENCH02: - cout << "MOENCH 0.2" << endl; - dataStructure=new moench02CtbData(); - commonMode=new moenchCommonMode(); - break; - // case 2: - // dataStructure=new jungfrau10ModuleData(); - // commonMode=new commonModeSubtraction(); - // break; - // case 3: - // cout << "************** Flat!!!!!!!!!!" << endl; - // dataStructure=new moench03CtbData(); - // commonMode=new moench03CommonMode(); - // break; - // case MYTHEN301: - // deserializer=1; - // cout << "MYTHEN 3 0.1" << endl; - // dataStructure=new mythen3_01_jctbData(eNumCount->GetIntNumber(),eDynRange->GetIntNumber(),eSerOff->GetIntNumber()); - // //( int nch=64*3,int dr=24, int off=5) - // eNumCount->SetState(kTRUE); - // eDynRange->SetState(kTRUE); - // eSerOff->SetState(kTRUE); - // commonMode=NULL; - // dim=1; - // break; - // case ADCSAR2: - // deserializer=1; - // //adcsar2 - // dataStructure=new adcSar2_jctbData(); - // //need to use configurable number of counters, offset or dynamic range? - // commonMode=NULL; - // dim=1; - // break; - - // case MYTHEN302: - // deserializer=1; - // cout << "MYTHEN 3 0.2" << endl; - // dataStructure=new mythen3_02_jctbData(eNumCount->GetIntNumber(),eDynRange->GetIntNumber(),eSerOff->GetIntNumber()); - // //( int nch=64*3,int dr=24, int off=5) - // eNumCount->SetState(kTRUE); - // eDynRange->SetState(kTRUE); - // eSerOff->SetState(kTRUE); - // commonMode=NULL; - // dim=1; - // break; - default: - dataStructure=NULL; - commonMode=NULL; - } - if (cbCommonMode->IsOn()) cm=commonMode; - } - - if (dataStructure || deserializer) { - if (dataStructure) { - photonFinder=new singlePhotonDetector(dataStructure,csize,nsigma,1,cm); //sign is positive - should correct with ADC mask, no common mode - //photonFinder=new singlePhotonDetector(dataStructure,csize,nsigma,1,cm); //sign is positive - should correct with ADC mask, no common mode - dataStructure->getDetectorSize(nx,ny); - - } - if (deserializer) { - ny=1; - nx=eNumCount->GetIntNumber(); - eNumCount->SetState(kTRUE); - eDynRange->SetState(kTRUE); - eSerOff->SetState(kTRUE); - } - // cout << "h size is " << nx << " " << ny << endl; - int ymax=ny, xmax=nx; - // if (ny>500) {ny=ny/2;} - // if (nx>500) {nx=nx/2;} - cout << "*** " << nx << " " << ny << endl; - if (rb2D->IsOn()) { - if (ny>1) { - h2DMapAn=new TH2F("h2dmapAn","",nx,0,xmax,ny,0,ymax); - h2DMapAn->SetStats(kFALSE); - cout << "Created h2DMapAn"<< endl; - if (dbitPlot && adcPlot){ - h2DMapDig=new TH2F("h2dmapDig","",nx,0,xmax,ny,0,ymax); - h2DMapDig->SetStats(kFALSE); - cout << "Created h2DMapDig"<< endl; - } - } else { - h1DMap=new TH1F("h1dmap","",nx,0,xmax); - h1DMap->SetStats(kFALSE); - cout << "Created h1DMap"<< endl; - } - } // else if (rbScan->IsOn()) { - // int nsteps=0;//myDet->getScanSteps(0); - // double stepmin=0, stepmax=1; - // if (nsteps>0) { - // stepmin=myDet->getScanStep(0,0); - // stepmax=myDet->getScanStep(0,nsteps-1); - // } - // cout << "************ creating scan histogram " << nx*ny << " " << nsteps << " " << stepmin << " " << stepmax << endl; - // if (nsteps<1) nsteps=1; - // double hmin=stepmin, hmax=stepmax; - // if (stepmin>stepmax) { - // hmin=stepmax; - // hmax=stepmin; - // } - // h2Scan=new TH2F("h2scan","",nx*ny,0,nx*ny,nsteps,hmin,hmax); - // } - - } - - - cout << "done " << endl; -} - - - -void ctbAcquisition::changeDetector(int i){ - changePlot(); - changeDetector(); -} - -void ctbAcquisition::changePlot(int i){ - changePlot(); - changeDetector(); -} - - - -void ctbAcquisition::setGraph(int i ,int en, Pixel_t col) { - char name[100]; - // TList *l= mgAdcs->GetListOfGraphs(); - sprintf(name,"adc%d",i); - - // TList *l= adcStack->GetHists(); - TH1F *h=adcHisto[i];//(TH1F*)l->At(i);; - TH1F *h1=countsHisto[i];//(TH1F*)(countsStack->GetHists()->At(i)); - if (en) { - plotFlag[i]=1; - h->SetLineColor(TColor::GetColor(col)); - h1->SetLineColor(TColor::GetColor(col)); - h1->SetFillColor(TColor::GetColor(col)); - - if (adcStack->GetHists()) - // if (adcStack->GetHists()->GetEntries()) - if (adcStack->GetHists()->Contains(h)==0) - adcStack->Add(h); - - if (countsStack->GetHists()) - if (countsStack->GetHists()->Contains(h1)==0) - countsStack->Add(h1); - - cout << "Enable plot " << i << " color " << col << endl; - } else { - cout << "Disable plot " << i << endl; - plotFlag[i]=0; - if (adcStack->GetHists()) - // if (adcStack->GetHists()->GetEntries()) - if (adcStack->GetHists()->Contains(h)) - adcStack->RecursiveRemove(h); - if (countsStack->GetHists()) - if (countsStack->GetHists()->Contains(h1)) - countsStack->RecursiveRemove(h1); - } - cout << countsStack->GetHists()->GetEntries() << endl; - - cout << "Number of histos " << adcStack->GetHists()->GetEntries() << endl; - - changePlot(); - - // globalPlot=0; - // for (int ii=0; iiGetListOfGraphs(); - sprintf(name,"bit%d",i); - // TList *l= adcStack->GetHists(); - TH1F *h=bitHisto[i];//(TH1F*)l->At(i);; - if (en) { - //cout<< "enabling plot of bit "<SetLineColor(TColor::GetColor(col)); - if (bitStack->GetHists()) - //if (bitStack->GetHists()->GetEntries()) - if (bitStack->GetHists()->Contains(h)==0) - bitStack->Add(h); - - - cout << "Enable bit plot " << i << " color " << col << endl; - } else { - cout << "Disable bit plot " << i << endl; - bitPlotFlag[i]=0; - if (bitStack->GetHists()) - // if (bitStack->GetHists()->GetEntries()) - if (bitStack->GetHists()->Contains(h)) - bitStack->RecursiveRemove(h); - } - cout << "Number of histos " << bitStack->GetHists()->GetEntries() << endl; - - changePlot(); - - float off=0; - for (int ii=0; ii(1.5); - cout << "bit " << ii << " offset " << bitOffset[ii] << endl; - } - } - - // globalPlot=0; - // for (int ii=0; iisetFilePath(eOutdir->GetText()); - } CATCH_DISPLAY ("Could not set file path", "ctbAcquisition::setOutdir") -} - -void ctbAcquisition::setFname() { - try { - myDet->setFileNamePrefix(eFname->GetText()); - } CATCH_DISPLAY ("Could not set file name prefix", "ctbAcquisition::setFname") -} - -void ctbAcquisition::setFindex() { - try { - myDet->setAcquisitionIndex(eFindex->GetNumber()); - } CATCH_DISPLAY ("Could not set acquisition index", "ctbAcquisition::setFindex") -} - -void ctbAcquisition::setFsave(Bool_t b) { - try { - myDet->setFileWrite(b); - eFname->SetState(b); - eOutdir->SetState(b); - } CATCH_DISPLAY ("Could not set file write", "ctbAcquisition::setFsave") -} - -void ctbAcquisition::update() { - try { - auto retval = myDet->getFileNamePrefix().tsquash("Different values"); - eFname->SetText(retval.c_str()); - } CATCH_DISPLAY ("Could not get file name prefix", "ctbAcquisition::update") - - try { - auto retval = myDet->getAcquisitionIndex().tsquash("Different values"); - eFindex->SetNumber(retval); - } CATCH_DISPLAY ("Could not get acquisition index", "ctbAcquisition::update") - - try { - auto retval = myDet->getFileWrite().tsquash("Different values"); - cFileSave->SetOn(retval); - } CATCH_DISPLAY ("Could not get file write", "ctbAcquisition::update") - - eFname->SetState(cFileSave->IsOn()); - eOutdir->SetState(cFileSave->IsOn()); - eFindex->SetState(cFileSave->IsOn()); - - try { - auto retval = myDet->getNumberOfAnalogSamples().tsquash("Different values"); - setAnalogSamples(retval); - } CATCH_DISPLAY ("Could not get number of analog samples", "ctbAcquisition::update") - - try { - auto retval = myDet->getNumberOfDigitalSamples().tsquash("Different values"); - setDigitalSamples(retval); - } CATCH_DISPLAY ("Could not get number of digital samples", "ctbAcquisition::update") - - try { - roMode = static_cast(myDet->getReadoutMode().tsquash("Different values")); - setReadoutMode(roMode); - } CATCH_DISPLAY ("Could not get readout mode", "ctbAcquisition::update") - - updateChans(); - - if (dataStructure) { - cout << cbDetType->GetSelected()<< endl; - // if (cbDetType->GetSelected()==MYTHEN301 || cbDetType->GetSelected()==MYTHEN302){ - // cout << "settings deserialiation parameters for MYTHEN" << endl; - // mythen3_01_jctbData* ms=(mythen3_01_jctbData*)dataStructure; - // eSerOff->SetNumber( ms->setSerialOffset(-1)); - // eDynRange->SetNumber( ms->setDynamicRange(-1)); - // eNumCount->SetNumber( ms->setNumberOfCounters(-1)); - // } - - } - - if (myDet->getDetectorType().squash() == slsDetectorDefs::MOENCH) { - dBitOffset = 0; - } else { - try { - dBitOffset = myDet->getRxDbitOffset().tsquash("Different values"); - } CATCH_DISPLAY ("Could not get receiver dbit offset", "ctbAcquisition::update") - } - try { - tenG = myDet->getTenGiga().tsquash("Different values"); - } CATCH_DISPLAY ("Could not get ten giga enable", "ctbAcquisition::update") - - // char aargs[10][100]; - // char *args[10]; - // for (int i=0; i<10; i++) - // args[i]=aargs[i]; - - // string retval; - // sprintf(args[0],"adcdisable"); - // slsDetectorCommand *cmd=new slsDetectorCommand(myDet); - // retval=cmd->executeLine(1,args,slsDetectorDefs::GET_ACTION); - // delete cmd; - // int mask; - // sscanf(retval.c_str(),"adcdisable %d",&mask); - // for (int i=0; iGetState()==1 || acqThread->GetState()==6) { - - - if (cCompile->IsOn()) { - sprintf(fname,"%s %s",patternCompiler,patternFile); - cout << "Compile: " << fname << endl; - strcpy(currdir,gSystem->pwd()); - - std::size_t found = string(patternCompiler).rfind('/'); - if (found!=std::string::npos) - gSystem->cd(string(patternCompiler).substr(0,found).c_str()); - - gSystem->cd(cdir); - system(fname); - gSystem->cd(currdir); - } - - if (string(patternCompiler).rfind(".pat")!=std::string::npos) - strcpy(fname,patternFile); - else if (string(patternCompiler).rfind(".npat")!=std::string::npos) - strcpy(fname,patternFile); - else - sprintf(fname,"%sat",patternFile); - - cout << "Load: " << fname << endl; - try { - myDet->loadParameters(fname); - } CATCH_DISPLAY ("Could not load parameters", "ctbAcquisition::loadPattern") - } -} - - -void ctbAcquisition::toggleAcquisition() { - - - if (acqThread->GetState()==1 || acqThread->GetState()==6) { - /** update all infos useful for the acquisition! */ - - try { - auto retval = myDet->getNumberOfAnalogSamples().tsquash("Different values"); - setAnalogSamples(retval); - } CATCH_DISPLAY ("Could not get number of analog samples", "ctbAcquisition::toggleAcquisition") - - try { - auto retval = myDet->getNumberOfDigitalSamples().tsquash("Different values"); - setDigitalSamples(retval); - } CATCH_DISPLAY ("Could not get number of digital samples", "ctbAcquisition::toggleAcquisition") - - if (myDet->getDetectorType().squash() == slsDetectorDefs::MOENCH) { - dBitOffset = 0; - } else { - try { - dBitOffset = myDet->getRxDbitOffset().tsquash("Different values"); - } CATCH_DISPLAY ("Could not get receiver dbit offset", "ctbAcquisition::toggleAcquisition") - } - - try { - roMode = static_cast(myDet->getReadoutMode().tsquash("Different values")); - setReadoutMode(roMode); - } CATCH_DISPLAY ("Could not get readout mode", "ctbAcquisition::toggleAcquisition") - - - cout << "Run" << endl; - bStatus->SetText("Stop"); - ip=0; - for (int i=0; iGetListOfFunctions()) - adcHisto[i]->GetListOfFunctions()->Delete(); - - adcHisto[i]->Reset(); - - if (countsHisto[i]->GetListOfFunctions()) - countsHisto[i]->GetListOfFunctions()->Delete(); - countsHisto[i]->Reset(); - // ((TH1F*)adcStack->GetHists()->At(i))->Reset(); - // ((TH1F*)countsStack->GetHists()->At(i))->Reset(); - } - for (int i=0; iReset(); - } - cout << "reset 2d an" << endl;; - if (h2DMapAn) h2DMapAn->Reset(); - cout << "reset 2d dig" << endl;; - if (h2DMapDig) h2DMapDig->Reset(); - cout << "reset 1d" << endl;; - if (h1DMap) h1DMap->Reset(); - cout << "done" << endl;; - // if (h2Scan) h2Scan->Reset(); - // cout << "reset 1d" << endl;; - // if (rbWaveform->IsOn()) -// adcStack->Draw("NOSTACK"); -// else if (rbDistribution->IsOn()) -// countsStack->Draw("NOSTACK"); -// else if (rb2D->IsOn()) -// h2DMap->Draw("colz"); - - // cout << "timer" << endl; - changePlot(); - - // plotTimer->TurnOn(); - // cout << "thread" << endl; - acqThread->Run(); - StopFlag=0; - - - - - - } else { - StopFlag=1; - try{ - myDet->stopDetector(); - } CATCH_DISPLAY ("Could not stop acquisition", "ctbAcquisition::toggleAcquisition") - stop=1; - bStatus->SetText("Start"); - // acqThread->Kill(); - } -} - -void ctbAcquisition::acquisitionFinished() { - bStatus->SetText("Start"); - cout << "finished " << endl; - // plotTimer->TurnOff(); - Draw(); -} - -void ctbAcquisition::startAcquisition(){ - cout << "Detector started " <GetNumber()<< endl; - stop=0; - - try { - tenG = myDet->getTenGiga().tsquash("Different values"); - } CATCH_DISPLAY ("Could not get ten giga enable", "ctbAcquisition::startAcquisition") - - for (int im=0; imGetNumber(); im++) { - try { - myDet->acquire(); - } CATCH_DISPLAY ("Could not acquire", "ctbAcquisition::startAcquisition") - - cout << im << endl; - if (stop) - break; - } -} - -void* ctbAcquisition::ThreadHandle(void *arg) -{ - ctbAcquisition *acq = static_cast(arg); - - acq->startAcquisition(); - acq->acquisitionFinished(); - - return nullptr; -} - - void ctbAcquisition::progressCallback(double f,void* arg) { - - - // ctbAcquisition *acq = static_cast(arg); - - - cout << "*********" << f << "*******" << endl; - - - - - } - -void ctbAcquisition::setPatternFile(const char* t) { - - - cout << "New pattern is " << t << endl; - - strcpy(patternFile,t); - } - -void ctbAcquisition::setPatternCompiler(const char* t) { - - - cout << "New compiler is " << t << endl; - strcpy(patternCompiler,t); - - } -void ctbAcquisition::setMeasurements() { - -} - -void ctbAcquisition::setAnalogSamples(int n) { - - - cout<< "Set number of analog samples to " << dec<< n << endl; - if (n>0 && n<8192) - nAnalogSamples=n; - - // TList *l= adcStack->GetHists(); - TH1 *h; - // if (l) { - for (int i=0; iAt(i); - if (h) { - - h->SetBins(nAnalogSamples,0,nAnalogSamples); - } - } - - h=adcStack->GetHistogram(); - if (h) - h->SetBins(nAnalogSamples,0,nAnalogSamples); -} - - - -void ctbAcquisition::setDigitalSamples(int n) { - - - cout<< "Set number of digital samples to " << dec<< n << endl; - if (n>0 && n<8192) - nDigitalSamples=n; - - TH1 *h; - for (int i=0; iAt(i); - if (h) { - - h->SetBins(nDigitalSamples,0,nDigitalSamples); - } - - } - // cout<< "histos resized " << dec<< h->GetNbinsX() << endl; - - h=bitStack->GetHistogram(); - if (h) - h->SetBins(nDigitalSamples,0,nDigitalSamples); - -} - -void ctbAcquisition::setReadoutMode(int f) { - - roMode=f; - slsDetectorDefs::readoutMode flag=(slsDetectorDefs::readoutMode)f; - if (flag == slsDetectorDefs::DIGITAL_ONLY) { - nAnalogSamples=0; - adclist.clear(); - } else if (flag ==slsDetectorDefs::ANALOG_AND_DIGITAL) { - ; - } - else { - nDigitalSamples=0; - dbitlist.clear(); - } - - // for (int i=0; igetDetectorType().squash() == slsDetectorDefs::MOENCH) { - dbitlist.clear(); - } else { - try { - auto retval = myDet->getRxDbitList().tsquash("Different values"); - dbitlist.clear(); - if (!retval.empty()) { - for (const auto &value : retval) - dbitlist.push_back(value); - } - } CATCH_DISPLAY ("Could not get receiver dbit list.", "ctbAcquisition::updateChans") - } - - // adc mask - try { - auto retval = myDet->getADCEnableMask().tsquash("Different values"); - adclist.clear(); - if (retval!=0xffffffff) { - for (int i=0; inewDataSet(); - }; - -} - -void ctbAcquisition::ToggleCommonMode(Bool_t b) { - if (photonFinder) { - if (b) { - photonFinder->setCommonModeSubtraction(commonMode); - cmSub=1; - cout << "Enable common mode" << endl; - } else { - photonFinder->setCommonModeSubtraction(NULL); - cmSub=0; - cout << "Disable common mode" << endl; - } - } - -} - - -void ctbAcquisition::TogglePedSub(Bool_t b) { - if (b) { - ChangeHistoLimitsPedSub(); - } else { - ChangeHistoLimitsRaw(); - } - -} - - -void ctbAcquisition::FitADC() { - int iadc=eFitADC->GetNumber(); - if (iadc<0 || iadc>=NADCS) return; - cout << "fit panel for adc " << eFitADC->GetNumber() << endl; - if (rbWaveform->IsOn()) { - if (adcHisto[iadc]==NULL) return; - new TCanvas("Cadcfit"); - if (adcFit) { - delete adcFit; - adcFit=NULL; - } - adcFit=(TH1F*)(adcHisto[iadc]->Clone("adcfit")); - adcFit->Draw(); - adcFit->FitPanel(); - - } else if (rbDistribution->IsOn()) { - if (countsHisto[iadc]==NULL) return; - new TCanvas("Ccountsfit"); - - if (countsFit) { - delete countsFit; - countsFit=NULL; - } - - countsFit=(TH1F*)(countsHisto[iadc]->Clone("countsfit")); - countsFit->Draw(); - countsFit->FitPanel(); - } -} - - -void ctbAcquisition::plotBit() { - int iadc=eBitPlot->GetNumber(); - if (iadc<0 || iadc>=NSIGNALS) return; - cout << "plot panel for bit " << eBitPlot->GetNumber() << endl; - if (bitHisto[iadc]==NULL) return; - new TCanvas("Cbitplot"); - if (bitPlot) { - delete bitPlot; - bitPlot=NULL; - } - bitPlot=(TH1F*)(bitHisto[iadc]->Clone("bitplot")); - bitPlot->Draw(); -} - - - - - - - - - - -void ctbAcquisition::ChangeSerialOffset(Long_t a){ - ChangeSerialOffset(); -}; - - -void ctbAcquisition::ChangeDynamicRange(Long_t a){ - ChangeDynamicRange(); -}; - -void ctbAcquisition::ChangeNumberOfChannels(Long_t a){ - ChangeNumberOfChannels(); -}; - - - -void ctbAcquisition::ChangeSerialOffset(){ - changeDetector(); - // if (dataStructure) { - - // cout << cbDetType->GetSelected()<< endl; - // if (cbDetType->GetSelected()==MYTHEN301 || cbDetType->GetSelected()==MYTHEN302 ){ - // cout << "settings offsets for MYTHEN" << endl; - // mythen3_01_jctbData* ms=(mythen3_01_jctbData*)dataStructure; - // ms->setSerialOffset(eSerOff->GetIntNumber()); - - // } - // } -}; - - -void ctbAcquisition::ChangeDynamicRange(){ - changeDetector(); - // if (dataStructure) { - - // cout << cbDetType->GetSelected()<< endl; - // if (cbDetType->GetSelected()==MYTHEN301 || cbDetType->GetSelected()==MYTHEN302){ - // cout << "settings dynamic range for MYTHEN" << endl; - // mythen3_01_jctbData* ms=(mythen3_01_jctbData*)dataStructure; - // ms->setDynamicRange(eDynRange->GetIntNumber()); - - // } - // } -}; - -void ctbAcquisition::ChangeNumberOfChannels(){ - changeDetector(); - // if (dataStructure) { - // cout << cbDetType->GetSelected()<< endl; - // if (cbDetType->GetSelected()==MYTHEN301 || cbDetType->GetSelected()==MYTHEN302){ - // cout << "settings number of channels for MYTHEN" << endl; - // mythen3_01_jctbData* ms=(mythen3_01_jctbData*)dataStructure; - // ms->setNumberOfCounters(eNumCount->GetIntNumber()); - - // } - // } - if (deserializer) - changePlot(); -}; - -void ctbAcquisition::ChangeImagePixels(Long_t a){ - ChangeImagePixels(); -}; - -void ctbAcquisition::ChangeImagePixels(){ - changeDetector(); - // if (dataStructure) { - // cout << cbDetType->GetSelected()<< endl; - // if (cbDetType->GetSelected()==MYTHEN301 || cbDetType->GetSelected()==MYTHEN302){ - // cout << "settings number of channels for MYTHEN" << endl; - // mythen3_01_jctbData* ms=(mythen3_01_jctbData*)dataStructure; - // ms->setNumberOfCounters(eNumCount->GetIntNumber()); - - // } - // } - // if (deserializer) - // changePlot(); -}; - - -void ctbAcquisition::ChangeHistoLimitsPedSub(Long_t a){ - ChangeHistoLimitsPedSub(); -}; - - -void ctbAcquisition::ChangeHistoLimitsRaw(Long_t a){ - ChangeHistoLimitsRaw(); -} - -void ctbAcquisition::ChangeHistoLimitsPedSub(Bool_t a){ - ChangeHistoLimitsPedSub(); -}; - - -void ctbAcquisition::ChangeHistoLimitsRaw(Bool_t a){ - ChangeHistoLimitsRaw(); -} - - -void ctbAcquisition::ChangeHistoLimitsPedSub(){ - - cout << "set Limits ped sub hist " << eMinPedSub->GetNumber() << " " << eMaxPedSub->GetNumber() << endl; - - if (eMinPedSub->GetNumber()>eMaxPedSub->GetNumber()) - return; - - if (cbSubtractPedestal->IsOn()) { - if (cMinMaxPedSub->IsOn()) { - adcStack->SetMaximum( eMaxPedSub->GetNumber()); - adcStack->SetMinimum( eMinPedSub->GetNumber()); - if (h2DMapAn) { - h2DMapAn->SetMaximum( eMaxPedSub->GetNumber()); - h2DMapAn->SetMinimum( eMinPedSub->GetNumber()); - } - if (h1DMap) { - h1DMap->SetMaximum( eMaxPedSub->GetNumber()); - h1DMap->SetMinimum( eMinPedSub->GetNumber()); - } - if (countsStack->GetHistogram()) - countsStack->GetHistogram()->GetXaxis()->SetRangeUser(eMinPedSub->GetNumber(), eMaxPedSub->GetNumber()); - } else { - if (adcStack->GetHistogram()) - adcStack->GetHistogram()->GetYaxis()->UnZoom(); - if (h2DMapAn) { - h2DMapAn->GetZaxis()->UnZoom(); - } - if (h1DMap) { - h1DMap->GetYaxis()->UnZoom(); - } - if (countsStack->GetHistogram()) - countsStack->GetHistogram()->GetXaxis()->UnZoom(); - } - } - - -}; - - -void ctbAcquisition::ChangeHistoLimitsRaw(){ - - cout << "set Limits raw hist " << eMinRaw->GetNumber() << " " << eMaxRaw->GetNumber() << endl; - if (eMinRaw->GetNumber()>eMaxRaw->GetNumber()) - return; - - if (cbSubtractPedestal->IsOn()==0) { - if (cMinMaxRaw->IsOn()) { - adcStack->SetMaximum( eMaxRaw->GetNumber()); - adcStack->SetMinimum( eMinRaw->GetNumber()); - if (h2DMapAn) { - h2DMapAn->SetMaximum( eMaxRaw->GetNumber()); - h2DMapAn->SetMinimum( eMinRaw->GetNumber()); - } - if (h1DMap) { - h1DMap->SetMaximum( eMaxRaw->GetNumber()); - h1DMap->SetMinimum( eMinRaw->GetNumber()); - } - if (countsStack->GetHistogram()) - countsStack->GetHistogram()->GetXaxis()->SetRangeUser(eMinRaw->GetNumber(), eMaxRaw->GetNumber()); - } else { - - if (adcStack->GetHistogram()) - adcStack->GetHistogram()->GetYaxis()->UnZoom(); - if (h2DMapAn) { - h2DMapAn->GetZaxis()->UnZoom(); - } - - if (h1DMap) { - h1DMap->GetYaxis()->UnZoom(); - } - if (countsStack->GetHistogram()) - countsStack->GetHistogram()->GetXaxis()->UnZoom(); - - } - } - -} diff --git a/ctbGui/ctbAcquisition.h b/ctbGui/ctbAcquisition.h deleted file mode 100644 index 3d5524eda..000000000 --- a/ctbGui/ctbAcquisition.h +++ /dev/null @@ -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 - -#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 slsDetectorData; - -class singlePhotonDetector; -//class singlePhotonDetector; -class commonModeSubtraction; - -#include -#include -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 dbitlist; - std::vector 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 *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 diff --git a/ctbGui/ctbAdcs.cpp b/ctbGui/ctbAdcs.cpp deleted file mode 100644 index 694f5ff13..000000000 --- a/ctbGui/ctbAdcs.cpp +++ /dev/null @@ -1,616 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-other -// Copyright (C) 2021 Contributors to the SLS Detector Package -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#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<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; idacAddFrame(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; issetAdcAlias(NULL,-1,-1); - if (invreg & (1<setInverted(kTRUE); - else - sAdc[is]->setInverted(kFALSE); - - if (disreg & (1<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; issetPlot(kTRUE); - } -} - - -void ctbAdcs::RemoveAll() { - for (int is=0; issetPlot(kFALSE); - } -} - - - -void ctbAdcs::CheckHalf0() { - for (int is=0; issetPlot(kTRUE); - } -} - - -void ctbAdcs::RemoveHalf0() { - for (int is=0; issetPlot(kFALSE); - } -} - -void ctbAdcs::CheckHalf1() { - for (int is=NADCS/2; issetPlot(kTRUE); - } -} - - -void ctbAdcs::RemoveHalf1() { - for (int is=NADCS/2; issetPlot(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 && issetAdcAlias(tit,plot,color); - } - return is; - -} - -string ctbAdcs::getAdcAlias() { - - ostringstream line; - - for (int is=0; isgetAdcAlias(); - - 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<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<getInverted()) - oreg|=m; - else - oreg&=~m; - - setInvert(oreg); -} - - - - - -Pixel_t ctbAdcs::getColor(int i){ - if (i>=0 && igetColor(); - return static_cast(-1); -} - -Bool_t ctbAdcs::getEnabled(int i){ - if (i>=0 && igetEnabled(); - return static_cast(-1); -} - -Bool_t ctbAdcs::getEnable(int i){ - if (i>=0 && igetEnable(); - return static_cast(-1); -} - -Bool_t ctbAdcs::getPlot(int i){ - if (i>=0 && igetPlot(); - return static_cast(-1); -} diff --git a/ctbGui/ctbAdcs.h b/ctbGui/ctbAdcs.h deleted file mode 100644 index 3a4cf35da..000000000 --- a/ctbGui/ctbAdcs.h +++ /dev/null @@ -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 - - -#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 -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 - - diff --git a/ctbGui/ctbDacs.cpp b/ctbGui/ctbDacs.cpp deleted file mode 100644 index dd2763fdf..000000000 --- a/ctbGui/ctbDacs.cpp +++ /dev/null @@ -1,235 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-other -// Copyright (C) 2021 Contributors to the SLS Detector Package - -#include -#include -#include - -#include -#include -#include -#include - -#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(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(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(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(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; idacsetLabel((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 && issetLabel(tit,mv); - return is; - -} - -string ctbDacs::getDacAlias() { - ostringstream line; - - for (int i=0; igetLabel() << endl; - return line.str(); -} - - - - - -string ctbDacs::getDacParameters() { - ostringstream line; - - for (int i=0; igetValue << endl; - line << "dac:" << i << " " << dacs[i]->getValue() << endl; - } - return line.str(); -} - - - -void ctbDacs::update() { - for (int idac=0; idacgetValue(); - } -} diff --git a/ctbGui/ctbDacs.h b/ctbGui/ctbDacs.h deleted file mode 100644 index 818c0c42d..000000000 --- a/ctbGui/ctbDacs.h +++ /dev/null @@ -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 - - -#define NDACS 18 -//#define NDACS 16 - - -class TGTextEntry; -class TGLabel; -class TGNumberEntry; -class TGCheckButton; - - -namespace sls -{ - class Detector; -}; - -#include -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 - diff --git a/ctbGui/ctbDefs.h b/ctbGui/ctbDefs.h deleted file mode 100644 index 85d7e1b8a..000000000 --- a/ctbGui/ctbDefs.h +++ /dev/null @@ -1,86 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-other -// Copyright (C) 2021 Contributors to the SLS Detector Package -#pragma once - -#include -#include -#include - -//#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(duration(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>(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 struct NonDeduced { using type = CT; }; - template - static void HandleExceptions(const std::string emsg, const std::string src, S* s, - RT (S::*somefunc)(CT...), - typename NonDeduced::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); - }; - -}; diff --git a/ctbGui/ctbGui.cpp b/ctbGui/ctbGui.cpp deleted file mode 100644 index 5c34d8ee0..000000000 --- a/ctbGui/ctbGui.cpp +++ /dev/null @@ -1,159 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-other -// Copyright (C) 2021 Contributors to the SLS Detector Package -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -#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; ialoadConfig(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; ialoadAlias(afname); - else - cout << "no alias specified" << endl; - - theApp.Run(); - - return 0; -} diff --git a/ctbGui/ctbLinkDef.h b/ctbGui/ctbLinkDef.h deleted file mode 100644 index f041a01fd..000000000 --- a/ctbGui/ctbLinkDef.h +++ /dev/null @@ -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; diff --git a/ctbGui/ctbMain.cpp b/ctbGui/ctbMain.cpp deleted file mode 100644 index 0308589bb..000000000 --- a/ctbGui/ctbMain.cpp +++ /dev/null @@ -1,588 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-other -// Copyright (C) 2021 Contributors to the SLS Detector Package -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -//#include -//#include - - - - -#include -#include -#include -#include - -#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); -} diff --git a/ctbGui/ctbMain.h b/ctbGui/ctbMain.h deleted file mode 100644 index 34ff8d429..000000000 --- a/ctbGui/ctbMain.h +++ /dev/null @@ -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 - - -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 -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 diff --git a/ctbGui/ctbPattern.cpp b/ctbGui/ctbPattern.cpp deleted file mode 100644 index 5d3d49a5e..000000000 --- a/ctbGui/ctbPattern.cpp +++ /dev/null @@ -1,1111 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-other -// Copyright (C) 2021 Contributors to the SLS Detector Package -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "ctbPattern.h" -#include "ctbDefs.h" -#include "sls/Detector.h" -#include -using namespace std; - - - - - -ctbLoop::ctbLoop(TGGroupFrame *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)); - MapWindow(); - - - - - - sprintf(tit, "Loop %d Repetitions: ", id); - - TGLabel *label= new TGLabel(hframe, tit); - hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1)); - label->MapWindow(); - label->SetTextJustify(kTextLeft); - - - - - eLoopNumber = new TGNumberEntry(hframe, 0, 9,999, TGNumberFormat::kNESInteger, - TGNumberFormat::kNEANonNegative, - TGNumberFormat::kNELNoLimits); - hframe->AddFrame( eLoopNumber,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 1, 1, 1, 1)); - eLoopNumber->MapWindow(); - eLoopNumber->Resize(150,30); - TGTextEntry *e= eLoopNumber->TGNumberEntry::GetNumberEntry(); - e->Connect("ReturnPressed()","ctbLoop",this,"setNLoops()"); - - - - - sprintf(tit, "Start Address: "); - - label= new TGLabel(hframe, tit); - hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1)); - label->MapWindow(); - label->SetTextJustify(kTextLeft); - - - - - eLoopStartAddr = new TGNumberEntry(hframe, 0, 9,999, TGNumberFormat::kNESHex, - TGNumberFormat::kNEANonNegative, - TGNumberFormat::kNELLimitMinMax, - 0, 1024); - hframe->AddFrame( eLoopStartAddr,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 1, 1, 1, 1)); - eLoopStartAddr->MapWindow(); - eLoopStartAddr->Resize(150,30); - - // eLoopStartAddr->SetState(kFALSE); - - label= new TGLabel(hframe, "Stop Address: "); - hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1)); - label->MapWindow(); - label->SetTextJustify(kTextLeft); - - - - - - eLoopStopAddr = new TGNumberEntry(hframe, 0, 9,999, TGNumberFormat::kNESHex, - TGNumberFormat::kNEANonNegative, - TGNumberFormat::kNELLimitMinMax, - 0, 1024); - hframe->AddFrame( eLoopStopAddr,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 1, 1, 1, 1)); - eLoopStopAddr->MapWindow(); - eLoopStopAddr->Resize(150,30); - - - - // eLoopStopAddr->SetState(kFALSE); - - - - - - -} - -void ctbLoop::setNLoops() { - try{ - myDet->setPatternLoopCycles(id, eLoopNumber->GetNumber()); - } CATCH_DISPLAY ("Could not set number of pattern loops for level " + to_string(id) + ".", "ctbLoop::setNLoops") -} - - - -void ctbLoop::update() { - try{ - - auto loop = myDet->getPatternLoopCycles(id).tsquash("Different values"); - eLoopNumber->SetNumber(loop); - auto loopaddr = myDet->getPatternLoopAddresses(id).tsquash("Different values"); - eLoopStartAddr->SetHexNumber(loopaddr[0]); - eLoopStopAddr->SetHexNumber(loopaddr[1]); - - - } CATCH_DISPLAY ("Could not get pattern loops for level " + to_string(id) + ".", "ctbLoop::update") -} - - - -ctbWait::ctbWait(TGGroupFrame *page, int i, sls::Detector *det) : TGHorizontalFrame(page, 800,800), id(i), myDet(det) { - - char tit[100]; - TGHorizontalFrame *hframe=this; - page->AddFrame(hframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 1,1,1,1)); - MapWindow(); - - - - sprintf(tit, "Wait %d (run clk): ", id); - - TGLabel *label= new TGLabel(hframe, tit); - hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1)); - label->MapWindow(); - label->SetTextJustify(kTextLeft); - - - - - eWaitTime = new TGNumberEntry(hframe, 0, 9,999, TGNumberFormat::kNESInteger, - TGNumberFormat::kNEANonNegative, - TGNumberFormat::kNELNoLimits); - hframe->AddFrame( eWaitTime,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 1, 1, 1, 1)); - eWaitTime->MapWindow(); - eWaitTime->Resize(150,30); - TGTextEntry *e= eWaitTime->TGNumberEntry::GetNumberEntry(); - e->Connect("ReturnPressed()","ctbWait",this,"setWaitTime()"); - - - - sprintf(tit, "Wait Address: "); - - label= new TGLabel(hframe, tit); - hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1)); - label->MapWindow(); - label->SetTextJustify(kTextLeft); - - - - - eWaitAddr = new TGNumberEntry(hframe, 0, 9,999, TGNumberFormat::kNESHex, - TGNumberFormat::kNEANonNegative, - TGNumberFormat::kNELLimitMinMax, - 0, 1024); - hframe->AddFrame( eWaitAddr,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 1, 1, 1, 1)); - eWaitAddr->MapWindow(); - eWaitAddr->Resize(150,30); - - // eWaitAddr->SetState(kFALSE); - -} - - - -void ctbWait::setWaitTime() { - try{ - - myDet->setPatternWaitTime(id, eWaitTime->GetNumber()); - - } CATCH_DISPLAY ("Could not set pattern wait time for level " + to_string(id) + ".", "ctbWait::setWaitTime") -} - - - -void ctbWait::update() { - try{ - - auto time = myDet->getPatternWaitTime(id).tsquash("Different values"); - auto addr = myDet->getPatternWaitAddr(id).tsquash("Different values"); - - eWaitAddr->SetHexNumber(addr); - eWaitTime->SetNumber(time); - - } CATCH_DISPLAY ("Could not get pattern loops for level " + to_string(id) + ".", "ctbWait::update") -} - - - - - - - - - -ctbPattern::ctbPattern(TGVerticalFrame *page, sls::Detector *det) - : TGGroupFrame(page,"Pattern",kVerticalFrame), myDet(det) { - - - SetTitlePos(TGGroupFrame::kLeft); - page->AddFrame(this,new TGLayoutHints( kLHintsTop | kLHintsExpandX , 10,10,10,10)); - MapWindow(); - - - char tit[100]; - - - TGHorizontalFrame* hframe=new TGHorizontalFrame(this, 800,800); - AddFrame(hframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 1,1,1,1)); - hframe->MapWindow(); - - - sprintf(tit, "Run Clock Frequency (MHz): "); - - TGLabel *label= new TGLabel(hframe, tit); - hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1)); - label->MapWindow(); - label->SetTextJustify(kTextLeft); - - - - - eRunClkFreq = new TGNumberEntry(hframe, 0, 9,999, TGNumberFormat::kNESInteger, - TGNumberFormat::kNEANonNegative, - TGNumberFormat::kNELLimitMinMax, - 0, 400); - hframe->AddFrame( eRunClkFreq,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 1, 1, 1, 1)); - eRunClkFreq->MapWindow(); - eRunClkFreq->Resize(150,30); - TGTextEntry *e= eRunClkFreq->TGNumberEntry::GetNumberEntry(); - e->Connect("ReturnPressed()","ctbPattern",this,"setRunFreq()"); - - - - - - hframe=new TGHorizontalFrame(this, 800,800); - AddFrame(hframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 1,1,1,1)); - hframe->MapWindow(); - - - - - sprintf(tit, "ADC Clock Frequency (MHz): "); - - label= new TGLabel(hframe, tit); - hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1)); - label->MapWindow(); - label->SetTextJustify(kTextLeft); - - - - - eAdcClkFreq = new TGNumberEntry(hframe, 0, 9,999, TGNumberFormat::kNESInteger, - TGNumberFormat::kNEANonNegative, - TGNumberFormat::kNELLimitMinMax, - 0, 40); - hframe->AddFrame( eAdcClkFreq,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 1, 1, 1, 1)); - eAdcClkFreq->MapWindow(); - eAdcClkFreq->Resize(150,30); - e= eAdcClkFreq->TGNumberEntry::GetNumberEntry(); - e->Connect("ReturnPressed()","ctbPattern",this,"setAdcFreq()"); - - - - - sprintf(tit, "DBIT Clock Frequency (MHz): "); - - label= new TGLabel(hframe, tit); - hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1)); - label->MapWindow(); - label->SetTextJustify(kTextLeft); - - - - - eDBitClkFreq = new TGNumberEntry(hframe, 0, 9,999, TGNumberFormat::kNESInteger, - TGNumberFormat::kNEANonNegative, - TGNumberFormat::kNELLimitMinMax, - 0, 400); - hframe->AddFrame( eDBitClkFreq,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 1, 1, 1, 1)); - eDBitClkFreq->MapWindow(); - eDBitClkFreq->Resize(150,30); - e= eDBitClkFreq->TGNumberEntry::GetNumberEntry(); - e->Connect("ReturnPressed()","ctbPattern",this,"setDBitFreq()"); - - - - - - - - - - - hframe=new TGHorizontalFrame(this, 800,800); - AddFrame(hframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 1,1,1,1)); - hframe->MapWindow(); - - - - - label= new TGLabel(hframe, "ADC Clock Phase (a.u.): "); - hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1)); - label->MapWindow(); - label->SetTextJustify(kTextLeft); - - - - - - eAdcClkPhase = new TGNumberEntry(hframe, 0, 9,999, TGNumberFormat::kNESInteger, - TGNumberFormat::kNEAAnyNumber, - TGNumberFormat::kNELLimitMinMax, - -255, 255); - hframe->AddFrame( eAdcClkPhase,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 1, 1, 1, 1)); - eAdcClkPhase->MapWindow(); - eAdcClkPhase->Resize(150,30); - e= eAdcClkPhase->TGNumberEntry::GetNumberEntry(); - e->Connect("ReturnPressed()","ctbPattern",this,"setAdcPhase()"); - - - - - label= new TGLabel(hframe, "DBit Clock Phase (a.u.): "); - hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1)); - label->MapWindow(); - label->SetTextJustify(kTextLeft); - - - - - - eDBitClkPhase = new TGNumberEntry(hframe, 0, 9,999, TGNumberFormat::kNESInteger, - TGNumberFormat::kNEAAnyNumber, - TGNumberFormat::kNELLimitMinMax, - -255, 255); - hframe->AddFrame( eDBitClkPhase,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 1, 1, 1, 1)); - eDBitClkPhase->MapWindow(); - eDBitClkPhase->Resize(150,30); - e= eDBitClkPhase->TGNumberEntry::GetNumberEntry(); - e->Connect("ReturnPressed()","ctbPattern",this,"setDBitPhase()"); - - -// label= new TGLabel(hframe, " Phase (0.15ns step): "); -// hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1)); -// label->MapWindow(); -// label->SetTextJustify(kTextLeft); - - - - - -// eRunClkPhase = new TGNumberEntry(hframe, 0, 9,999, TGNumberFormat::kNESInteger, -// TGNumberFormat::kNEANonNegative, -// TGNumberFormat::kNELLimitMinMax, -// 0, 200); -// hframe->AddFrame( eRunClkPhase,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 1, 1, 1, 1)); -// eRunClkPhase->MapWindow(); -// eRunClkPhase->Resize(150,30); -// e= eRunClkPhase->TGNumberEntry::GetNumberEntry(); -// e->Connect("ReturnPressed()","ctbPattern",this,"setRunPhase()"); - - - - - - hframe=new TGHorizontalFrame(this, 800,800); - AddFrame(hframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 1,1,1,1)); - hframe->MapWindow(); - - - - - label= new TGLabel(hframe, "Adc pipeline: "); - hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1)); - label->MapWindow(); - label->SetTextJustify(kTextLeft); - - - - - - eAdcPipeline = new TGNumberEntry(hframe, 0, 9,999, TGNumberFormat::kNESInteger, - TGNumberFormat::kNEANonNegative, - TGNumberFormat::kNELLimitMinMax, - 0, 64); - hframe->AddFrame( eAdcPipeline,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 1, 1, 1, 1)); - eAdcPipeline->MapWindow(); - eAdcPipeline->Resize(150,30); - e= eAdcPipeline->TGNumberEntry::GetNumberEntry(); - e->Connect("ReturnPressed()","ctbPattern",this,"setAdcPipeline()"); - - - - - - - label= new TGLabel(hframe, "DBIT pipeline: "); - hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1)); - label->MapWindow(); - label->SetTextJustify(kTextLeft); - - - - - - eDBitPipeline = new TGNumberEntry(hframe, 0, 9,999, TGNumberFormat::kNESInteger, - TGNumberFormat::kNEANonNegative, - TGNumberFormat::kNELLimitMinMax, - 0, 64); - hframe->AddFrame( eDBitPipeline,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 1, 1, 1, 1)); - eDBitPipeline->MapWindow(); - eDBitPipeline->Resize(150,30); - e= eDBitPipeline->TGNumberEntry::GetNumberEntry(); - e->Connect("ReturnPressed()","ctbPattern",this,"setDBitPipeline()"); - - - - - - - - - hframe=new TGHorizontalFrame(this, 800,800); - AddFrame(hframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 1,1,1,1)); - hframe->MapWindow(); - - - sprintf(tit, "Number of triggers: "); - - label= new TGLabel(hframe, tit); - hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1)); - label->MapWindow(); - label->SetTextJustify(kTextLeft); - - - - - eTriggers = new TGNumberEntry(hframe, 0, 9,999, TGNumberFormat::kNESInteger, - TGNumberFormat::kNEANonNegative, - TGNumberFormat::kNELNoLimits); - hframe->AddFrame( eTriggers,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 1, 1, 1, 1)); - eTriggers->MapWindow(); - eTriggers->Resize(150,30); - e= eTriggers->TGNumberEntry::GetNumberEntry(); - e->Connect("ReturnPressed()","ctbPattern",this,"setTriggers()"); - - - // sprintf(tit, "Number of measurements: "); - - // label= new TGLabel(hframe, tit); - // hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1)); - // label->MapWindow(); - // label->SetTextJustify(kTextLeft); - - - - - // eMeasurements = new TGNumberEntry(hframe, 0, 9,999, TGNumberFormat::kNESInteger, - // TGNumberFormat::kNEANonNegative, - // TGNumberFormat::kNELNoLimits); - // hframe->AddFrame( eMeasurements,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 1, 1, 1, 1)); - // eMeasurements->MapWindow(); - // eMeasurements->Resize(150,30); - // e= eMeasurements->TGNumberEntry::GetNumberEntry(); - // e->Connect("ReturnPressed()","ctbPattern",this,"setMeasurements()"); - - - hframe=new TGHorizontalFrame(this, 800,800); - AddFrame(hframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 1,1,1,1)); - hframe->MapWindow(); - - - sprintf(tit, "Number of frames: "); - - label= new TGLabel(hframe, tit); - hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1)); - label->MapWindow(); - label->SetTextJustify(kTextLeft); - - - - - eFrames = new TGNumberEntry(hframe, 0, 9,999, TGNumberFormat::kNESInteger, - TGNumberFormat::kNEANonNegative, - TGNumberFormat::kNELNoLimits); - hframe->AddFrame( eFrames,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 1, 1, 1, 1)); - eFrames->MapWindow(); - eFrames->Resize(150,30); - e= eFrames->TGNumberEntry::GetNumberEntry(); - e->Connect("ReturnPressed()","ctbPattern",this,"setFrames()"); - - - label= new TGLabel(hframe, " Period (s): "); - hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1)); - label->MapWindow(); - label->SetTextJustify(kTextLeft); - - - - - - ePeriod = new TGNumberEntry(hframe, 0, 9,999, TGNumberFormat::kNESReal, - TGNumberFormat::kNEANonNegative, - TGNumberFormat::kNELNoLimits); - hframe->AddFrame( ePeriod,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 1, 1, 1, 1)); - ePeriod->MapWindow(); - ePeriod->Resize(150,30); - e= ePeriod->TGNumberEntry::GetNumberEntry(); - e->Connect("ReturnPressed()","ctbPattern",this,"setPeriod()"); - - - - - - - hframe=new TGHorizontalFrame(this, 800,800); - AddFrame(hframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 1,1,1,1)); - hframe->MapWindow(); - - - sprintf(tit, "Start Address: "); - - label= new TGLabel(hframe, tit); - hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1)); - label->MapWindow(); - label->SetTextJustify(kTextLeft); - - - - - eStartAddr = new TGNumberEntry(hframe, 0, 9,999, TGNumberFormat::kNESHex, - TGNumberFormat::kNEANonNegative, - TGNumberFormat::kNELLimitMinMax, - 0, 1024); - hframe->AddFrame( eStartAddr,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 1, 1, 1, 1)); - eStartAddr->MapWindow(); - eStartAddr->Resize(150,30); - - eStartAddr->SetState(kFALSE); - - label= new TGLabel(hframe, "Stop Address: "); - hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1)); - label->MapWindow(); - label->SetTextJustify(kTextLeft); - - - - - - eStopAddr = new TGNumberEntry(hframe, 0, 9,999, TGNumberFormat::kNESHex, - TGNumberFormat::kNEANonNegative, - TGNumberFormat::kNELLimitMinMax, - 0, 1024); - hframe->AddFrame( eStopAddr,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 1, 1, 1, 1)); - eStopAddr->MapWindow(); - eStopAddr->Resize(150,30); - - - - - eStopAddr->SetState(kFALSE); - - - - - - - int idac=0; - for (idac=0; idacMapWindow(); - - - - label= new TGLabel(hframe, "Compiler: "); - hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1)); - label->MapWindow(); - label->SetTextJustify(kTextLeft); - - - - - patternCompiler=new TGTextEntry(hframe,"generate.sh"); - hframe->AddFrame(patternCompiler,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1)); - patternCompiler->MapWindow(); - // patternCompiler->SetTextJustify(kTextLeft); - patternCompiler->Connect("ReturnPressed()","ctbPattern",this,"setCompiler()"); - - - browseCompiler=new TGTextButton(hframe,"Browse"); - hframe->AddFrame(browseCompiler,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1)); - browseCompiler->MapWindow(); - // patternCompiler->SetTextJustify(kTextLeft); - browseCompiler->Connect("Clicked()","ctbPattern",this,"chooseCompiler()"); - - - - - hframe=new TGHorizontalFrame(this, 800,800); - AddFrame(hframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 1,1,1,1)); - hframe->MapWindow(); - - - label= new TGLabel(hframe, "Pattern: "); - hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1)); - label->MapWindow(); - label->SetTextJustify(kTextLeft); - - - patternFile=new TGTextEntry(hframe,"file.p"); - hframe->AddFrame(patternFile,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1)); - patternFile->MapWindow(); - patternFile->Connect("ReturnPressed()","ctbPattern",this,"setFile()"); - // patternFile->SetTextJustify(kTextLeft); - - - - browseFile=new TGTextButton(hframe,"Browse"); - hframe->AddFrame(browseFile,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1)); - browseFile->MapWindow(); - // patternCompiler->SetTextJustify(kTextLeft); - browseFile->Connect("Clicked()","ctbPattern",this,"choosePattern()"); - - - - - hframe=new TGHorizontalFrame(this, 800,800); - AddFrame(hframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 1,1,1,1)); - hframe->MapWindow(); - - - sprintf(tit, "Samples per frame - "); - - label= new TGLabel(hframe, tit); - hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1)); - label->MapWindow(); - label->SetTextJustify(kTextLeft); - - - sprintf(tit, "Analog: "); - - label= new TGLabel(hframe, tit); - hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1)); - label->MapWindow(); - label->SetTextJustify(kTextLeft); - - - - eAnalogSamples = new TGNumberEntry(hframe, 0, 9,999, TGNumberFormat::kNESInteger, - TGNumberFormat::kNEANonNegative, - TGNumberFormat::kNELLimitMinMax, - 1, 8192); - hframe->AddFrame( eAnalogSamples,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 1, 1, 1, 1)); - eAnalogSamples->MapWindow(); - eAnalogSamples->Resize(150,30); - e= eAnalogSamples->TGNumberEntry::GetNumberEntry(); - e->Connect("ReturnPressed()","ctbPattern",this,"setAnalogSamples()"); - - sprintf(tit, "Digital: "); - - label= new TGLabel(hframe, tit); - hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1)); - label->MapWindow(); - label->SetTextJustify(kTextLeft); - - - - eDigitalSamples = new TGNumberEntry(hframe, 0, 9,999, TGNumberFormat::kNESInteger, - TGNumberFormat::kNEANonNegative, - TGNumberFormat::kNELLimitMinMax, - 1, 8192); - hframe->AddFrame( eDigitalSamples,new TGLayoutHints(kLHintsTop | kLHintsExpandX, 1, 1, 1, 1)); - eDigitalSamples->MapWindow(); - eDigitalSamples->Resize(150,30); - e= eDigitalSamples->TGNumberEntry::GetNumberEntry(); - e->Connect("ReturnPressed()","ctbPattern",this,"setDigitalSamples()"); - - - hframe=new TGHorizontalFrame(this, 800,800); - AddFrame(hframe,new TGLayoutHints(kLHintsTop | kLHintsExpandX , 1,1,1,1)); - hframe->MapWindow(); - - - sprintf(tit, "Read Out Mode: "); - - label= new TGLabel(hframe, tit); - hframe->AddFrame(label,new TGLayoutHints(kLHintsTop | kLHintsLeft| kLHintsExpandX, 1, 1, 1, 1)); - label->MapWindow(); - label->SetTextJustify(kTextLeft); - - - cbAnalog= new TGCheckButton(hframe, "Analog"); - hframe->AddFrame(cbAnalog,new TGLayoutHints(kLHintsTop | kLHintsLeft | kLHintsExpandX, 5, 5, 5, 5)); - cbAnalog->MapWindow(); - cbAnalog->SetTextJustify(kTextRight); - cbAnalog->Connect("Toggled(Bool_t)","ctbPattern",this,"setReadoutMode(Bool_t)"); - - cbDigital= new TGCheckButton(hframe, "Digital"); - hframe->AddFrame(cbDigital,new TGLayoutHints(kLHintsTop | kLHintsLeft | kLHintsExpandX, 5, 5, 5, 5)); - cbDigital->MapWindow(); - cbDigital->SetTextJustify(kTextRight); - cbDigital->Connect("Toggled(Bool_t)","ctbPattern",this,"setReadoutMode(Bool_t)"); - - - - -} - -void ctbPattern::update() { - try{ - auto retval = myDet->getRUNClock().tsquash("Different values"); - eRunClkFreq->SetNumber(retval); - } CATCH_DISPLAY ("Could not get run clock.", "ctbPattern::update") - - try{ - auto retval = myDet->getADCClock().tsquash("Different values"); - eAdcClkFreq->SetNumber(retval); - } CATCH_DISPLAY ("Could not get adc clock.", "ctbPattern::update") - - try{ - auto retval = myDet->getADCPhase().tsquash("Different values"); - eAdcClkPhase->SetNumber(retval); - } CATCH_DISPLAY ("Could not get adc phase shift.", "ctbPattern::update") - - try{ - auto retval = myDet->getADCPipeline().tsquash("Different values"); - eAdcPipeline->SetNumber(retval); - } CATCH_DISPLAY ("Could not get adc pipeline.", "ctbPattern::update") - - try{ - auto retval = myDet->getDBITClock().tsquash("Different values"); - eDBitClkFreq->SetNumber(retval); - } CATCH_DISPLAY ("Could not get dbit clock.", "ctbPattern::update") - - try{ - auto retval = myDet->getDBITPhase().tsquash("Different values"); - eDBitClkPhase->SetNumber(retval); - } CATCH_DISPLAY ("Could not get dbit phase shift.", "ctbPattern::update") - - try{ - auto retval = myDet->getDBITPipeline().tsquash("Different values"); - eDBitPipeline->SetNumber(retval); - } CATCH_DISPLAY ("Could not get dbit pipeline.", "ctbPattern::update") - - try{ - auto retval = myDet->getNumberOfFrames().tsquash("Different values"); - eFrames->SetNumber(retval); - } CATCH_DISPLAY ("Could not get number of frames.", "ctbPattern::update") - - try{ - auto timeNs = myDet->getPeriod().tsquash("Different values"); - ePeriod->SetNumber(ctbDefs::ConvertChronoNStoDoubleS(timeNs)); - } CATCH_DISPLAY ("Could not get period.", "ctbPattern::update") - - try{ - auto retval = myDet->getNumberOfTriggers().tsquash("Different values"); - eTriggers->SetNumber(retval); - } CATCH_DISPLAY ("Could not get number of triggers.", "ctbPattern::update") - - try{ - auto retval = myDet->getPatternLoopAddresses(-1).tsquash("Different values"); - eStartAddr->SetHexNumber(retval[0]); - eStopAddr->SetHexNumber(retval[1]); - } CATCH_DISPLAY ("Could not get dbit phase shift.", "ctbPattern::update") - - for (int iloop=0; iloopupdate(); - } - - for (int iwait=0; iwaitupdate(); - } - - getAnalogSamples(); - getDigitalSamples(); - getReadoutMode(); -} - - -void ctbPattern::setFile() { - patternFileChanged(patternFile->GetText()); - -} - - -void ctbPattern::setCompiler() { - patternCompilerChanged(patternCompiler->GetText()); -} - - -void ctbPattern::patternFileChanged(const char* t){ - Emit("patternFileChanged(const char*)", t); -} - - -void ctbPattern::patternCompilerChanged(const char* t){ - Emit("patternCompilerChanged(const char*)", t); - -} - - -void ctbPattern::setPatternAlias(string line){ - char fname[10000]; - if (sscanf(line.c_str(),"PATCOMPILER %s",fname)) { - patternCompiler->SetText(fname); - patternCompilerChanged(patternCompiler->GetText()); - } else if (sscanf(line.c_str(),"PATFILE %s",fname)) { - patternFile->SetText(fname); - patternFileChanged(patternFile->GetText()); - } -} - - -string ctbPattern::getPatternAlias() { - char line[100000]; - sprintf(line, "PATCOMPILER %s\nPATFILE %s\n",patternCompiler->GetText(),patternFile->GetText()); - return line; -} - - -void ctbPattern::chooseCompiler() { - 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) { - patternCompiler->SetText(fi.fFilename); - patternCompilerChanged(patternCompiler->GetText()); - } -} - - -void ctbPattern::choosePattern() { - 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) { - patternFile->SetText(fi.fFilename); - patternFileChanged(patternFile->GetText()); - } - -} - - -string ctbPattern::getCompiler() { - return string(patternCompiler->GetText()); - -} - -string ctbPattern::getPatternFile() { - return string(patternFile->GetText()); - -} - -void ctbPattern::setFrames() { - try{ - myDet->setNumberOfFrames(eFrames->GetNumber()); - } CATCH_DISPLAY ("Could not set number of frames", "ctbPattern::setFrames") -} - -void ctbPattern::setTriggers() { - try{ - myDet->setNumberOfTriggers(eTriggers->GetNumber()); - } CATCH_DISPLAY ("Could not set number of triggers", "ctbPattern::setTriggers") -} - -void ctbPattern::setPeriod() { - using std::chrono::duration; - using std::chrono::duration_cast; - using std::chrono::nanoseconds; - try{ - auto timeNs = ctbDefs::ConvertDoubleStoChronoNS(ePeriod->GetNumber()); - myDet->setPeriod(timeNs); - } CATCH_DISPLAY ("Could not set period", "ctbPattern::setPeriod") -} - -void ctbPattern::setAdcFreq() { - try{ - myDet->setADCClock(eAdcClkFreq->GetNumber()); - } CATCH_DISPLAY ("Could not set adc clock", "ctbPattern::setAdcFreq") -} - -void ctbPattern::setRunFreq() { - try{ - myDet->setRUNClock(eRunClkFreq->GetNumber()); - } CATCH_DISPLAY ("Could not set run clock", "ctbPattern::setRunFreq") -} - -void ctbPattern::setDBitFreq() { - try{ - myDet->setDBITClock(eDBitClkFreq->GetNumber()); - } CATCH_DISPLAY ("Could not set dbit clock", "ctbPattern::setDBitFreq") -} - -void ctbPattern::setAdcPhase() { - try{ - myDet->setADCPhase(eAdcClkPhase->GetNumber()); - } CATCH_DISPLAY ("Could not set adc phase shift", "ctbPattern::setAdcPhase") -} - -void ctbPattern::setDBitPhase() { - try{ - myDet->setDBITPhase(eDBitClkPhase->GetNumber()); - } CATCH_DISPLAY ("Could not set dbit phase shift", "ctbPattern::setDBitPhase") -} - -void ctbPattern::setAdcPipeline() { - try{ - myDet->setADCPipeline(eAdcPipeline->GetNumber()); - } CATCH_DISPLAY ("Could not set adc pipeline", "ctbPattern::setAdcPipeline") -} - -void ctbPattern::setDBitPipeline() { - try{ - myDet->setDBITPipeline(eDBitPipeline->GetNumber()); - } CATCH_DISPLAY ("Could not set dbit pipeline", "ctbPattern::setDBitPipeline") -} - - -void ctbPattern::setAnalogSamples() { - try{ - myDet->setNumberOfAnalogSamples(eAnalogSamples->GetNumber()); - } CATCH_DISPLAY ("Could not set number of analog sampels", "ctbPattern::setAnalogSamples") - - analogSamplesChanged(eAnalogSamples->GetNumber()); -} - -void ctbPattern::setDigitalSamples() { - try{ - myDet->setNumberOfDigitalSamples(eDigitalSamples->GetNumber()); - } CATCH_DISPLAY ("Could not set number of digital samples", "ctbPattern::setDigitalSamples") - - digitalSamplesChanged(eDigitalSamples->GetNumber()); -} - -void ctbPattern::setReadoutMode(Bool_t) { - try { - slsDetectorDefs::readoutMode flag = slsDetectorDefs::ANALOG_ONLY; - if (cbAnalog->IsOn() && cbDigital->IsOn()) - flag=slsDetectorDefs::ANALOG_AND_DIGITAL; - else if (~cbAnalog->IsOn() && cbDigital->IsOn()) - flag=slsDetectorDefs::DIGITAL_ONLY; - else if (cbAnalog->IsOn() && ~cbDigital->IsOn()) - flag=slsDetectorDefs::ANALOG_ONLY; - else { - throw runtime_error("unkown readout flag"); - } - myDet->setReadoutMode(flag); - cout << "Set readout flag: " << flag << endl; - } CATCH_DISPLAY ("Could not set readout flag", "ctbPattern::setReadoutMode") - - getReadoutMode(); -} - -void ctbPattern::readoutModeChanged(int flags) { - Emit("readoutModeChanged(Int_t)",(int)flags); - -} - -int ctbPattern::getReadoutMode() { - int retval=slsDetectorDefs::ANALOG_ONLY; - - if (myDet->getDetectorType().squash() == slsDetectorDefs::CHIPTESTBOARD) { - try{ - retval = myDet->getReadoutMode().tsquash("Different values"); - } CATCH_DISPLAY ("Could not get readout flags", "ctbPattern::getReadoutMode") - - switch(retval) { - case slsDetectorDefs::ANALOG_AND_DIGITAL: - cout << "analog and digital" << endl; - cbAnalog->SetOn(kTRUE); - cbDigital->SetOn(kTRUE); - break; - case slsDetectorDefs::DIGITAL_ONLY: - cout << "digital only" << endl; - cbAnalog->SetOn(kFALSE); - cbDigital->SetOn(kTRUE); - break; - case slsDetectorDefs::ANALOG_ONLY: - cout << "analog only" << endl; - cbAnalog->SetOn(kTRUE); - cbDigital->SetOn(kFALSE); - break; - default: - throw("unknown readout flag"); - } - } else { - cbAnalog->SetOn(kTRUE); - cbDigital->SetOn(kFALSE); - } - - Emit("readoutModeChanged(int)",static_cast(retval)); - return retval; - - -} - -int ctbPattern::getAnalogSamples() { - try{ - auto retval = myDet->getNumberOfAnalogSamples().tsquash("Different values"); - eAnalogSamples->SetNumber((Double_t)retval); - Emit("analogSamplesChanged(const int)", eAnalogSamples->GetNumber()); - return eAnalogSamples->GetNumber(); - } CATCH_DISPLAY ("Could not get number of triggers.", "ctbPattern::update") - - return -1; -} - -int ctbPattern::getDigitalSamples() { - int retval=0; - if (myDet->getDetectorType().squash() == slsDetectorDefs::CHIPTESTBOARD) { - try{ - auto retval = myDet->getNumberOfDigitalSamples().tsquash("Different values"); - } CATCH_DISPLAY ("Could not get number of digital samples.", "ctbPattern::getDigitalSamples") - } - eDigitalSamples->SetNumber((Double_t)retval); - Emit("digitalSamplesChanged(const int)", eDigitalSamples->GetNumber()); - return eDigitalSamples->GetNumber(); - - - return -1; -} - - -void ctbPattern::analogSamplesChanged(const int t){ - Emit("analogSamplesChanged(const int)", t); -} - -void ctbPattern::digitalSamplesChanged(const int t){ - Emit("digitalSamplesChanged(const int)", t); -} diff --git a/ctbGui/ctbPattern.h b/ctbGui/ctbPattern.h deleted file mode 100644 index 6f85974a1..000000000 --- a/ctbGui/ctbPattern.h +++ /dev/null @@ -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 - - -#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 -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 diff --git a/ctbGui/ctbPowers.cpp b/ctbGui/ctbPowers.cpp deleted file mode 100644 index 498ec2c13..000000000 --- a/ctbGui/ctbPowers.cpp +++ /dev/null @@ -1,225 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-other -// Copyright (C) 2021 Contributors to the SLS Detector Package -#include - - -#include -#include -#include -#include - -#include -#include -#include - -#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(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(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(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; idacsetLabel(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; igetLabel() << 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; igetValue << endl; - // line << "dac:" << i << " " << dacs[i]->getValue() << endl; - // } - return line.str(); -} - - - -void ctbPowers::update() { - for (int idac=0; idacgetValue(); - - } -} diff --git a/ctbGui/ctbPowers.h b/ctbGui/ctbPowers.h deleted file mode 100644 index d0c39f1c7..000000000 --- a/ctbGui/ctbPowers.h +++ /dev/null @@ -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 - -#define NPOWERS 6 - - - -class TGTextEntry; -class TGLabel; -class TGNumberEntry; -class TGCheckButton; - - - - -namespace sls -{ - class Detector; -}; - -#include -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 diff --git a/ctbGui/ctbSignals.cpp b/ctbGui/ctbSignals.cpp deleted file mode 100644 index f1e0c840f..000000000 --- a/ctbGui/ctbSignals.cpp +++ /dev/null @@ -1,543 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-other -// Copyright (C) 2021 Contributors to the SLS Detector Package -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - - -#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 <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<SetEnabled(b); -} - -void ctbSignal::ColorChanged(Pixel_t p){ - ToggledSignalPlot(id); -} - - -void ctbSignal::ToggledSignalOutput(Int_t b) { - cout << "Toggle signal " << id << " " << b << " " << sOutput->IsOn() <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; idacAddFrame(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 && issetSignalAlias(tit,plot,col); - } - return is; - -} - -string ctbSignals::getSignalAlias() { - - ostringstream oss; - for (int is=0; isgetSignalAlias() << endl; - - - return oss.str(); - -} - - -void ctbSignals::update() { - try { - - Long64_t oreg = static_cast(myDet->getPatternIOControl().tsquash("Different values")); - cout << hex << oreg << dec << endl; - - for (int idac=0; idacsetOutput(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(myDet->getPatternIOControl().tsquash("Different values")); - Long64_t m=((Long64_t)1)<isOutput()) { - cout << " or " << m ; - oreg|=m; - } else { - cout << " not " << ~m ; - oreg&=~m; - } - cout << " after " << oreg << endl; - - myDet->setPatternIOControl(static_cast(oreg)); - oreg = static_cast(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 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 && igetColor(); - return static_cast(-1); -} - -int ctbSignals::getPlot(int i){ - if (i>=0 && iisPlot(); - 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") -} diff --git a/ctbGui/ctbSignals.h b/ctbGui/ctbSignals.h deleted file mode 100644 index eb3deb221..000000000 --- a/ctbGui/ctbSignals.h +++ /dev/null @@ -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 - - -#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 -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 diff --git a/ctbGui/ctbSlowAdcs.cpp b/ctbGui/ctbSlowAdcs.cpp deleted file mode 100644 index 6507e0d17..000000000 --- a/ctbGui/ctbSlowAdcs.cpp +++ /dev/null @@ -1,184 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-other -// Copyright (C) 2021 Contributors to the SLS Detector Package - -#include -#include -#include - -#include -#include -#include -#include - -#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(slsDetectorDefs::SLOW_ADC_TEMP)) { - - int val = myDet->getTemperature(static_cast(id)).tsquash("Different values"); - cout << "slow adc temp" << " " << val << endl; - - s = to_string(val) + " " + to_string(0x00b0) + "C";//�C - dacsValue->SetText(s.c_str()); - return val; - } - - // mv - else { - - int val = myDet->getSlowADC(static_cast(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; idacsetLabel((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 && issetLabel(tit); - return is; - -} - -string ctbSlowAdcs::getSlowAdcAlias() { - - ostringstream line; - - for (int i=0; igetLabel() << endl; - return line.str(); -} - - - - -string ctbSlowAdcs::getAdcParameters() { - - ostringstream line; - - for (int i=0; igetValue << 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; idacgetValue(); - } -} diff --git a/ctbGui/ctbSlowAdcs.h b/ctbGui/ctbSlowAdcs.h deleted file mode 100644 index a25bbe5b1..000000000 --- a/ctbGui/ctbSlowAdcs.h +++ /dev/null @@ -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 - - -//#define NDACS 16 -#define NSLOWADCS 8 - - - - -class TGTextEntry; -class TGLabel; -class TGNumberEntry; -class TGCheckButton; -class TGTextButton; - - - -namespace sls -{ - class Detector; -}; - -#include -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 - diff --git a/pyctbgui/.github/workflows/build-and-test-inplace.yml b/pyctbgui/.github/workflows/build-and-test-inplace.yml new file mode 100644 index 000000000..465bfcd13 --- /dev/null +++ b/pyctbgui/.github/workflows/build-and-test-inplace.yml @@ -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 \ No newline at end of file diff --git a/pyctbgui/.gitignore b/pyctbgui/.gitignore new file mode 100644 index 000000000..53456bd67 --- /dev/null +++ b/pyctbgui/.gitignore @@ -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/ diff --git a/pyctbgui/.pre-commit-config.yaml b/pyctbgui/.pre-commit-config.yaml new file mode 100644 index 000000000..f45532776 --- /dev/null +++ b/pyctbgui/.pre-commit-config.yaml @@ -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 diff --git a/pyctbgui/CtbGui b/pyctbgui/CtbGui new file mode 100755 index 000000000..0312b6d61 --- /dev/null +++ b/pyctbgui/CtbGui @@ -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_() diff --git a/pyctbgui/MANIFEST.in b/pyctbgui/MANIFEST.in new file mode 100644 index 000000000..f0aa8ba82 --- /dev/null +++ b/pyctbgui/MANIFEST.in @@ -0,0 +1,2 @@ +include pyctbgui/ui/*.ui +recursive-include src *.c *.h \ No newline at end of file diff --git a/pyctbgui/Makefile b/pyctbgui/Makefile new file mode 100644 index 000000000..f1b26ec09 --- /dev/null +++ b/pyctbgui/Makefile @@ -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}' diff --git a/pyctbgui/README.md b/pyctbgui/README.md new file mode 100644 index 000000000..d38bdfb40 --- /dev/null +++ b/pyctbgui/README.md @@ -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 +``` diff --git a/pyctbgui/client.py b/pyctbgui/client.py new file mode 100644 index 000000000..36e92f937 --- /dev/null +++ b/pyctbgui/client.py @@ -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.rx_zmqip +zmqport = det.rx_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_() diff --git a/pyctbgui/pyctbgui/__init__.py b/pyctbgui/pyctbgui/__init__.py new file mode 100644 index 000000000..561a39e95 --- /dev/null +++ b/pyctbgui/pyctbgui/__init__.py @@ -0,0 +1,2 @@ +from .utils.defines import Defines as defs +from .utils import bit_utils, alias_utility diff --git a/pyctbgui/pyctbgui/services/ADC.py b/pyctbgui/pyctbgui/services/ADC.py new file mode 100644 index 000000000..f470fc917 --- /dev/null +++ b/pyctbgui/pyctbgui/services/ADC.py @@ -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()}", + ] diff --git a/pyctbgui/pyctbgui/services/Acquisition.py b/pyctbgui/pyctbgui/services/Acquisition.py new file mode 100644 index 000000000..9ececaf82 --- /dev/null +++ b/pyctbgui/pyctbgui/services/Acquisition.py @@ -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.rx_zmqip + self.zmqport = self.det.rx_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()}', + ] diff --git a/pyctbgui/pyctbgui/services/DACs.py b/pyctbgui/pyctbgui/services/DACs.py new file mode 100644 index 000000000..1bd7ab721 --- /dev/null +++ b/pyctbgui/pyctbgui/services/DACs.py @@ -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 diff --git a/pyctbgui/pyctbgui/services/Pattern.py b/pyctbgui/pyctbgui/services/Pattern.py new file mode 100644 index 000000000..e7e274ff9 --- /dev/null +++ b/pyctbgui/pyctbgui/services/Pattern.py @@ -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 diff --git a/pyctbgui/pyctbgui/services/Plot.py b/pyctbgui/pyctbgui/services/Plot.py new file mode 100644 index 000000000..0dfedd205 --- /dev/null +++ b/pyctbgui/pyctbgui/services/Plot.py @@ -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', "Output [ADC]") + self.mainWindow.plotAnalogWaveform.setLabel( + 'bottom', "Analog Sample [#]") + self.mainWindow.plotDigitalWaveform.setLabel( + 'left', "Digital Bit") + self.mainWindow.plotDigitalWaveform.setLabel( + 'bottom', "Digital Sample [#]") + self.mainWindow.plotTransceiverWaveform.setLabel( + 'left', "Transceiver Bit") + self.mainWindow.plotTransceiverWaveform.setLabel( + 'bottom', "Transceiver Sample [#]") + + 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 diff --git a/pyctbgui/pyctbgui/services/PowerSupplies.py b/pyctbgui/pyctbgui/services/PowerSupplies.py new file mode 100644 index 000000000..ec8d2f5dd --- /dev/null +++ b/pyctbgui/pyctbgui/services/PowerSupplies.py @@ -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 diff --git a/pyctbgui/pyctbgui/services/Signals.py b/pyctbgui/pyctbgui/services/Signals.py new file mode 100644 index 000000000..a06b9a412 --- /dev/null +++ b/pyctbgui/pyctbgui/services/Signals.py @@ -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 diff --git a/pyctbgui/pyctbgui/services/SlowADCs.py b/pyctbgui/pyctbgui/services/SlowADCs.py new file mode 100644 index 000000000..4b73b18f0 --- /dev/null +++ b/pyctbgui/pyctbgui/services/SlowADCs.py @@ -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') diff --git a/pyctbgui/pyctbgui/services/Transceiver.py b/pyctbgui/pyctbgui/services/Transceiver.py new file mode 100644 index 000000000..98c8fc541 --- /dev/null +++ b/pyctbgui/pyctbgui/services/Transceiver.py @@ -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())] diff --git a/pyctbgui/pyctbgui/services/__init__.py b/pyctbgui/pyctbgui/services/__init__.py new file mode 100644 index 000000000..9f3e43434 --- /dev/null +++ b/pyctbgui/pyctbgui/services/__init__.py @@ -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 diff --git a/pyctbgui/pyctbgui/ui/CtbGui.ui b/pyctbgui/pyctbgui/ui/CtbGui.ui new file mode 100644 index 000000000..3d96407aa --- /dev/null +++ b/pyctbgui/pyctbgui/ui/CtbGui.ui @@ -0,0 +1,779 @@ + + + MainWindow + + + + 0 + 0 + 1444 + 943 + + + + Chip Test Board + + + false + + + + + 870 + 890 + + + + + 870 + 890 + + + + + 9 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 50 + 0 + + + + QFrame::Plain + + + true + + + + + 0 + 0 + 870 + 879 + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 16777215 + 16777215 + + + + QFrame::NoFrame + + + QFrame::Plain + + + 0 + + + + 0 + + + 9 + + + 0 + + + 0 + + + + + + 870 + 870 + + + + + 870 + 870 + + + + 0 + + + + DACs + + + + + 0 + 0 + 851 + 841 + + + + + 711 + 791 + + + + + + + Power Supplies + + + + + -1 + -1 + 841 + 821 + + + + + + + Slow ADCs + + + + + 0 + 0 + 871 + 821 + + + + + 871 + 571 + + + + + + + Signals + + + + + 0 + 0 + 831 + 821 + + + + + 831 + 821 + + + + + + + Transceivers + + + + + 9 + 19 + 841 + 341 + + + + + 841 + 181 + + + + + + + ADCs + + + + + -1 + -1 + 841 + 821 + + + + + + + Pattern + + + + + 0 + 0 + 851 + 831 + + + + + + + Acquisition + + + + + -10 + 0 + 860 + 800 + + + + + 860 + 800 + + + + + + + Plot + + + + + 0 + 0 + 860 + 800 + + + + + 860 + 800 + + + + + + + + + + + + + + + + + + + 0 + 0 + 1444 + 25 + + + + + File + + + + + + + + Help + + + + + + + + + + + + 0 + 0 + + + + + 568 + 214 + + + + + 524287 + 524287 + + + + QDockWidget::DockWidgetFloatable|QDockWidget::DockWidgetMovable + + + Qt::RightDockWidgetArea + + + 2 + + + + + + + + 16777215 + 100 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + 70 + 0 + + + + + 70 + 16777215 + + + + 0 + + + + + + + + 100 + 0 + + + + 24 + + + + + + + + 0 + 36 + + + + + 100 + 16777215 + + + + + + + + + 85 + 170 + 127 + + + + + + + 85 + 170 + 127 + + + + + + + 85 + 170 + 127 + + + + + + + + + 85 + 170 + 127 + + + + + + + 85 + 170 + 127 + + + + + + + 85 + 170 + 127 + + + + + + + + + 85 + 170 + 127 + + + + + + + 85 + 170 + 127 + + + + + + + 85 + 170 + 127 + + + + + + + + Shift + Enter is the keyboard shortcut to start/stop acquisition from any tab + + + QPushButton {background-color: rgb(85, 170, 127);} +QPushButton:checked{background-color: red;} + + + Start + + + true + + + + + + + + 110 + 0 + + + + IDLE + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 70 + 16777215 + + + + Acquired: + + + + + + + + 70 + 0 + + + + + 70 + 16777215 + + + + 0 + + + + + + + + 0 + 0 + + + + + 100 + 16777215 + + + + Measurement: + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + # + + + + + + + + + + + + + + Load Parameters + + + + + Save + + + + + Exit + + + + + Info + + + + + Keyboard Shortcuts + + + + + Save Parameters + + + + + + PowerSuppliesTab + QWidget +
pyctbgui.services.PowerSupplies
+ 1 +
+ + DacTab + QWidget +
pyctbgui.services.DACs
+ 1 +
+ + SlowAdcTab + QWidget +
pyctbgui.services.SlowADCs
+ 1 +
+ + SignalsTab + QWidget +
pyctbgui.services.Signals
+ 1 +
+ + TransceiverTab + QWidget +
pyctbgui.services.Transceiver
+ 1 +
+ + AdcTab + QWidget +
pyctbgui.services.ADC
+ 1 +
+ + PatternTab + QWidget +
pyctbgui.services.Pattern
+ 1 +
+ + AcquisitionTab + QWidget +
pyctbgui.services.Acquisition
+ 1 +
+ + PlotTab + QWidget +
pyctbgui.services.Plot
+ 1 +
+
+ + + + actionExit + triggered() + MainWindow + close() + + + -1 + -1 + + + 753 + 496 + + + + +
diff --git a/pyctbgui/pyctbgui/ui/Dacs.ui b/pyctbgui/pyctbgui/ui/Dacs.ui new file mode 100644 index 000000000..940f93c7d --- /dev/null +++ b/pyctbgui/pyctbgui/ui/Dacs.ui @@ -0,0 +1,1198 @@ + + + Form + + + + 0 + 0 + 870 + 791 + + + + + 870 + 791 + + + + + 2000 + 2000 + + + + + 711 + 791 + + + + Form + + + + + 20 + 10 + 711 + 791 + + + + + 711 + 791 + + + + + 1000 + 1000 + + + + QFrame::StyledPanel + + + QFrame::Sunken + + + + 11 + + + + + false + + + Unchecking will set DAC in tristate (sends -100).<br> +Checking sends nothing to DAC + + + DAC 1 + + + + + + + Checking or unchecking this will only get DAC values on the right (with this condition).<br> +Only pressing enter on spinbox will set DAC (with this condition). + + + mV + + + + + + + false + + + Unchecking will set DAC in tristate (sends -100).<br> +Checking sends nothing to DAC + + + DAC 7 + + + + + + + false + + + Unchecking will set DAC in tristate (sends -100).<br> +Checking sends nothing to DAC + + + DAC 8 + + + + + + + Checking or unchecking this will only get DAC values on the right (with this condition).<br> +Only pressing enter on spinbox will set DAC (with this condition). + + + mV + + + + + + + Checking or unchecking this will only get DAC values on the right (with this condition).<br> +Only pressing enter on spinbox will set DAC (with this condition). + + + mV + + + + + + + false + + + Unchecking will set DAC in tristate (sends -100).<br> +Checking sends nothing to DAC + + + DAC 15 + + + + + + + false + + + Unchecking will set DAC in tristate (sends -100).<br> +Checking sends nothing to DAC + + + DAC 2 + + + + + + + Checking or unchecking this will only get DAC values on the right (with this condition).<br> +Only pressing enter on spinbox will set DAC (with this condition). + + + mV + + + + + + + 0 + + + + + + + Checking or unchecking this will only get DAC values on the right (with this condition).<br> +Only pressing enter on spinbox will set DAC (with this condition). + + + mV + + + + + + + + 0 + 32 + + + + + 16777215 + 32 + + + + Only accepts value range (0 - 4096). Only modifying this or pressing enter will set DAC. + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 4096 + + + + + + + 0 + + + + + + + + 0 + 32 + + + + + 16777215 + 32 + + + + Only accepts value range (0 - 4096). Only modifying this or pressing enter will set DAC. + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 4096 + + + + + + + false + + + Unchecking will set DAC in tristate (sends -100).<br> +Checking sends nothing to DAC + + + DAC 14 + + + + + + + 0 + + + + + + + 0 + + + + + + + 0 + + + + + + + 0 + + + + + + + false + + + Unchecking will set DAC in tristate (sends -100).<br> +Checking sends nothing to DAC + + + DAC 16 + + + + + + + false + + + Unchecking will set DAC in tristate (sends -100).<br> +Checking sends nothing to DAC + + + DAC 0 + + + + + + + Checking or unchecking this will only get DAC values on the right (with this condition).<br> +Only pressing enter on spinbox will set DAC (with this condition). + + + mV + + + + + + + Checking or unchecking this will only get DAC values on the right (with this condition).<br> +Only pressing enter on spinbox will set DAC (with this condition). + + + mV + + + + + + + 0 + + + + + + + false + + + Unchecking will set DAC in tristate (sends -100).<br> +Checking sends nothing to DAC + + + DAC 6 + + + + + + + + 0 + 32 + + + + + 16777215 + 32 + + + + Only accepts value range (0 - 4096). Only modifying this or pressing enter will set DAC. + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 0 + + + 4096 + + + + + + + false + + + Unchecking will set DAC in tristate (sends -100).<br> +Checking sends nothing to DAC + + + DAC 9 + + + + + + + 0 + + + + + + + mV + + + + + + + Checking or unchecking this will only get DAC values on the right (with this condition).<br> +Only pressing enter on spinbox will set DAC (with this condition). + + + mV + + + + + + + 0 + + + + + + + Checking or unchecking this will only get DAC values on the right (with this condition).<br> +Only pressing enter on spinbox will set DAC (with this condition). + + + mV + + + + + + + + 0 + 32 + + + + + 16777215 + 32 + + + + Only accepts value range (0 - 4096). Only modifying this or pressing enter will set DAC. + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 4096 + + + + + + + V + + + + + + + 0 + + + + + + + Checking or unchecking this will only get DAC values on the right (with this condition).<br> +Only pressing enter on spinbox will set DAC (with this condition). + + + mV + + + + + + + false + + + Unchecking will set DAC in tristate (sends -100).<br> +Checking sends nothing to DAC + + + DAC 5 + + + + + + + + 0 + 32 + + + + + 16777215 + 32 + + + + Only accepts value range (0 - 4096). Only modifying this or pressing enter will set DAC. + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 4096 + + + + + + + false + + + Unchecking will set DAC in tristate (sends -100).<br> +Checking sends nothing to DAC + + + DAC 13 + + + + + + + 0 + + + + + + + 0 + + + + + + + + 0 + 32 + + + + + 16777215 + 32 + + + + Only accepts value range (0 - 4096). Only modifying this or pressing enter will set DAC. + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 4096 + + + + + + + false + + + Unchecking will set DAC in tristate (sends -100).<br> +Checking sends nothing to DAC + + + DAC 17 + + + + + + + 0 + + + + + + + High Voltage + + + + + + + Qt::LeftToRight + + + + 1000 + + + + + 1140 + + + + + 1330 + + + + + 1600 + + + + + 2000 + + + + + + + + 0 + + + + + + + + 0 + 32 + + + + + 16777215 + 32 + + + + Only accepts value range (0 - 4096). Only modifying this or pressing enter will set DAC. + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 4096 + + + + + + + + 0 + 32 + + + + + 16777215 + 32 + + + + Only accepts value range (0 - 4096). Only modifying this or pressing enter will set DAC. + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 4096 + + + + + + + Checking or unchecking this will only get DAC values on the right (with this condition).<br> +Only pressing enter on spinbox will set DAC (with this condition). + + + mV + + + + + + + Checking or unchecking this will only get DAC values on the right (with this condition).<br> +Only pressing enter on spinbox will set DAC (with this condition). + + + mV + + + + + + + Checking or unchecking this will only get DAC values on the right (with this condition).<br> +Only pressing enter on spinbox will set DAC (with this condition). + + + mV + + + + + + + + 0 + 32 + + + + + 16777215 + 32 + + + + Only accepts value range (0 - 4096). Only modifying this or pressing enter will set DAC. + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 4096 + + + + + + + + 0 + 32 + + + + + 16777215 + 32 + + + + Only accepts value range (0 - 4096). Only modifying this or pressing enter will set DAC. + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 4096 + + + + + + + + 0 + 32 + + + + + 16777215 + 32 + + + + Only accepts value range (0 - 4096). Only modifying this or pressing enter will set DAC. + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 4096 + + + + + + + ADC_VPP + + + + + + + false + + + Unchecking will set DAC in tristate (sends -100).<br> +Checking sends nothing to DAC + + + DAC 11 + + + + + + + Checking or unchecking this will only get DAC values on the right (with this condition).<br> +Only pressing enter on spinbox will set DAC (with this condition). + + + mV + + + + + + + Checking or unchecking this will only get DAC values on the right (with this condition).<br> +Only pressing enter on spinbox will set DAC (with this condition). + + + mV + + + + + + + + 0 + 32 + + + + + 16777215 + 32 + + + + Only accepts value range (0 - 4096). Only modifying this or pressing enter will set DAC. + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 4096 + + + + + + + + 0 + 32 + + + + + 16777215 + 32 + + + + Only accepts value range (0 - 4096). Only modifying this or pressing enter will set DAC. + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 4096 + + + + + + + + 0 + 32 + + + + + 16777215 + 32 + + + + Only accepts value range (0 - 4096). Only modifying this or pressing enter will set DAC. + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 4096 + + + + + + + 0 + + + + + + + 0 + + + + + + + + 0 + 32 + + + + + 16777215 + 32 + + + + Only accepts value range (0 - 4096). Only modifying this or pressing enter will set DAC. + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 4096 + + + + + + + Checking or unchecking this will only get DAC values on the right (with this condition).<br> +Only pressing enter on spinbox will set DAC (with this condition). + + + mV + + + + + + + 0 + + + + + + + + 0 + 32 + + + + + 16777215 + 32 + + + + Only enter values between 60-200 + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 200 + + + + + + + false + + + Unchecking will set DAC in tristate (sends -100).<br> +Checking sends nothing to DAC + + + DAC 3 + + + + + + + 0 + + + + + + + + 0 + 32 + + + + + 16777215 + 32 + + + + Only accepts value range (0 - 4096). Only modifying this or pressing enter will set DAC. + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 4096 + + + + + + + Checking or unchecking this will only get DAC values on the right (with this condition).<br> +Only pressing enter on spinbox will set DAC (with this condition). + + + mV + + + + + + + false + + + Unchecking will set DAC in tristate (sends -100).<br> +Checking sends nothing to DAC + + + DAC 10 + + + + + + + 0 + + + + + + + + 0 + 32 + + + + + 16777215 + 32 + + + + Only accepts value range (0 - 4096). Only modifying this or pressing enter will set DAC. + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 4096 + + + + + + + false + + + Unchecking will set DAC in tristate (sends -100).<br> +Checking sends nothing to DAC + + + DAC 4 + + + + + + + + 0 + 32 + + + + + 16777215 + 32 + + + + Only accepts value range (0 - 4096). Only modifying this or pressing enter will set DAC. + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 4096 + + + + + + + Checking or unchecking this will only get DAC values on the right (with this condition).<br> +Only pressing enter on spinbox will set DAC (with this condition). + + + mV + + + + + + + false + + + Unchecking will set DAC in tristate (sends -100).<br> +Checking sends nothing to DAC + + + DAC 12 + + + + + + + 0 + + + + + + + + + diff --git a/pyctbgui/pyctbgui/ui/MainWindow.py b/pyctbgui/pyctbgui/ui/MainWindow.py new file mode 100644 index 000000000..acd07c6f7 --- /dev/null +++ b/pyctbgui/pyctbgui/ui/MainWindow.py @@ -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) + "
" + 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
Move Tab Right : Ctrl + '+'
Move Tab Left :" + " Ctrl + '-'
") + 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) diff --git a/pyctbgui/pyctbgui/ui/__init__.py b/pyctbgui/pyctbgui/ui/__init__.py new file mode 100644 index 000000000..0a3f5ca61 --- /dev/null +++ b/pyctbgui/pyctbgui/ui/__init__.py @@ -0,0 +1 @@ +from .MainWindow import MainWindow \ No newline at end of file diff --git a/pyctbgui/pyctbgui/ui/acquisition.ui b/pyctbgui/pyctbgui/ui/acquisition.ui new file mode 100644 index 000000000..5b9fa58fd --- /dev/null +++ b/pyctbgui/pyctbgui/ui/acquisition.ui @@ -0,0 +1,927 @@ + + + Form + + + + 0 + 0 + 870 + 823 + + + + + 870 + 800 + + + + Form + + + + + 10 + 10 + 841 + 71 + + + + QFrame::StyledPanel + + + QFrame::Sunken + + + + + + + 0 + 0 + + + + + 125 + 31 + + + + + 125 + 31 + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + QAbstractSpinBox::UpDownArrows + + + 1000 + + + 0 + + + + + + + Read Out Mode: + + + + + + + + 0 + 32 + + + + + 16777215 + 32 + + + + + Analog + + + + + Digital + + + + + Analog and Digital + + + + + Transceiver + + + + + Digital and Transceiver + + + + + + + + Run Clock Frequency (MHz): + + + + + + + + + 10 + 90 + 841 + 51 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + 0 + 0 + + + + + 125 + 32 + + + + + 125 + 32 + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 1 + + + 100000 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 200 + 0 + + + + Transceiver Samples: + + + + + + + + + 10 + 150 + 841 + 201 + + + + QFrame::StyledPanel + + + QFrame::Sunken + + + + + + + 200 + 0 + + + + DBIT Clock Frequency (MHz): + + + + + + + + 0 + 0 + + + + + 200 + 0 + + + + ADC Clock Frequency (MHz): + + + + + + + + 0 + 0 + + + + + 125 + 31 + + + + + 125 + 31 + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 9999 + + + + + + + DBIT Pipeline: + + + + + + + + 0 + 0 + + + + + 125 + 31 + + + + + 125 + 31 + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 1000 + + + + + + + + 0 + 0 + + + + + 125 + 31 + + + + + 125 + 31 + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + ADC Pipeline: + + + + + + + ADC Clock Phase (a.u.): + + + + + + + DBIT Clock Phase (a.u.): + + + + + + + Qt::Horizontal + + + QSizePolicy::Expanding + + + + 10 + 20 + + + + + + + + + 0 + 0 + + + + + 125 + 31 + + + + + 125 + 31 + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 1000 + + + + + + + + 0 + 0 + + + + + 125 + 31 + + + + + 125 + 31 + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 0 + 0 + + + + + 125 + 31 + + + + + 125 + 31 + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 9999 + + + + + + + Analog Samples: + + + + + + + + 0 + 0 + + + + + 125 + 32 + + + + + 125 + 32 + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 1 + + + 100000 + + + + + + + Digital Samples: + + + + + + + + 0 + 0 + + + + + 125 + 32 + + + + + 125 + 32 + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 1 + + + 100000 + + + 1 + + + + + + + + + 10 + 370 + 841 + 181 + + + + QFrame::StyledPanel + + + QFrame::Sunken + + + + + + + 11 + + + + QFrame::Sunken + + + 1 + + + Output Settings + + + + + + + File name: + + + + + + + + 0 + 31 + + + + + 16777215 + 31 + + + + background-color: rgb(200, 219, 230); + + + File Name + + + + + + + Index: + + + + + + + + 0 + 31 + + + + + 200 + 31 + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 999999999 + + + + + + + Raw + + + + + + + + 0 + 36 + + + + background-color: rgb(199, 213, 207); + + + Browse + + + + + + + + 0 + 31 + + + + + 16777215 + 31 + + + + background-color: rgb(200, 219, 230); + + + File Path + + + + + + + File path: + + + + + + + Numpy + + + + + + + Save format: + + + + + + + + + 10 + 570 + 841 + 141 + + + + + 0 + 0 + + + + QFrame::StyledPanel + + + QFrame::Sunken + + + + + + Number of frames: + + + + + + + + 0 + 0 + + + + + 120 + 32 + + + + + 16777215 + 32 + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 1 + + + 999999999 + + + 999999999 + + + + + + + + 0 + 0 + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Period (s): + + + + + + + + 0 + 0 + + + + + 120 + 32 + + + + + 150 + 32 + + + + 4 + + + 99999.990000000005239 + + + + + + + + 0 + 31 + + + + + s + + + + + ms + + + + + μs + + + + + ns + + + + + + + + + 0 + 0 + + + + Number of triggers: + + + + + + + + 0 + 0 + + + + + 120 + 32 + + + + + 16777215 + 32 + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 1 + + + 999999999 + + + + + + + Number of measurements: + + + + + + + + 120 + 32 + + + + + 16777215 + 32 + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 1 + + + 999999999 + + + + + + + + + diff --git a/pyctbgui/pyctbgui/ui/adc.ui b/pyctbgui/pyctbgui/ui/adc.ui new file mode 100644 index 000000000..c1fabe266 --- /dev/null +++ b/pyctbgui/pyctbgui/ui/adc.ui @@ -0,0 +1,4212 @@ + + + Form + + + + 0 + 0 + 841 + 470 + + + + + 841 + 461 + + + + Form + + + + + 0 + 10 + 841 + 461 + + + + QFrame::StyledPanel + + + QFrame::Sunken + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + + + + false + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + Plot + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + En + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + Plot + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + + + + false + + + + + + + + 16777215 + 16 + + + + + 10 + + + + Inv + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + ADC17 + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + ADC29 + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + Plot + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + En + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + ADC22 + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + Inv + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + Plot + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + Inv + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + + + + false + + + + + + + + 16777215 + 16 + + + + + 10 + + + + Inv + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + En + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + Plot + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + Inv + + + + + + + + 16777215 + 16 + + + + + 10 + + + + Inv + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + En + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + + + + false + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + Plot + + + + + + + + 16777215 + 16 + + + + + 10 + + + + Inv + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + ADC31 + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + + + + false + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + + + + false + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + ADC30 + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + Inv + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + ADC2 + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + ADC5 + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + Plot + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + Inv + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + Inv + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + ADC26 + + + + + + + + 16777215 + 16 + + + + + 10 + + + + Inv + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + ADC28 + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + ADC18 + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + Plot + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + + + + false + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + + + + false + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + En + + + + + + + + 80 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + ADC 16-31 + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + + + + false + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + En + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + En + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + Plot + + + + + + + + 16777215 + 16 + + + + + 10 + + + + Inv + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + En + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + + + + false + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + Inv + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + Plot + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + En + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + ADC4 + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + Plot + + + + + + + + 80 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + ADC 0-15 + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + Inv + + + + + + + + 16777215 + 16 + + + + + 10 + + + + Inv + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + En + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + Plot + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + En + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + Inv + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + ADC11 + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + ADC21 + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + ADC12 + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + + + + false + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + + + + false + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + Plot + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + Plot + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + ADC16 + + + + + + + + 16777215 + 16 + + + + + 10 + + + + Inv + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + Plot + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + Plot + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + + + + false + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + ADC9 + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + Plot + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + ADC19 + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + ADC3 + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + En + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + En + + + + + + + + 16777215 + 16 + + + + + 10 + + + + Inv + + + + + + + + 16777215 + 16 + + + + + 10 + + + + Inv + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + Plot + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + Plot + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + ADC13 + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + ADC20 + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + Inv + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + En + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + ADC10 + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + Inv + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + Plot + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + Plot + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + + + + false + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + + + + false + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + En + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + ADC6 + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + En + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + En + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + En + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + Plot + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + Inv + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + ADC23 + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + + + + false + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + + + + false + + + + + + + + 16777215 + 16 + + + + + 10 + + + + Inv + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + Plot + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + Inv + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + ADC24 + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + Plot + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + Plot + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + ADC25 + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + ADC1 + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + En + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + Inv + + + + + + + + 16777215 + 16 + + + + + 10 + + + + Inv + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + + + + false + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + ADC7 + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + + + + false + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + Plot + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + + + + false + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + ADC8 + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + Plot + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + En + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + En + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + Plot + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + + + + false + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + + + + false + + + + + + + + 16777215 + 16 + + + + + 10 + + + + Inv + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + En + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + 10 + + + + Inversion mask: + + + + + + + + 150 + 32 + + + + + 150 + 32 + + + + + Monospace + 10 + + + + background-color: rgb(255, 255, 255); + + + 0xFFFFFFFF + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + false + + + + + + + + 10 + + + + Enable mask: + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 150 + 32 + + + + + 150 + 32 + + + + + Monospace + 10 + + + + background-color: rgb(255, 255, 255); + + + 0xFFFFFFFF + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + false + + + + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + Inv + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + + + + false + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + ADC0 + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + En + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + En + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + + + + false + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + En + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + En + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + Plot + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + En + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + Plot + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + Plot + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + + + + false + + + + + + + + 16777215 + 16 + + + + + 10 + + + + Inv + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + En + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + Plot + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + + + + false + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + + + + false + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + Plot + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + Inv + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + ADC14 + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + + + + false + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + En + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + + + + false + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + + + + false + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + + + + false + + + + + + + + 16777215 + 16 + + + + + 10 + + + + Inv + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + En + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + + + + false + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + Inv + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + En + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + En + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + ADC27 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 16777215 + 16 + + + + + 10 + + + + Inv + + + + + + + + 16777215 + 16 + + + + + 10 + + + + Inv + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + En + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + En + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + Plot + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + ADC15 + + + + + + + + + diff --git a/pyctbgui/pyctbgui/ui/pattern.ui b/pyctbgui/pyctbgui/ui/pattern.ui new file mode 100644 index 000000000..0c642a83a --- /dev/null +++ b/pyctbgui/pyctbgui/ui/pattern.ui @@ -0,0 +1,2733 @@ + + + Form + + + + 0 + 0 + 870 + 800 + + + + + 870 + 800 + + + + Form + + + + + 0 + 10 + 471 + 311 + + + + QFrame::StyledPanel + + + QFrame::Sunken + + + + + + + 0 + 0 + + + + + 50 + 16777215 + + + + Loop 3 + + + + + + + + 110 + 31 + + + + + 110 + 31 + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 999999999 + + + 0 + + + + + + + + 80 + 31 + + + + + 80 + 31 + + + + + + + + + 36 + 31 + 49 + + + + + + + + + 36 + 31 + 49 + + + + + + + + + 146 + 149 + 149 + + + + + + + + + Monospace + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + false + + + + + + + + 110 + 31 + + + + + 110 + 31 + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 999999999 + + + + + + + + 80 + 31 + + + + + 80 + 31 + + + + + + + + + 36 + 31 + 49 + + + + + + + + + 36 + 31 + 49 + + + + + + + + + 146 + 149 + 149 + + + + + + + + + Monospace + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + false + + + + + + + + 80 + 31 + + + + + 80 + 31 + + + + + + + + + 36 + 31 + 49 + + + + + + + + + 36 + 31 + 49 + + + + + + + + + 146 + 149 + 149 + + + + + + + + + Monospace + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + false + + + + + + + + 80 + 31 + + + + + 80 + 31 + + + + + + + + + 36 + 31 + 49 + + + + + + + + + 36 + 31 + 49 + + + + + + + + + 146 + 149 + 149 + + + + + + + + + Monospace + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + false + + + + + + + + 80 + 31 + + + + + 80 + 31 + + + + + + + + + 36 + 31 + 49 + + + + + + + + + 36 + 31 + 49 + + + + + + + + + 146 + 149 + 149 + + + + + + + + + Monospace + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + false + + + + + + + + 110 + 31 + + + + + 110 + 31 + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 999999999 + + + + + + + + 0 + 0 + + + + + 50 + 16777215 + + + + Loop 4 + + + + + + + + 110 + 31 + + + + + 110 + 31 + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 999999999 + + + + + + + Stop Address + + + Qt::AlignCenter + + + + + + + + 0 + 0 + + + + + 50 + 16777215 + + + + Loop 5 + + + + + + + + 80 + 31 + + + + + 80 + 31 + + + + + + + + + 36 + 31 + 49 + + + + + + + + + 36 + 31 + 49 + + + + + + + + + 146 + 149 + 149 + + + + + + + + + Monospace + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + false + + + + + + + + 80 + 31 + + + + + 80 + 31 + + + + + + + + + 36 + 31 + 49 + + + + + + + + + 36 + 31 + 49 + + + + + + + + + 146 + 149 + 149 + + + + + + + + + Monospace + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + false + + + + + + + + 0 + 0 + + + + + 50 + 16777215 + + + + Loop 2 + + + + + + + Repetitions + + + Qt::AlignCenter + + + + + + + + 80 + 31 + + + + + 80 + 31 + + + + + + + + + 36 + 31 + 49 + + + + + + + + + 36 + 31 + 49 + + + + + + + + + 146 + 149 + 149 + + + + + + + + + Monospace + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + false + + + + + + + Start Address + + + Qt::AlignCenter + + + + + + + + 80 + 31 + + + + + 80 + 31 + + + + + + + + + 36 + 31 + 49 + + + + + + + + + 36 + 31 + 49 + + + + + + + + + 146 + 149 + 149 + + + + + + + + + Monospace + + + + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + false + + + + + + + + 0 + 0 + + + + + 50 + 16777215 + + + + Loop 1 + + + + + + + + 80 + 31 + + + + + 80 + 31 + + + + + + + + + 36 + 31 + 49 + + + + + + + + + 36 + 31 + 49 + + + + + + + + + 146 + 149 + 149 + + + + + + + + + Monospace + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + false + + + + + + + + 110 + 31 + + + + + 110 + 31 + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 999999999 + + + + + + + + 80 + 31 + + + + + 80 + 31 + + + + + + + + + 36 + 31 + 49 + + + + + + + + + 36 + 31 + 49 + + + + + + + + + 146 + 149 + 149 + + + + + + + + + Monospace + + + + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + false + + + + + + + + 0 + 0 + + + + + 50 + 16777215 + + + + Loop 0 + + + + + + + + 110 + 31 + + + + + 110 + 31 + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 999999999 + + + + + + + + 80 + 31 + + + + + 80 + 31 + + + + + + + + + 36 + 31 + 49 + + + + + + + + + 36 + 31 + 49 + + + + + + + + + 146 + 149 + 149 + + + + + + + + + Monospace + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + false + + + + + + + + 0 + 0 + + + + + 50 + 16777215 + + + + Limits: + + + + + + + + 80 + 31 + + + + + 80 + 31 + + + + + + + + + 36 + 31 + 49 + + + + + + + + + 36 + 31 + 49 + + + + + + + + + 146 + 149 + 149 + + + + + + + + + Monospace + + + + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + false + + + + + + + + 80 + 31 + + + + + 80 + 31 + + + + + + + + + 36 + 31 + 49 + + + + + + + + + 36 + 31 + 49 + + + + + + + + + 146 + 149 + 149 + + + + + + + + + Monospace + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + false + + + + + + + + + 490 + 10 + 361 + 271 + + + + QFrame::StyledPanel + + + QFrame::Sunken + + + + + + + 125 + 31 + + + + + 125 + 31 + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 999999999 + + + + + + + + 125 + 31 + + + + + 125 + 31 + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 999999999 + + + + + + + + 0 + 0 + + + + + 50 + 16777215 + + + + Wait 0 + + + + + + + + 0 + 0 + + + + + 50 + 16777215 + + + + Wait 5 + + + + + + + + 125 + 31 + + + + + 125 + 31 + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 999999999 + + + + + + + + 80 + 31 + + + + + 80 + 31 + + + + + + + + + 36 + 31 + 49 + + + + + + + + + 36 + 31 + 49 + + + + + + + + + 146 + 149 + 149 + + + + + + + + + Monospace + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + false + + + + + + + + 80 + 31 + + + + + 80 + 31 + + + + + + + + + 36 + 31 + 49 + + + + + + + + + 36 + 31 + 49 + + + + + + + + + 146 + 149 + 149 + + + + + + + + + Monospace + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + false + + + + + + + + 0 + 0 + + + + + 50 + 16777215 + + + + Wait 3 + + + + + + + Time + + + Qt::AlignCenter + + + + + + + + 80 + 31 + + + + + 80 + 31 + + + + + + + + + 36 + 31 + 49 + + + + + + + + + 36 + 31 + 49 + + + + + + + + + 146 + 149 + 149 + + + + + + + + + Monospace + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + false + + + + + + + + 125 + 31 + + + + + 125 + 31 + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 999999999 + + + + + + + + 0 + 0 + + + + + 50 + 16777215 + + + + Wait 4 + + + + + + + + 80 + 31 + + + + + 80 + 31 + + + + + + + + + 36 + 31 + 49 + + + + + + + + + 36 + 31 + 49 + + + + + + + + + 146 + 149 + 149 + + + + + + + + + Monospace + + + + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + false + + + + + + + + 0 + 0 + + + + + 50 + 16777215 + + + + Wait 1 + + + + + + + + 80 + 31 + + + + + 80 + 31 + + + + + + + + + 36 + 31 + 49 + + + + + + + + + 36 + 31 + 49 + + + + + + + + + 146 + 149 + 149 + + + + + + + + + Monospace + + + + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + false + + + + + + + Address + + + Qt::AlignCenter + + + + + + + + 125 + 31 + + + + + 125 + 31 + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 999999999 + + + + + + + + 80 + 31 + + + + + 80 + 31 + + + + + + + + + 36 + 31 + 49 + + + + + + + + + 36 + 31 + 49 + + + + + + + + + 146 + 149 + 149 + + + + + + + + + Monospace + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + false + + + + + + + + 125 + 31 + + + + + 125 + 31 + + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + 999999999 + + + + + + + + 0 + 0 + + + + + 50 + 16777215 + + + + Wait 2 + + + + + + + + + 10 + 330 + 841 + 141 + + + + QFrame::StyledPanel + + + QFrame::Sunken + + + + + + + 0 + 36 + + + + + 16777215 + 31 + + + + background-color: rgb(199, 213, 207); + + + Browse + + + + + + + background-color: rgb(200, 219, 230); + + + python + + + Compiler + + + + + + + + 0 + 36 + + + + + 16777215 + 31 + + + + background-color: rgb(199, 213, 207); + + + Browse + + + + + + + Pattern: + + + + + + + background-color: rgb(200, 219, 230); + + + Pattern File + + + + + + + background-color: rgb(200, 219, 230); + + + Uncompiled Pattern File + + + + + + + + 0 + 36 + + + + + 16777215 + 31 + + + + background-color: rgb(199, 213, 207); + + + Browse + + + + + + + Uncompiled Pattern: + + + + + + + Compiler: + + + + + + + + + 10 + 480 + 841 + 211 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + 0 + 0 + + + + + 30 + 16777215 + + + + : + + + + + + + + 100 + 20 + + + + + 9 + + + + Alpha + + + Qt::AlignCenter + + + + + + + + 100 + 20 + + + + + 9 + + + + Alpha rect + + + Qt::AlignCenter + + + + + + + + 80 + 20 + + + + + 9 + + + + Color + + + Qt::AlignCenter + + + + + + + + 100 + 20 + + + + Viewer + + + + + + + + 0 + 31 + + + + + 120 + 32 + + + + Alpha + + + 1.000000000000000 + + + 0.010000000000000 + + + + + + + + 100 + 32 + + + + + 120 + 32 + + + + + Loop 0 + + + + + Loop 1 + + + + + Loop 2 + + + + + Loop 3 + + + + + Loop 4 + + + + + Loop 5 + + + + + + + + + 0 + 0 + + + + + 30 + 16777215 + + + + : + + + + + + + + 0 + 31 + + + + + 120 + 32 + + + + Alpha + + + 1.000000000000000 + + + 0.010000000000000 + + + + + + + + 100 + 32 + + + + + 120 + 32 + + + + + Wait 0 + + + + + Wait 1 + + + + + Wait 2 + + + + + Wait 3 + + + + + Wait 4 + + + + + Wait 5 + + + + + + + + + 70 + 32 + + + + + 120 + 32 + + + + Line Style + + + + + + + + 120 + 32 + + + + Alpha Rect + + + 1.000000000000000 + + + 0.010000000000000 + + + + + + + + 80 + 32 + + + + + 120 + 32 + + + + + + + + + 70 + 32 + + + + + 120 + 32 + + + + Line Style + + + + + + + + 120 + 32 + + + + Alpha Rect + + + 1.000000000000000 + + + 0.010000000000000 + + + + + + + + 70 + 20 + + + + + 9 + + + + Line style + + + Qt::AlignCenter + + + + + + + + 80 + 32 + + + + + 120 + 32 + + + + + + + + + 100 + 32 + + + + + 120 + 32 + + + + + Plot color 1 + + + + + Plot color 2 + + + + + + + + + 80 + 32 + + + + + 120 + 32 + + + + + + + + + + + 100 + 0 + + + + + 100 + 16777215 + + + + Clock spacing: + + + + + + + + 70 + 32 + + + + + 16777215 + 32 + + + + 999 + + + 999 + + + + + + + Qt::Horizontal + + + QSizePolicy::Expanding + + + + 40 + 0 + + + + + + + + Clocks Number + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 70 + 0 + + + + + 70 + 16777215 + + + + Line width + + + + + + + + 0 + 32 + + + + + 120 + 32 + + + + Alpha Rect + + + + + + + + + + + 10 + 720 + 841 + 51 + + + + + + + Qt::Horizontal + + + QSizePolicy::Expanding + + + + 200 + 0 + + + + + + + + Compile + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 15 + 20 + + + + + + + + + 150 + 36 + + + + + 16777215 + 36 + + + + background-color: rgb(199, 213, 207); + + + Load Pattern + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 15 + 20 + + + + + + + + + 150 + 36 + + + + + 16777215 + 36 + + + + background-color: rgb(199, 213, 207); + + + View Pattern + + + + + + + + + diff --git a/pyctbgui/pyctbgui/ui/plot.ui b/pyctbgui/pyctbgui/ui/plot.ui new file mode 100644 index 000000000..b01bc3e71 --- /dev/null +++ b/pyctbgui/pyctbgui/ui/plot.ui @@ -0,0 +1,1055 @@ + + + Form + + + + 0 + 0 + 860 + 800 + + + + + 860 + 800 + + + + Form + + + + + 10 + 50 + 841 + 141 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + true + + + Type: + + + + + + + false + + + Distribution + + + buttonGroup + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + 2 + + + + + + + Digital plot: + + + + + + + Overlay + + + buttonGroup_2 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + show legend + + + true + + + + + + + Stripe + + + true + + + buttonGroup_2 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + + true + + + + 0 + 31 + + + + Image decoder + + + + Matterhorn + + + + + Moench04 + + + + + + + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + true + + + + 120 + 31 + + + + Color map of the image + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 40 + 20 + + + + + + + + Decoder: + + + + + + + Color Map: + + + + + + + + + + + Options: + + + + + + + true + + + No Plot + + + false + + + buttonGroup + + + + + + + true + + + + 0 + 31 + + + + <html><head/><body><p>If set to high readout, zmq HWM is set to 2 and buffer size to 1MB to drop zmq packets to catch up.</p><p>If set to low readout (default), zmq HWM is set to zmq default (1000) and buffer size to os default to not drop any zmq packets.</p></body></html> + + + + Low - drop no zmq packet + + + + + High - drop zmq packets to catch up + + + + + + + + <html><head/><body><p>If set to high readout, zmq HWM is set to 2 and buffer size to 1MB to drop zmq packets to catch up.</p><p>If set to low readout (default), zmq HWM is set to zmq default (1000) and buffer size to os default to not drop any zmq packets.</p></body></html> + + + Readout speed: + + + + + + + true + + + Image + + + buttonGroup + + + + + + + true + + + Waveform + + + true + + + buttonGroup + + + + + + + + + 0 + 480 + 841 + 311 + + + + QFrame::StyledPanel + + + QFrame::Sunken + + + + + + false + + + Fit Panel ADC: + + + + + + + false + + + Max: + + + + + + + false + + + Values + + + + + + + false + + + Dynamic Range: + + + + + + + false + + + Y: + + + + + + + false + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + false + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + false + + + Min: + + + + + + + false + + + X: + + + + + + + false + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + false + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + false + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + false + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + false + + + Image Pixels: + + + + + + + false + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + false + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + false + + + Y + + + + + + + false + + + Min: + + + + + + + false + + + X + + + + + + + false + + + Max: + + + + + + + false + + + Serial offset: + + + + + + + false + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + false + + + Plot Bit: + + + + + + + false + + + Raw Data + + + + + + + + 0 + 31 + + + + background-color: rgb(199, 213, 207); + + + Referesh + + + + + + + false + + + Pedestal Subtract + + + + + + + false + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + false + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + false + + + N Counters: + + + + + + + + + 10 + 219 + 841 + 81 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + 0 + -7 + 841 + 111 + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 40 + 20 + + + + + + + + Color Range: + + + + + + + + + 0 + 0 + 121 + 91 + + + + + + + + 16777215 + 15 + + + + All + + + true + + + buttonGroup_4 + + + + + + + true + + + + 16777215 + 15 + + + + 3-97% + + + buttonGroup_4 + + + + + + + + 16777215 + 15 + + + + Fixed + + + buttonGroup_4 + + + + + + + + + + + + 50 + 16777215 + + + + min: + + + + + + + false + + + -1000.000000000000000 + + + 100000.000000000000000 + + + + + + + + 50 + 16777215 + + + + max: + + + + + + + false + + + 100000.000000000000000 + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 40 + 20 + + + + + + + + + + + 10 + 330 + 841 + 101 + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + 0 + 0 + 841 + 51 + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 40 + 20 + + + + + + + + true + + + Pedestal: + + + + + + + + 250 + 0 + + + + recorded frames: 0 + + + + + + + true + + + Record + + + true + + + false + + + buttonGroup_3 + + + + + + + true + + + Apply + + + true + + + buttonGroup_3 + + + + + + + true + + + + 0 + 31 + + + + background-color: rgb(199, 213, 207); + + + Reset + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 40 + 20 + + + + + + + + + + -1 + 49 + 841 + 51 + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 120 + 31 + + + + background-color: rgb(199, 213, 207); + + + Load Pedestal + + + + + + + + 120 + 31 + + + + background-color: rgb(199, 213, 207); + + + Save Pedestal + + + + + + + Qt::Horizontal + + + QSizePolicy::Preferred + + + + 40 + 20 + + + + + + + + + + + + + + + + + diff --git a/pyctbgui/pyctbgui/ui/powerSupplies.ui b/pyctbgui/pyctbgui/ui/powerSupplies.ui new file mode 100644 index 000000000..d8739957c --- /dev/null +++ b/pyctbgui/pyctbgui/ui/powerSupplies.ui @@ -0,0 +1,483 @@ + + + Form + + + + 0 + 0 + 827 + 375 + + + + Form + + + + + 0 + 0 + 841 + 381 + + + + QFrame::StyledPanel + + + QFrame::Sunken + + + + + + + 0 + 32 + + + + + 150 + 32 + + + + Only accepts value range (636 - 2468) + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + mV + + + 2468 + + + + + + + + 100 + 16777215 + + + + 0 + + + + + + + + 0 + 32 + + + + + 150 + 32 + + + + Only accepts value range (636 - 2468) + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + mV + + + 0 + + + 2468 + + + 0 + + + + + + + + 100 + 16777215 + + + + 0 + + + + + + + true + + + + 0 + 36 + + + + + 150 + 16777215 + + + + QPushButton{background-color: red;} +QPushButton:disabled{background-color: grey;} + + + Power off + + + false + + + + + + + + 100 + 16777215 + + + + 0 + + + + + + + + 100 + 16777215 + + + + 0 + + + + + + + + 100 + 16777215 + + + + VC + + + + + + + + 0 + 32 + + + + + 150 + 32 + + + + Only accepts value range (1200 - 2468) + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + mV + + + 2468 + + + + + + + + 0 + 32 + + + + + 150 + 32 + + + + Only accepts value range (1200 - 2468) + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + mV + + + 2468 + + + + + + + + 100 + 16777215 + + + + VB + + + + + + + + 100 + 16777215 + + + + 0 + + + + + + + + 100 + 16777215 + + + + 0 + + + + + + + + 100 + 16777215 + + + + VA + + + + + + + + 100 + 16777215 + + + + 0 + + + + + + + + 100 + 16777215 + + + + VD + + + + + + + + 100 + 16777215 + + + + VCHIP + + + + + + + + 100 + 16777215 + + + + 0 + + + + + + + + 0 + 32 + + + + + 150 + 32 + + + + Only accepts value range (636 - 2468) + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + mV + + + 2468 + + + + + + + + 100 + 16777215 + + + + VIO + + + + + + + + 100 + 16777215 + + + + 0 + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 80 + 20 + + + + + + + + + 100 + 16777215 + + + + 0 + + + + + + + + 0 + 32 + + + + + 150 + 32 + + + + Only accepts value range (636 - 2468) + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + mV + + + 2468 + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 80 + 20 + + + + + + + + + + diff --git a/pyctbgui/pyctbgui/ui/signals.ui b/pyctbgui/pyctbgui/ui/signals.ui new file mode 100644 index 000000000..231c0b92f --- /dev/null +++ b/pyctbgui/pyctbgui/ui/signals.ui @@ -0,0 +1,6189 @@ + + + Form + + + + 0 + 0 + 831 + 821 + + + + + 831 + 821 + + + + Form + + + + + 0 + 0 + 831 + 821 + + + + + 831 + 821 + + + + QFrame::StyledPanel + + + QFrame::Sunken + + + + + + + 50 + 0 + + + + + 16777215 + 16 + + + + + 10 + + + + BIT 28 + + + + + + + + 16777215 + 16 + + + + + 10 + + + + Out + + + + + + + + 16777215 + 16 + + + + + 9 + + + + DB List + + + + + + + + 16777215 + 16 + + + + + + + false + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Out + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Out + + + + + + + true + + + + 16777215 + 16 + + + + + + + + + + false + + + + + + + + 50 + 0 + + + + + 16777215 + 16 + + + + + 10 + + + + BIT 26 + + + + + + + + 16777215 + 16 + + + + + 10 + + + + Out + + + + + + + + 50 + 0 + + + + + 16777215 + 16 + + + + + 10 + + + + BIT 2 + + + + + + + + 50 + 0 + + + + + 16777215 + 16 + + + + + 10 + + + + BIT 20 + + + + + + + + 0 + 0 + + + + + 16777215 + 16 + + + + + 10 + + + + BIT 23 + + + + + + + + 16777215 + 16 + + + + + 10 + + + + Out + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Out + + + + + + + + 16777215 + 16 + + + + + + + false + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Plot + + + + + + + + 50 + 0 + + + + + 16777215 + 16 + + + + + 10 + + + + BIT 8 + + + + + + + + 16777215 + 16 + + + + + 9 + + + + DB List + + + + + + + + 16777215 + 16 + + + + + 9 + + + + BIT 43 + + + + + + + + 16777215 + 16 + + + + + 10 + + + + Out + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Plot + + + + + + + + 16777215 + 16 + + + + + 9 + + + + DB List + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Plot + + + + + + + + 50 + 0 + + + + + 16777215 + 16 + + + + + 10 + + + + BIT 22 + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Plot + + + + + + + + 16777215 + 16 + + + + + 9 + + + + DB List + + + + + + + + 16777215 + 16 + + + + + 9 + + + + BIT 44 + + + + + + + + 16777215 + 16 + + + + + 10 + + + + Out + + + + + + + + 50 + 0 + + + + + 16777215 + 16 + + + + + 10 + + + + BIT 19 + + + + + + + + 16777215 + 16 + + + + + + + false + + + + + + + + 16777215 + 16 + + + + + 10 + + + + Out + + + + + + + + 16777215 + 16 + + + + + 9 + + + + BIT 60 + + + + + + + + 16777215 + 16 + + + + + 9 + + + + DB List + + + + + + + + 16777215 + 16 + + + + + + + false + + + + + + + + 16777215 + 16 + + + + + 9 + + + + DB List + + + + + + + + 16777215 + 16 + + + + + + + false + + + + + + + + 50 + 0 + + + + + 16777215 + 16 + + + + + 10 + + + + BIT 7 + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Plot + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Out + + + + + + + + 16777215 + 16 + + + + + 9 + + + + DB List + + + + + + + + 16777215 + 16 + + + + + + + false + + + + + + + + 16777215 + 16 + + + + + + + false + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Out + + + + + + + + 16777215 + 16 + + + + + + + false + + + + + + + + 16777215 + 16 + + + + + 10 + + + + Out + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Plot + + + + + + + + 16777215 + 16 + + + + + + + false + + + + + + + + 50 + 0 + + + + + 16777215 + 16 + + + + + 10 + + + + BIT 18 + + + + + + + + 16777215 + 16 + + + + + 9 + + + + DB List + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Plot + + + + + + + + 50 + 0 + + + + + 16777215 + 16 + + + + + 10 + + + + BIT 16 + + + + + + + + 16777215 + 16 + + + + + + + false + + + + + + + + 16777215 + 16 + + + + + 9 + + + + BIT 59 + + + + + + + + 16777215 + 16 + + + + + 9 + + + + DB List + + + + + + + + 16777215 + 16 + + + + + 9 + + + + DB List + + + + + + + + 16777215 + 16 + + + + + 9 + + + + DB List + + + + + + + + 50 + 0 + + + + + 16777215 + 16 + + + + + 10 + + + + BIT 29 + + + + + + + + 16777215 + 16 + + + + + 9 + + + + DB List + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Out + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Plot + + + + + + + + 16777215 + 16 + + + + + 10 + + + + Out + + + + + + + + 16777215 + 16 + + + + + + + false + + + + + + + + 16777215 + 16 + + + + + 9 + + + + DB List + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Out + + + + + + + + 16777215 + 16 + + + + + + + false + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Plot + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Plot + + + + + + + + 16777215 + 16 + + + + + 9 + + + + BIT 41 + + + + + + + + 16777215 + 16 + + + + + + + false + + + + + + + + 16777215 + 16 + + + + + 10 + + + + Out + + + + + + + + 16777215 + 16 + + + + + 9 + + + + DB List + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Plot + + + + + + + + 16777215 + 16 + + + + + + + false + + + + + + + + 50 + 0 + + + + + 16777215 + 16 + + + + + 10 + + + + BIT 4 + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Plot + + + + + + + + 16777215 + 16 + + + + + 9 + + + + DB List + + + + + + + + 16777215 + 16 + + + + + 9 + + + + BIT 58 + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Plot + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Out + + + + + + + + 16777215 + 16 + + + + + 9 + + + + DB List + + + + + + + + 16777215 + 16 + + + + + 9 + + + + DB List + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Out + + + + + + + + 16777215 + 16 + + + + + + + false + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Plot + + + + + + + + 16777215 + 16 + + + + + 9 + + + + DB List + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Plot + + + + + + + + 16777215 + 16 + + + + + 10 + + + + Out + + + + + + + + 50 + 0 + + + + + 16777215 + 16 + + + + + 10 + + + + BIT 9 + + + + + + + + 16777215 + 16 + + + + + 10 + + + + Out + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Plot + + + + + + + + 50 + 0 + + + + + 16777215 + 16 + + + + + 10 + + + + BIT 17 + + + + + + + + 16777215 + 16 + + + + + + + false + + + + + + + + 16777215 + 16 + + + + + + + false + + + + + + + + 16777215 + 16 + + + + + 10 + + + + Out + + + + + + + + 16777215 + 16 + + + + + 9 + + + + DB List + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Plot + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Plot + + + + + + + + 16777215 + 16 + + + + + + + false + + + + + + + + 16777215 + 16 + + + + + + + false + + + + + + + + 50 + 0 + + + + + 16777215 + 16 + + + + + 10 + + + + BIT 6 + + + + + + + + 16777215 + 16 + + + + + 9 + + + + DB List + + + + + + + + 50 + 0 + + + + + 16777215 + 16 + + + + + 10 + + + + BIT 1 + + + + + + + + 16777215 + 16 + + + + + 9 + + + + BIT 35 + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Plot + + + + + + + + 16777215 + 16 + + + + + 9 + + + + DB List + + + + + + + + 16777215 + 16 + + + + + + + false + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Plot + + + + + + + + 16777215 + 16 + + + + + + + false + + + + + + + + 16777215 + 16 + + + + + 9 + + + + DB List + + + + + + + + 16777215 + 16 + + + + + 9 + + + + BIT 51 + + + + + + + + 50 + 0 + + + + + 16777215 + 16 + + + + + 10 + + + + BIT 21 + + + + + + + + 16777215 + 16 + + + + + + + false + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Out + + + + + + + + 16777215 + 16 + + + + + 10 + + + + Out + + + + + + + + 16777215 + 16 + + + + + 9 + + + + DB List + + + + + + + + 16777215 + 16 + + + + + + + false + + + + + + + + 16777215 + 16 + + + + + 10 + + + + Out + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Plot + + + + + + + + 16777215 + 16 + + + + + + + false + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Out + + + + + + + + 16777215 + 16 + + + + + 10 + + + + Out + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Out + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Plot + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Out + + + + + + + + 16777215 + 16 + + + + + + + false + + + + + + + + 16777215 + 16 + + + + + 9 + + + + DB List + + + + + + + + 16777215 + 16 + + + + + 10 + + + + Out + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Plot + + + + + + + + 16777215 + 16 + + + + + + + false + + + + + + + + 16777215 + 16 + + + + + 9 + + + + DB List + + + + + + + + 16777215 + 16 + + + + + 9 + + + + DB List + + + + + + + + 16777215 + 16 + + + + + 9 + + + + DB List + + + + + + + + 16777215 + 16 + + + + + 9 + + + + DB List + + + + + + + + 16777215 + 16 + + + + + 9 + + + + DB List + + + + + + + + 16777215 + 16 + + + + + 10 + + + + Out + + + + + + + + 50 + 0 + + + + + 16777215 + 16 + + + + + 10 + + + + BIT 13 + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Out + + + + + + + + 50 + 0 + + + + + 16777215 + 16 + + + + + 10 + + + + BIT 0 + + + + + + + + 16777215 + 16 + + + + + 9 + + + + DB List + + + + + + + + 16777215 + 16 + + + + + + + false + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Plot + + + + + + + + 16777215 + 16 + + + + + 10 + + + + Out + + + + + + + + 16777215 + 16 + + + + + 9 + + + + DB List + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Plot + + + + + + + + 16777215 + 16 + + + + + 9 + + + + BIT 47 + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Plot + + + + + + + + 16777215 + 16 + + + + + + + false + + + + + + + + 16777215 + 16 + + + + + + + false + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Plot + + + + + + + + 16777215 + 16 + + + + + 10 + + + + Out + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Plot + + + + + + + + 16777215 + 16 + + + + + + + false + + + + + + + + 50 + 0 + + + + + 16777215 + 16 + + + + + 10 + + + + BIT 24 + + + + + + + + 16777215 + 16 + + + + + 9 + + + + DB List + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Plot + + + + + + + + 16777215 + 16 + + + + + 9 + + + + DB List + + + + + + + + 16777215 + 16 + + + + + 10 + + + + Out + + + + + + + + 16777215 + 16 + + + + + 9 + + + + BIT 57 + + + + + + + + 16777215 + 16 + + + + + 10 + + + + Out + + + + + + + + 16777215 + 16 + + + + + 9 + + + + DB List + + + + + + + + 16777215 + 16 + + + + + + + false + + + + + + + + 16777215 + 16 + + + + + + + false + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Plot + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Out + + + + + + + + 16777215 + 16 + + + + + 10 + + + + Out + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Plot + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Plot + + + + + + + + 16777215 + 16 + + + + + 9 + + + + BIT 63 + + + + + + + + 16777215 + 16 + + + + + 10 + + + + Out + + + + + + + + 16777215 + 16 + + + + + 9 + + + + DB List + + + + + + + + 16777215 + 16 + + + + + 9 + + + + DB List + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Out + + + + + + + + 16777215 + 16 + + + + + 10 + + + + Out + + + + + + + + 16777215 + 16 + + + + + 9 + + + + DB List + + + + + + + + 16777215 + 16 + + + + + 9 + + + + DB List + + + + + + + + 16777215 + 16 + + + + + 9 + + + + DB List + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Plot + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Out + + + + + + + + 16777215 + 16 + + + + + + + false + + + + + + + + 16777215 + 16 + + + + + 9 + + + + DB List + + + + + + + + 16777215 + 16 + + + + + 10 + + + + Out + + + + + + + + 16777215 + 16 + + + + + 9 + + + + DB List + + + + + + + + 80 + 0 + + + + + 16777215 + 16 + + + + + 9 + + + + BIT 32-63 + + + + + + + + 16777215 + 16 + + + + + + + false + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Plot + + + + + + + true + + + + 16777215 + 16 + + + + + 9 + + + + Plot + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Out + + + + + + + + 16777215 + 16 + + + + + 9 + + + + BIT 36 + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Plot + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Plot + + + + + + + + 16777215 + 16 + + + + + + + false + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Plot + + + + + + + + 16777215 + 16 + + + + + + + false + + + + + + + + 16777215 + 16 + + + + + 9 + + + + DB List + + + + + + + + 16777215 + 16 + + + + + 9 + + + + BIT 48 + + + + + + + + 16777215 + 16 + + + + + 9 + + + + DB List + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Out + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Out + + + + + + + + 50 + 0 + + + + + 16777215 + 16 + + + + + 10 + + + + BIT 3 + + + + + + + + 16777215 + 16 + + + + + 9 + + + + BIT 37 + + + + + + + + 50 + 0 + + + + + 16777215 + 16 + + + + + 10 + + + + BIT 5 + + + + + + + + 16777215 + 16 + + + + + + + false + + + + + + + + 16777215 + 16 + + + + + 9 + + + + BIT 34 + + + + + + + + 16777215 + 16 + + + + + 9 + + + + BIT 46 + + + + + + + + 50 + 0 + + + + + 16777215 + 16 + + + + + 10 + + + + BIT3 1 + + + + + + + + 16777215 + 16 + + + + + 10 + + + + Out + + + + + + + + 16777215 + 16 + + + + + + + false + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Plot + + + + + + + + 16777215 + 16 + + + + + + + false + + + + + + + + 16777215 + 16 + + + + + 9 + + + + BIT 32 + + + + + + + + 16777215 + 16 + + + + + 9 + + + + DB List + + + + + + + + 16777215 + 16 + + + + + 9 + + + + DB List + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Plot + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Plot + + + + + + + + 16777215 + 16 + + + + + 9 + + + + DB List + + + + + + + + 16777215 + 16 + + + + + + + false + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Plot + + + + + + + + 16777215 + 16 + + + + + 9 + + + + BIT 50 + + + + + + + + 16777215 + 16 + + + + + 10 + + + + Out + + + + + + + + 16777215 + 16 + + + + + 9 + + + + DB List + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Plot + + + + + + + + 16777215 + 16 + + + + + 9 + + + + DB List + + + + + + + + 16777215 + 16 + + + + + 9 + + + + DB List + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Plot + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Plot + + + + + + + + 16777215 + 16 + + + + + + + false + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Plot + + + + + + + + 50 + 0 + + + + + 16777215 + 16 + + + + + 10 + + + + BIT 14 + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Plot + + + + + + + + 16777215 + 16 + + + + + 9 + + + + BIT 40 + + + + + + + + 16777215 + 16 + + + + + + + false + + + + + + + + 16777215 + 16 + + + + + 9 + + + + DB List + + + + + + + + 16777215 + 16 + + + + + + + false + + + + + + + true + + + + 16777215 + 16 + + + + + 9 + + + + Plot + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Out + + + + + + + + 16777215 + 16 + + + + + + + false + + + + + + + + 16777215 + 16 + + + + + 9 + + + + DB List + + + + + + + + 16777215 + 16 + + + + + 9 + + + + DB List + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Plot + + + + + + + + 16777215 + 16 + + + + + 10 + + + + Out + + + + + + + + 16777215 + 16 + + + + + 9 + + + + BIT 42 + + + + + + + + 50 + 0 + + + + + 16777215 + 16 + + + + + 10 + + + + BIT 25 + + + + + + + + 16777215 + 16 + + + + + 9 + + + + BIT 39 + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Out + + + + + + + + 0 + 0 + + + + + 16777215 + 16 + + + + + 9 + + + + BIT 55 + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Out + + + + + + + + 50 + 0 + + + + + 16777215 + 16 + + + + + 10 + + + + BIT 10 + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Plot + + + + + + + + 16777215 + 16 + + + + + + + false + + + + + + + + 16777215 + 16 + + + + + + + false + + + + + + + + 16777215 + 16 + + + + + 9 + + + + DB List + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Out + + + + + + + + 16777215 + 16 + + + + + + + false + + + + + + + + 16777215 + 16 + + + + + + + false + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Plot + + + + + + + + 16777215 + 16 + + + + + 9 + + + + BIT 53 + + + + + + + + 16777215 + 16 + + + + + + + false + + + + + + + + 16777215 + 16 + + + + + 9 + + + + DB List + + + + + + + + 16777215 + 16 + + + + + 9 + + + + DB List + + + + + + + + 16777215 + 16 + + + + + 9 + + + + BIT 49 + + + + + + + + 16777215 + 16 + + + + + 9 + + + + DB List + + + + + + + + 16777215 + 16 + + + + + + + false + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Out + + + + + + + + 50 + 0 + + + + + 16777215 + 16 + + + + + 10 + + + + BIT 30 + + + + + + + + 16777215 + 16 + + + + + + + false + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Out + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Plot + + + + + + + + 16777215 + 16 + + + + + 9 + + + + DB List + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Plot + + + + + + + + 16777215 + 16 + + + + + 9 + + + + BIT 52 + + + + + + + + 16777215 + 16 + + + + + 9 + + + + BIT 62 + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Plot + + + + + + + + 16777215 + 16 + + + + + + + false + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Plot + + + + + + + + 16777215 + 16 + + + + + 10 + + + + Out + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Plot + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Plot + + + + + + + + 50 + 0 + + + + + 16777215 + 16 + + + + + 10 + + + + BIT 27 + + + + + + + + 16777215 + 16 + + + + + + + false + + + + + + + + 16777215 + 16 + + + + + 10 + + + + Out + + + + + + + + 16777215 + 16 + + + + + 9 + + + + DB List + + + + + + + + 16777215 + 16 + + + + + + + false + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Plot + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Plot + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Plot + + + + + + + + 16777215 + 16 + + + + + + + false + + + + + + + + 16777215 + 16 + + + + + 9 + + + + DB List + + + + + + + + 16777215 + 16 + + + + + 9 + + + + DB List + + + + + + + + 16777215 + 16 + + + + + 10 + + + + Out + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Out + + + + + + + + 80 + 0 + + + + + 16777215 + 16 + + + + + 10 + + + + BIT 0-31 + + + + + + + + 16777215 + 16 + + + + + 9 + + + + BIT 56 + + + + + + + + 16777215 + 16 + + + + + + + false + + + + + + + + 16777215 + 16 + + + + + 9 + + + + DB List + + + + + + + + 16777215 + 16 + + + + + + + false + + + + + + + + 16777215 + 16 + + + + + 9 + + + + DB List + + + + + + + + 50 + 0 + + + + + 16777215 + 16 + + + + + 10 + + + + BIT 11 + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Out + + + + + + + + 16777215 + 16 + + + + + 9 + + + + DB List + + + + + + + + 16777215 + 16 + + + + + + + false + + + + + + + + 16777215 + 16 + + + + + + + false + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Plot + + + + + + + + 16777215 + 16 + + + + + 10 + + + + Out + + + + + + + + 16777215 + 16 + + + + + 9 + + + + DB List + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Plot + + + + + + + + 16777215 + 16 + + + + + 9 + + + + BIT 61 + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Out + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Out + + + + + + + + 16777215 + 16 + + + + + + + false + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Out + + + + + + + + 16777215 + 16 + + + + + 10 + + + + Out + + + + + + + + 50 + 0 + + + + + 16777215 + 16 + + + + + 10 + + + + BIT 15 + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Plot + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Out + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Plot + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Plot + + + + + + + + 16777215 + 16 + + + + + + + false + + + + + + + + 16777215 + 16 + + + + + + + false + + + + + + + + 50 + 0 + + + + + 16777215 + 16 + + + + + 10 + + + + BIT 12 + + + + + + + + 16777215 + 16 + + + + + 9 + + + + BIT 38 + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Plot + + + + + + + + 16777215 + 16 + + + + + 9 + + + + BIT 54 + + + + + + + + 16777215 + 16 + + + + + 9 + + + + BIT 45 + + + + + + + + 16777215 + 16 + + + + + + + false + + + + + + + + 16777215 + 16 + + + + + 9 + + + + DB List + + + + + + + + 16777215 + 16 + + + + + 9 + + + + Out + + + + + + + + 16777215 + 16 + + + + + 9 + + + + DB List + + + + + + + + 16777215 + 16 + + + + + 9 + + + + BIT 33 + + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + 10 + + + + DBit Offset: + + + + + + + + 0 + 0 + + + + + 200 + 32 + + + + + 200 + 32 + + + + + Monospace + 10 + + + + 0xFFFFFFFFFFFFFFFF + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 150 + 32 + + + + + 150 + 32 + + + + + 10 + + + + background-color: rgb(255, 255, 255); + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 50 + 0 + + + + + 10 + + + + IO Control Register: + + + + + + + + + + + + diff --git a/pyctbgui/pyctbgui/ui/slowAdcs.ui b/pyctbgui/pyctbgui/ui/slowAdcs.ui new file mode 100644 index 000000000..546a30e53 --- /dev/null +++ b/pyctbgui/pyctbgui/ui/slowAdcs.ui @@ -0,0 +1,472 @@ + + + Form + + + + 0 + 0 + 841 + 571 + + + + + 841 + 571 + + + + Form + + + + + 0 + 0 + 841 + 571 + + + + QFrame::StyledPanel + + + QFrame::Sunken + + + + + + SENSE 0: + + + + + + + *** + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 150 + 36 + + + + + 16777215 + 36 + + + + + Cantarell + + + + background-color: rgb(199, 213, 207); + + + Update + + + + ../../../../.designer../../../../.designer + + + false + + + + + + + *** + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + *** + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 150 + 36 + + + + + 16777215 + 36 + + + + background-color: rgb(199, 213, 207); + + + Update + + + false + + + + + + + SENSE 4: + + + + + + + *** + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 150 + 36 + + + + + 16777215 + 36 + + + + background-color: rgb(199, 213, 207); + + + Update + + + false + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + SENSE 5: + + + + + + + *** + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 150 + 36 + + + + + 16777215 + 36 + + + + background-color: rgb(199, 213, 207); + + + Update + + + false + + + + + + + SENSE 6: + + + + + + + *** + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + SENSE 1: + + + + + + + + 150 + 36 + + + + + 16777215 + 36 + + + + background-color: rgb(199, 213, 207); + + + Update + + + false + + + + + + + SENSE 2: + + + + + + + *** + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + *** + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 150 + 36 + + + + + 16777215 + 36 + + + + background-color: rgb(199, 213, 207); + + + Update + + + false + + + + + + + SENSE 3: + + + + + + + + 150 + 36 + + + + + 16777215 + 36 + + + + background-color: rgb(199, 213, 207); + + + Update + + + false + + + + + + + SENSE 7: + + + + + + + *** + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + + + + 150 + 36 + + + + + 16777215 + 36 + + + + background-color: rgb(199, 213, 207); + + + Update + + + false + + + + + + + Temperature + + + + + + + + 150 + 36 + + + + + 16777215 + 36 + + + + background-color: rgb(199, 213, 207); + + + Update + + + false + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 40 + 20 + + + + + + + + + + diff --git a/pyctbgui/pyctbgui/ui/transceiver.ui b/pyctbgui/pyctbgui/ui/transceiver.ui new file mode 100644 index 000000000..7d1548028 --- /dev/null +++ b/pyctbgui/pyctbgui/ui/transceiver.ui @@ -0,0 +1,542 @@ + + + Form + + + + 0 + 0 + 841 + 239 + + + + + 841 + 181 + + + + Form + + + + + 10 + 20 + 841 + 181 + + + + + 841 + 181 + + + + QFrame::StyledPanel + + + QFrame::Sunken + + + + + + QFrame::StyledPanel + + + QFrame::Raised + + + + + + + 150 + 32 + + + + + 150 + 32 + + + + + Monospace + 10 + + + + background-color: rgb(255, 255, 255); + + + 0xFFFF + + + Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + false + + + + + + + + 10 + + + + Enable mask: + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + Plot + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + Plot + + + + + + + + 80 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + Transceiver 0 + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + En + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + Transceiver 2 + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + + + + false + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + En + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + En + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + Transceiver 1 + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + Plot + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + Transceiver 3 + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + Plot + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + + + + false + + + + + + + Qt::Horizontal + + + + 40 + 20 + + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + En + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + + + + false + + + + + + + + 0 + 16 + + + + + 16777215 + 16 + + + + + 10 + + + + + + + false + + + + + + + + + diff --git a/pyctbgui/pyctbgui/utils/__init__.py b/pyctbgui/pyctbgui/utils/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/pyctbgui/pyctbgui/utils/alias_utility.py b/pyctbgui/pyctbgui/utils/alias_utility.py new file mode 100644 index 000000000..af5cbbe36 --- /dev/null +++ b/pyctbgui/pyctbgui/utils/alias_utility.py @@ -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.

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.") diff --git a/pyctbgui/pyctbgui/utils/bit_utils.py b/pyctbgui/pyctbgui/utils/bit_utils.py new file mode 100644 index 000000000..335c9d3e9 --- /dev/null +++ b/pyctbgui/pyctbgui/utils/bit_utils.py @@ -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) diff --git a/pyctbgui/pyctbgui/utils/decoder.py b/pyctbgui/pyctbgui/utils/decoder.py new file mode 100644 index 000000000..6197f811c --- /dev/null +++ b/pyctbgui/pyctbgui/utils/decoder.py @@ -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 diff --git a/pyctbgui/pyctbgui/utils/defines.py b/pyctbgui/pyctbgui/utils/defines.py new file mode 100644 index 000000000..51c6ac1cb --- /dev/null +++ b/pyctbgui/pyctbgui/utils/defines.py @@ -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 diff --git a/pyctbgui/pyctbgui/utils/numpyWriter/__init__.py b/pyctbgui/pyctbgui/utils/numpyWriter/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/pyctbgui/pyctbgui/utils/numpyWriter/npy_writer.py b/pyctbgui/pyctbgui/utils/numpyWriter/npy_writer.py new file mode 100644 index 000000000..7eea8ec67 --- /dev/null +++ b/pyctbgui/pyctbgui/utils/numpyWriter/npy_writer.py @@ -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() diff --git a/pyctbgui/pyctbgui/utils/numpyWriter/npz_writer.py b/pyctbgui/pyctbgui/utils/numpyWriter/npz_writer.py new file mode 100644 index 000000000..4f0cf881d --- /dev/null +++ b/pyctbgui/pyctbgui/utils/numpyWriter/npz_writer.py @@ -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() diff --git a/pyctbgui/pyctbgui/utils/numpyWriter/usage.md b/pyctbgui/pyctbgui/utils/numpyWriter/usage.md new file mode 100644 index 000000000..b47bb742c --- /dev/null +++ b/pyctbgui/pyctbgui/utils/numpyWriter/usage.md @@ -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] +``` \ No newline at end of file diff --git a/pyctbgui/pyctbgui/utils/pixelmap.py b/pyctbgui/pyctbgui/utils/pixelmap.py new file mode 100644 index 000000000..6cfa28a14 --- /dev/null +++ b/pyctbgui/pyctbgui/utils/pixelmap.py @@ -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 diff --git a/pyctbgui/pyctbgui/utils/plotPattern.py b/pyctbgui/pyctbgui/utils/plotPattern.py new file mode 100755 index 000000000..443b766e9 --- /dev/null +++ b/pyctbgui/pyctbgui/utils/plotPattern.py @@ -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 diff --git a/pyctbgui/pyctbgui/utils/recordOrApplyPedestal.py b/pyctbgui/pyctbgui/utils/recordOrApplyPedestal.py new file mode 100644 index 000000000..235e76d22 --- /dev/null +++ b/pyctbgui/pyctbgui/utils/recordOrApplyPedestal.py @@ -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 diff --git a/pyctbgui/pyproject.toml b/pyctbgui/pyproject.toml new file mode 100644 index 000000000..08de6be1c --- /dev/null +++ b/pyctbgui/pyproject.toml @@ -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/*" +] diff --git a/pyctbgui/setup.py b/pyctbgui/setup.py new file mode 100644 index 000000000..1bb1e3848 --- /dev/null +++ b/pyctbgui/setup.py @@ -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', + ], + }) diff --git a/pyctbgui/src/decoder.c b/pyctbgui/src/decoder.c new file mode 100644 index 000000000..67cb0c4a2 --- /dev/null +++ b/pyctbgui/src/decoder.c @@ -0,0 +1,179 @@ +#define NPY_NO_DEPRECATED_API NPY_1_7_API_VERSION +#define PY_SSIZE_T_CLEAN +#include +#include + +#include +#include + +#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; +} diff --git a/pyctbgui/src/pm_decode.c b/pyctbgui/src/pm_decode.c new file mode 100644 index 000000000..99cbcfc01 --- /dev/null +++ b/pyctbgui/src/pm_decode.c @@ -0,0 +1,17 @@ +#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 +#include +//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); \ No newline at end of file diff --git a/pyctbgui/src/thread_utils.h b/pyctbgui/src/thread_utils.h new file mode 100644 index 000000000..bd8f283ef --- /dev/null +++ b/pyctbgui/src/thread_utils.h @@ -0,0 +1,10 @@ +#pragma once +#include +#include +typedef struct{ + uint16_t* src; + uint16_t* dst; + uint32_t* pm; + size_t n_frames; + size_t n_pixels; +}thread_args; \ No newline at end of file diff --git a/pyctbgui/tests/gui/__init__.py b/pyctbgui/tests/gui/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/pyctbgui/tests/gui/conftest.py b/pyctbgui/tests/gui/conftest.py new file mode 100644 index 000000000..e60342ab7 --- /dev/null +++ b/pyctbgui/tests/gui/conftest.py @@ -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() diff --git a/pyctbgui/tests/gui/data/matterhorm_image_transceiver.npy b/pyctbgui/tests/gui/data/matterhorm_image_transceiver.npy new file mode 100644 index 000000000..37ccc6c2d Binary files /dev/null and b/pyctbgui/tests/gui/data/matterhorm_image_transceiver.npy differ diff --git a/pyctbgui/tests/gui/data/matterhorn_waveform_transceiver1and2.npz b/pyctbgui/tests/gui/data/matterhorn_waveform_transceiver1and2.npz new file mode 100644 index 000000000..942fbf129 Binary files /dev/null and b/pyctbgui/tests/gui/data/matterhorn_waveform_transceiver1and2.npz differ diff --git a/pyctbgui/tests/gui/data/moench04_image_analog.npy b/pyctbgui/tests/gui/data/moench04_image_analog.npy new file mode 100644 index 000000000..791e6e3da Binary files /dev/null and b/pyctbgui/tests/gui/data/moench04_image_analog.npy differ diff --git a/pyctbgui/tests/gui/data/moench04_waveform_adc.npz b/pyctbgui/tests/gui/data/moench04_waveform_adc.npz new file mode 100644 index 000000000..8f94f2783 Binary files /dev/null and b/pyctbgui/tests/gui/data/moench04_waveform_adc.npz differ diff --git a/pyctbgui/tests/gui/data/pattern.pat b/pyctbgui/tests/gui/data/pattern.pat new file mode 100644 index 000000000..20ba27158 --- /dev/null +++ b/pyctbgui/tests/gui/data/pattern.pat @@ -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 diff --git a/pyctbgui/tests/gui/data/pattern.png b/pyctbgui/tests/gui/data/pattern.png new file mode 100644 index 000000000..1847bb5a4 Binary files /dev/null and b/pyctbgui/tests/gui/data/pattern.png differ diff --git a/pyctbgui/tests/gui/data/simulator.config b/pyctbgui/tests/gui/data/simulator.config new file mode 100644 index 000000000..bbc5d8475 --- /dev/null +++ b/pyctbgui/tests/gui/data/simulator.config @@ -0,0 +1,9 @@ +hostname localhost +rx_hostname localhost +udp_dstip auto +udp_srcip auto + +romode analog +asamples 5000 +tsamples 288 + diff --git a/pyctbgui/tests/gui/test_analog_moench.py b/pyctbgui/tests/gui/test_analog_moench.py new file mode 100644 index 000000000..faca2efe1 --- /dev/null +++ b/pyctbgui/tests/gui/test_analog_moench.py @@ -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]) diff --git a/pyctbgui/tests/gui/test_pattern.py b/pyctbgui/tests/gui/test_pattern.py new file mode 100644 index 000000000..688a2fc61 --- /dev/null +++ b/pyctbgui/tests/gui/test_pattern.py @@ -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") diff --git a/pyctbgui/tests/gui/test_pedestal_matterhorn.py b/pyctbgui/tests/gui/test_pedestal_matterhorn.py new file mode 100644 index 000000000..0ed6d3ae1 --- /dev/null +++ b/pyctbgui/tests/gui/test_pedestal_matterhorn.py @@ -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))) diff --git a/pyctbgui/tests/gui/test_signal_matterhorn.py b/pyctbgui/tests/gui/test_signal_matterhorn.py new file mode 100644 index 000000000..b3daebb2c --- /dev/null +++ b/pyctbgui/tests/gui/test_signal_matterhorn.py @@ -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) +# diff --git a/pyctbgui/tests/gui/test_transceiver_matterhorn.py b/pyctbgui/tests/gui/test_transceiver_matterhorn.py new file mode 100644 index 000000000..20f72be44 --- /dev/null +++ b/pyctbgui/tests/gui/test_transceiver_matterhorn.py @@ -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']) diff --git a/pyctbgui/tests/gui/utils.py b/pyctbgui/tests/gui/utils.py new file mode 100644 index 000000000..25264e88a --- /dev/null +++ b/pyctbgui/tests/gui/utils.py @@ -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)) diff --git a/pyctbgui/tests/unit/data/moench04_start_trigger.alias b/pyctbgui/tests/unit/data/moench04_start_trigger.alias new file mode 100755 index 000000000..ca85551f9 --- /dev/null +++ b/pyctbgui/tests/unit/data/moench04_start_trigger.alias @@ -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 diff --git a/pyctbgui/tests/unit/test_alias_file.py b/pyctbgui/tests/unit/test_alias_file.py new file mode 100644 index 000000000..a318d0885 --- /dev/null +++ b/pyctbgui/tests/unit/test_alias_file.py @@ -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']) diff --git a/pyctbgui/tests/unit/test_bit_utils.py b/pyctbgui/tests/unit/test_bit_utils.py new file mode 100644 index 000000000..c04e7c642 --- /dev/null +++ b/pyctbgui/tests/unit/test_bit_utils.py @@ -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 diff --git a/pyctbgui/tests/unit/test_decoder.py b/pyctbgui/tests/unit/test_decoder.py new file mode 100644 index 000000000..21c8b69bf --- /dev/null +++ b/pyctbgui/tests/unit/test_decoder.py @@ -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() diff --git a/pyctbgui/tests/unit/test_npy_writer.py b/pyctbgui/tests/unit/test_npy_writer.py new file mode 100644 index 000000000..5d7928fd3 --- /dev/null +++ b/pyctbgui/tests/unit/test_npy_writer.py @@ -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') diff --git a/pyctbgui/tests/unit/test_npz_writer.py b/pyctbgui/tests/unit/test_npz_writer.py new file mode 100644 index 000000000..e1d0fb48e --- /dev/null +++ b/pyctbgui/tests/unit/test_npz_writer.py @@ -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']