From 1abf12926ef8d211b7ddb8b33f61039959949aa7 Mon Sep 17 00:00:00 2001 From: Maps Date: Fri, 29 Mar 2024 19:29:05 +0100 Subject: [PATCH] cleaned up and commited for push/backup --- .gitignore | 10 +- analysis/mbs/CMakeLists.txt | 42 + analysis/mbs/dabc/plugins/hadaq/hldprint.cxx | 152 -- analysis/mbs/main.cxx | 511 +++++ analysis/rawreader/mimosis.h | 3 +- analysis/scurve/fpn.py | 27 - analysis/scurve/libtrbnet.a | Bin 125464 -> 0 bytes analysis/scurve/scurvemap.gp | 8 - analysis/scurve/start.sh | 22 - analysis/scurve/xy.py | 12 - analysis/scurve/xy.txt | 1803 ------------------ dabc/EventBuilder.xml | 1 + scripts/Mimosis.pm | 222 ++- scripts/cli/mimosis | 99 +- scripts/{pulse/curves => legacy/curves.py} | 0 scripts/{pulse/fpn => legacy/fpn.py} | 0 scripts/pulse/fit-raw.py | 74 + scripts/pulse/plot-raw.py | 20 + scripts/pulse/plot-root.py | 83 + scripts/pulse/requirements.txt | 22 + scripts/{ => qa}/DACscan.py | 0 scripts/test-mask.sh | 30 - trbnet/start.sh | 2 - 23 files changed, 1029 insertions(+), 2114 deletions(-) create mode 100644 analysis/mbs/CMakeLists.txt delete mode 100644 analysis/mbs/dabc/plugins/hadaq/hldprint.cxx create mode 100644 analysis/mbs/main.cxx delete mode 100755 analysis/scurve/fpn.py delete mode 100644 analysis/scurve/libtrbnet.a delete mode 100644 analysis/scurve/scurvemap.gp delete mode 100755 analysis/scurve/start.sh delete mode 100644 analysis/scurve/xy.py delete mode 100644 analysis/scurve/xy.txt rename scripts/{pulse/curves => legacy/curves.py} (100%) rename scripts/{pulse/fpn => legacy/fpn.py} (100%) create mode 100644 scripts/pulse/fit-raw.py create mode 100755 scripts/pulse/plot-raw.py create mode 100755 scripts/pulse/plot-root.py create mode 100644 scripts/pulse/requirements.txt rename scripts/{ => qa}/DACscan.py (100%) delete mode 100755 scripts/test-mask.sh diff --git a/.gitignore b/.gitignore index 3f96d35..e42618c 100644 --- a/.gitignore +++ b/.gitignore @@ -6,8 +6,8 @@ *aux *out *log +*.csv scratch -git data/ img/ *.png @@ -16,13 +16,15 @@ scripts/dac_scan/*.csv *.d *.so *.pcm -hld +*.hld *.hotstart *.kate-swp *GTAGS +git/ +build/ *GRTAGS *GPATH *.chat.swp -*.csv *STATUS -analysis/mbs/dabc* +.venv +WORKDIR* diff --git a/analysis/mbs/CMakeLists.txt b/analysis/mbs/CMakeLists.txt new file mode 100644 index 0000000..8ce1275 --- /dev/null +++ b/analysis/mbs/CMakeLists.txt @@ -0,0 +1,42 @@ +cmake_minimum_required(VERSION 3.9 FATAL_ERROR) + +project(mimosis-scurves + LANGUAGES C CXX +) + +add_executable(mimosis-scurves main.cxx) + +if(TRBNETTOOLS_DIR) + message(${TRBNETTOOLS_DIR}) +else() + message("TRBNETTOOLS_DIR not provided. Using /d/jspc85/bgutsche/trbnettools") + set(TRBNETTOOLS_DIR "/d/jspc85/bgutsche/trbnettools") +endif() +set(TRBNET_LIB_DIR ${TRBNETTOOLS_DIR}/libtrbnet/) +set(TRBNET_INCLUDE_DIR ${TRBNETTOOLS_DIR}/libtrbnet/) + +if(DABC_DIR) + message(${DABC_DIR}) +else() + message("DABC_DIR not provided. Using /d/jspc37/soft/trb3/dabc") + set(DABC_DIR "/d/jspc37/soft/trb3/dabc") +endif() +set(DABC_LIB_DIR ${DABC_DIR}/lib/) +set(DABC_INCLUDE_DIR ${DABC_DIR}/include/) + +include_directories( + ${TRBNET_INCLUDE_DIR} + ${DABC_INCLUDE_DIR} +) + +link_directories( + ${TRBNET_LIB_DIR} + ${DABC_LIB_DIR} +) + +target_link_libraries(mimosis-scurves + PRIVATE trbnet + PRIVATE DabcBase + PRIVATE DabcHadaq + PRIVATE DabcMbs +) diff --git a/analysis/mbs/dabc/plugins/hadaq/hldprint.cxx b/analysis/mbs/dabc/plugins/hadaq/hldprint.cxx deleted file mode 100644 index ef6b4fd..0000000 --- a/analysis/mbs/dabc/plugins/hadaq/hldprint.cxx +++ /dev/null @@ -1,152 +0,0 @@ -#include -#include -#include -#include -#include -#include "hadaq/api.h" - - -void await_params() { - std::string pipeName = "/tmp/scurveipipe"; - FILE *iPipe = fopen(pipeName.c_str(), "r"); - - int buf; - std::string msg; - bool foundFrame = false; - - if(iPipe == nullptr) { - std::printf("ERROR: Couldn't open file.\n"); - std::exit(-1); - } - - buf = fgetc(iPipe); - while(!foundFrame && buf != EOF) { - char c = static_cast(buf); - msg += c; - auto startPos = msg.find("START"); - auto endPos = msg.find("END"); - if(startPos != std::string::npos && endPos != std::string::npos) { - foundFrame = true; - break; - } - buf = fgetc(iPipe); - } - std::cout << msg << '\n'; - fclose(iPipe); -} - - -int send_ack() { - std::string pipeName = "/tmp/scurveapipe"; - FILE *iPipe = fopen(pipeName.c_str(), "w"); - - if(iPipe == nullptr) { - std::printf("ERROR: Couldn't open file.\n"); - std::exit(-1); - } - - std::string msg("ACK"); - fputs(msg.c_str(),iPipe); - fclose(iPipe); - return 0; -} - - -void fit(uint16_t vcasn) -{ - auto exec = [=]() - { - // std::ofstream fs; - // fs.open("params.csv"); - - // decltype(+SCurveRegionA) histP; - // switch(pulseRegion) - // { - // case 0: histP = SCurveRegionA; - // case 1: histP = SCurveRegionB; - // case 2: histP = SCurveRegionC; - // case 3: histP = SCurveRegionD; - // } - - // for(int i = 1; i < 504; i++) - // { - // for(int j = pulseColRegionLow; jSetParLimits(0,0,55000); - // f1->SetParLimits(1,0,255); - // f1->SetParameters(50000,100,10); - // f1->SetParError(1, 0.1); - - // auto hist = static_cast(histP)->ProjectionX(" ",i*colsN+j,i*colsN+j); - // int status = static_cast(hist)->Fit("f1","NQS"); - // fs << j << "\t" << i << "\t" << status << "\t" << f1->GetParameter(1) << "\t" << f1->GetParameter(2) << "\n"; - // std::cout << j << "\t" << i << "\t" << status << "\t" << f1->GetParameter(1) << "\t" << f1->GetParameter(2) << "\n"; - // delete hist; - // delete f1; - // } - // } - // fs.close(); - }; -} - - -int main(int argc, char* argv[]) -{ - std::string src = argv[1]; - hadaq::ReadoutHandle ref = hadaq::ReadoutHandle::Connect(src.c_str()); - if (ref.null()) return 1; - hadaq::RawEvent *evnt = nullptr; - - SCAN: - await_params(); - send_ack(); - - while (true) { - evnt = ref.NextEvent(1.,-1); - if (!evnt) continue; - hadaq::RawSubevent* sub = nullptr; - - while ((sub = evnt->NextSubevent(sub)) != nullptr) { - unsigned headersNow = 0; - uint32_t pulseMsg = 0; - unsigned size = sub->GetNrOfDataWords(); - - for( unsigned i = 0; i(sub->Data(i)); - - if((data & 0xFF000000) == 0xFE000000) { - - headersNow++; - - if(headersNow == 3) { - pulseMsg = (data & 0xFF0000) >> 16; - pulseMsg += (data & 0xFF) << 8; - } else if(headersNow == 4) { - pulseMsg += data & 0xFF0000; - pulseMsg += (data & 0xFF) << 24; - - if( ( ( 0x00c00000 & pulseMsg ) == 0x00c00000 ) ) { - std::printf("Start region\n"); - } else if( ( 0x00c00000 & pulseMsg ) == 0x00400000 ) { - std::printf("Start fit\n"); - fit(static_cast(pulseMsg & 0xFF)); - goto SCAN; - } else if( ( 0x00c00000 & pulseMsg ) == 0x00800000 ) { - std::printf("Start next round\n"); - goto SCAN; - } else if ( ( 0x00300000 & pulseMsg ) == 0x00300000 ){ - return 0; - } - } - } else if((data & 0xFF000000) == 0xFF000000) { - headersNow = 0; - } else { - } - // std::printf("%u\t%x\n",size, sub->Data(i)); - } - } - } - ref.Disconnect(); - return 0; -} diff --git a/analysis/mbs/main.cxx b/analysis/mbs/main.cxx new file mode 100644 index 0000000..a5b0fa7 --- /dev/null +++ b/analysis/mbs/main.cxx @@ -0,0 +1,511 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "hadaq/api.h" + +#include "trbnet.h" + + +using namespace std::chrono; + + +enum params {STATE, YLOW, YHIG, XLOW, XHIG, REGION, VCASN, VPHFINE}; + +namespace Data +{ + std::array dataArray; + int dataFraCnt = 0; + int limitFra = 500; + + short vphfine; + + int yLow, yHig, xLow, xHig; + int yLowMax = 504, yHigMax = 0, xLowMax = 1024, xHigMax = 0; + int sLowMax = 255, sHigMax = 0; + + std::string dataDir; + + std::string state; + + std::vector vcasnVec; + + decltype(high_resolution_clock::now()) start; + + std::vector mimFraCntNewVec; + std::vector mimFraCntOldVec; +}; + + +std::string pidName = "/tmp/hldprint-pid"; + + +void write_pid(void) +{ + int pid = (int)getpid(); + + // std::cout << pid << '\n'; + + FILE *pidFile = fopen(pidName.c_str(), "w"); + + if(pidFile == nullptr) { + std::printf("ERROR: Couldn't open file.\n"); + std::exit(-1); + } + + fprintf(pidFile, "%d",pid); + + fclose(pidFile); +} + + + +std::vector await_params() +{ + std::string pipeName = "/tmp/scurveipipe"; + FILE *iPipe = fopen(pipeName.c_str(), "r"); + + if(iPipe == nullptr) { + std::printf("ERROR: Couldn't open file.\n"); + std::exit(-1); + } + + int buf; + bool foundFrame = false, foundSta = false, foundEnd = false; + std::string word; + std::vector values; + + buf = fgetc(iPipe); + + while(!foundFrame && buf != EOF) + { + char c = static_cast(buf); + + if(c == '-') { + values.push_back(word); + word = ""; + } else { + word += c; + } + + if(word == "START") { foundSta = true; } + if(word == "END") { foundEnd = true; } + + buf = fgetc(iPipe); + + if(foundSta && foundEnd) { + foundFrame = true; + break; + } + } + + values.erase(values.begin()); + + // for (const auto& i: values) + // std::cout << i << '\n'; + + fclose(iPipe); + + return values; +} + + + +int send_ack() +{ + std::string pipeName = "/tmp/scurveapipe"; + FILE *iPipe = fopen(pipeName.c_str(), "w"); + + if(iPipe == nullptr) { + std::printf("ERROR: Couldn't open file.\n"); + std::exit(-1); + } + + std::string msg("ACK"); + fputs(msg.c_str(),iPipe); + fclose(iPipe); + return 0; +} + + + +void make_fit(std::string reg, std::string vcasn) +{ + // auto start = high_resolution_clock::now(); + + std::string subDir = Data::dataDir + "/" + reg + "-" + vcasn; + + mkdir(subDir.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); + + std::string fileName = subDir + "/" + reg + "-" + vcasn + ".csv"; + + + std::ofstream file(fileName); + char buffer[1000000]; + file.rdbuf()->pubsetbuf(buffer, sizeof(buffer)); + + for(int y = Data::yLowMax; y <= Data::yHigMax; y++) { + for(int x = Data::xLowMax; x <= Data::xHigMax; x++) { + for(int s = Data::sLowMax; s <= Data::sHigMax; s++) { + uint32_t v = Data::dataArray[(y*1024+x)*255+s]; + file << v << '\t'; + // if(v != 0) { printf("%d %d %d %d\n",y,x,s,v); } + Data::dataArray[(y*1024+x)*255+s] = 0; + } + file << '\n'; + } + } + file.close(); + + // auto stop = high_resolution_clock::now(); + // auto duration = duration_cast(stop - start); + // std::cout << duration.count() << std::endl; + + return; +} + + + +bool decode_pixel(const uint32_t& word, int& column, int& row, const int& region) +{ + const unsigned long pixelcode = (word >> 6) & 0x3ff; + + unsigned long + side = 0, + topdown = 0; + + if((pixelcode&3) == 0x1 || (pixelcode&3) == 0x2) side = 1; + if((pixelcode&3) == 0x3 || (pixelcode&3) == 0x2) topdown = 1; + + row = (pixelcode>>2)*2 + topdown; + column = (((word>>3)&0x7) + region*8)*2 + side; + + return true; +} + + + +void take_data(std::string src) +{ + hadaq::ReadoutHandle ref = hadaq::ReadoutHandle::Connect(src.c_str()); + if (ref.null()) return; + hadaq::RawEvent *evnt = nullptr; + + bool takeData = false; + int region = 0, column, row; + short vphfine; + + while (true) + { + evnt = ref.NextEvent(1.,-1); + if (!evnt) continue; + hadaq::RawSubevent* sub = nullptr; + + while ((sub = evnt->NextSubevent(sub)) != nullptr) + { + unsigned headersNow = 0; + uint32_t mimFraCntNew = 0; + uint32_t mimFraCntOld = 0; + bool fraFirst = true; + uint32_t pulseMsg = 0; + unsigned size = sub->GetNrOfDataWords(); + + for( unsigned i = 0; i(sub->Data(i)); + + if((data & 0xFF000000) == 0xFE000000) { + + headersNow++; + + if(headersNow == 1) { + + mimFraCntNew = (data & 0xFF0000) >> 16; + mimFraCntNew += (data & 0xFF) << 8; + + } else if(headersNow == 2) { + + mimFraCntNew += data & 0xFF0000; + mimFraCntNew += (data & 0xFF) << 24; + + if(mimFraCntNew-mimFraCntOld != 1 && !fraFirst) { + Data::mimFraCntNewVec.push_back(mimFraCntNew); + Data::mimFraCntOldVec.push_back(mimFraCntOld); + std::printf("Found skipped mimosis frame counter:\nOld:\t%u\nNew:\t%u\n",mimFraCntOld,mimFraCntNew); + } + mimFraCntOld = mimFraCntNew; + fraFirst = false; + + } else if(headersNow == 3) { + + pulseMsg = (data & 0xFF0000) >> 16; + pulseMsg += (data & 0xFF) << 8; + + // std::printf("%u\t%x\n",size, sub->Data(i)); + + } else if(headersNow == 4) { + + pulseMsg += data & 0xFF0000; + pulseMsg += (data & 0xFF) << 24; + vphfine = ( pulseMsg & 0xFF000000 ) >> 24; + + // std::printf("%u\t%x\n",size, sub->Data(i)); + // std::printf("%x\n", pulseMsg); + + if( ( ( 0x00c00000 & pulseMsg ) == 0x00c00000 ) && + (vphfine == Data::vphfine)) { + + takeData = true; + Data::dataFraCnt++; + + if(Data::dataFraCnt >= Data::limitFra) { + takeData = false; + Data::dataFraCnt = 0; + goto ENDFUNC; + } + + Data::sLowMax = vphfine < Data::sLowMax ? vphfine : Data::sLowMax; + Data::sHigMax = vphfine > Data::sHigMax ? vphfine : Data::sHigMax; + + } else if( ( 0x00c00000 & pulseMsg ) == 0x00400000 ) { + + takeData = false; + goto ENDFUNC; + + } else if( ( 0x00c00000 & pulseMsg ) == 0x00000000 ) { + takeData = false; + //Idle + } + } + + } else if((data & 0xFF000000) == 0xFF000000) { + + headersNow = 0; + + } else { + + headersNow = 0; + + if( takeData ) { + + if( (data & 0xFF000000) == 0xFD000000 ) { + const int tmp = (data>>16) & 0xFF; + if(tmp > 63) continue; + region = tmp; + + } else { + + decode_pixel(data>>16,column,row,region); + if(column >= Data::xLow && + column <= Data::xHig && + row >= Data::yLow && + row < Data::yHig ) { + Data::dataArray[(row*1024+column)*255+vphfine] += 1; + // printf("%d %d %d %d\n",row, column, vphfine, Data::dataArray[(row*1024+column)*255+vphfine]); + } + } + + if((data & 0x0000FF00) != 0x0000FC00) { + + decode_pixel(data&0xFFFF,column,row,region); + + if(column >= Data::xLow && + column <= Data::xHig && + row >= Data::yLow && + row < Data::yHig ) { + Data::dataArray[(row*1024+column)*255+vphfine] += 1; + } + } + } + } + } + } + } + ENDFUNC: + ref.Disconnect(); + return; +} + + + +void find_edge() +{ + using namespace Data; + yLowMax = yLow < yLowMax ? yLow : yLowMax; + yHigMax = yHig > yHigMax ? yHig : yHigMax; + xLowMax = xLow < xLowMax ? xLow : xLowMax; + xHigMax = xHig > xHigMax ? xHig : xHigMax; +} + + + +void write_meta() +{ + + std::string fileName = Data::dataDir + "/METADATA"; + std::ofstream file(fileName); + + file << "START:" << '\t' << Data::dataDir << '\n'; + + file << "VCASN:"; + for(const auto& i: Data::vcasnVec) { + file << '\t' << i; + } + file << '\n'; + + file << "YMIN:" << '\t' << Data::yLowMax << '\n'; + file << "YMAX:" << '\t' << Data::yHigMax << '\n'; + file << "XMIN:" << '\t' << Data::xLowMax << '\n'; + file << "XMAX:" << '\t' << Data::xHigMax << '\n'; + file << "SMIN:" << '\t' << Data::sLowMax << '\n'; + file << "SMAX:" << '\t' << Data::sHigMax << '\n'; + + file << "EXITSTATE:" << '\t' << Data::state << '\n'; + + auto stop = high_resolution_clock::now(); + auto duration = duration_cast(stop - Data::start); + file << "TIME(s):" << '\t' << duration.count() << '\n'; + + file << "COMMENT:\t\n"; + + file.close(); +} + + + +void signal_handler( int signum ) +{ + std::cout << "Interrupt signal (" << signum << ") received Cleaning up...\n"; + + if(Data::state == "TAKEDATA" || + Data::state == "WAITDAQ" || + Data::state == "FIT") { + + std::string lastReg = "INTERRUPTED"; + std::string lastVca = "INTERRUPTED"; + make_fit(lastReg, lastVca); + std::cout << "Remining data indicated by INTERRUPTED flags.\n"; + + } else { + } + + //remove pid file + remove(pidName.c_str()); + + write_meta(); + + std::exit(signum); +} + + + +int main(int argc, char* argv[]) +{ + //Read stream url + std::string src = argv[1]; + + + //Initialize trbnet for this run + int trbnetState = init_ports(); + + + //Start clock to report execution time METADATA + Data::start = high_resolution_clock::now(); + + + //Generate the PID file + write_pid(); + + + //Register signal SIGINT and signal handler + signal(SIGINT, signal_handler); + + + //Declare stateVec, that will hold the + //informations passed from control script + std::vector stateVec; + + + //Create main data dir by time stamp + std::time_t time = std::time(0); + std::tm* now = std::localtime(&time); + + Data::dataDir = std::to_string(now->tm_year + 1900) + '-' + + std::to_string(now->tm_mon + 1) + '-' + + std::to_string(now->tm_mday) + '-' + + std::to_string(now->tm_hour) + '-' + + std::to_string(now->tm_min); + + mkdir(Data::dataDir.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH); + + + //Initialize data array with 0's + for(int y = 0; y <= 505; y++) + for(int x = 0; x <= 1025; x++) + for(int s = 0; s <= 256; s++) + Data::dataArray[(y*1024+x)*255+s] = 0; + + + //Control loop. After init phase, + //wait for commands from control script + AWAIT: + stateVec = await_params(); + Data::state = stateVec[params::STATE]; + + if(Data::state == "TAKEDATA") { + + Data::yLow = std::stoi(stateVec[params::YLOW], nullptr, 10); + Data::yHig = Data::yLow + std::stoi(stateVec[params::YHIG], nullptr, 10); + Data::xLow = std::stoi(stateVec[params::XLOW], nullptr, 10); + Data::xHig = std::stoi(stateVec[params::XHIG], nullptr, 10); + + std::printf("Take data: "); + std::printf("%4d %4d %4d %4d\n", Data::yLow, Data::yHig, Data::xLow, Data::xHig); + find_edge(); + send_ack(); + take_data(src); + goto AWAIT; + + } else if(Data::state == "WAITDAQ") { + + // std::printf("At WAITDAQ.\n"); + send_ack(); + goto AWAIT; + + } else if(Data::state == "FIT") { + + std::string regStr = stateVec[params::REGION]; + std::string vcaStr = stateVec[params::VCASN]; + Data::vcasnVec.push_back(vcaStr); + std::printf("Write data: %s %s\n",regStr.c_str(),vcaStr.c_str()); + make_fit(regStr,vcaStr); + send_ack(); + goto AWAIT; + + } else if(Data::state == "DONE") { + + std::printf("Done.\n"); + send_ack(); + + remove(pidName.c_str()); + + write_meta(); + + return 0; + + } else { + + std::printf("Received garbage. Exiting.\n"); + + remove(pidName.c_str()); + + return 1; + } +} diff --git a/analysis/rawreader/mimosis.h b/analysis/rawreader/mimosis.h index 0d5da31..362c25b 100644 --- a/analysis/rawreader/mimosis.h +++ b/analysis/rawreader/mimosis.h @@ -135,8 +135,7 @@ bool hadaq::MimosisProcessor::FirstBufferScan(const base::Buffer& buf) noexcept Last4096->SetBinContent(frameNumber % 4096, hitcount); hitcount = 0; - if (frameCounter == 1000000) { - std::printf("Entries: %f\n", MatrixCurrent->GetEntries()); + if (frameCounter == 10000) { MatrixCurrent->Copy(*MatrixLast); MatrixLast->SetName("MatrixLast10000"); MatrixCurrent->Reset(); diff --git a/analysis/scurve/fpn.py b/analysis/scurve/fpn.py deleted file mode 100755 index 7c7d928..0000000 --- a/analysis/scurve/fpn.py +++ /dev/null @@ -1,27 +0,0 @@ -#!/usr/bin/env python -import csv -#from scipy import special -import matplotlib.pyplot as plt -import numpy as np -import pandas as pd - -#dataset = pd.read_csv('regA_1.csv', delimiter='\t',header=None) -dataset = pd.read_csv('params.csv', delimiter='\t',header=None) -values = list(dataset.columns.values) -meansig = np.array(dataset[values[0:5]], dtype='float32') - -x = np.linspace(0, 255, num=255) - -hist = np.zeros(255) - -for i in range(len(meansig)): - # if i > 3500: - # break - if meansig[i,2] != 0.0 or meansig[i,3] < 0.0 or meansig[i,3] > 255 or meansig[i,4] < 1.0 or meansig[i,4] > 10.0: - continue - hist[int(meansig[i,3])] += 1 - # plt.plot(x, 50000*(1 + special.erf((x-meansig[i,3])/(np.sqrt(2)*meansig[i,4])))) - -plt.bar(x,hist,width=1) -# plt.hist(hist) -plt.show() diff --git a/analysis/scurve/libtrbnet.a b/analysis/scurve/libtrbnet.a deleted file mode 100644 index f5bd46def9d7baead0dbe7ff6cd9332af36e315c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 125464 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

`y;4IKTwWdeW#Br6 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 + diff --git a/scripts/Mimosis.pm b/scripts/Mimosis.pm index cfb3720..1c5f2ca 100755 --- a/scripts/Mimosis.pm +++ b/scripts/Mimosis.pm @@ -523,11 +523,11 @@ set multiplot layout 2,2; set key Left left top box; set xlabel \\"set.\\"; set ylabel \\"[mV]\\"; -array names0[7] = [\\"VCASP\\", \\"VCASNA\\", \\"VCASNB\\", \\"VCASNC\\", \\"VCASND\\", \\"VCASN2\\", \\"VCLIP\\"]; +array names0[7] = [\\"VCASND\\", \\"VCASN2\\", \\"VCASP\\", \\"VCLIP\\", \\"VCASNA\\", \\"VCASNB\\", \\"VCASNC\\"]; plot for [i=0:6] \\"$vmon_file_n\\" using 2:3 index i with l title names0[i+1]; -array names1[3] = [\\"IBIAS\\", \\"ITHR\\", \\"IDB\\"]; +array names1[3] = [\\"IBIAS\\", \\"IDB\\", \\"ITHR\\"]; plot for [i=0:2] \\"$imon_file_n\\" using 2:3 index i with l title names1[i+1]; -array names2[3] = [\\"VRESET\\", \\"VPH\\", \\"VPL\\"]; +array names2[3] = [\\"VPH\\", \\"VPL\\", \\"VRESET\\"]; plot for [i=0:2] \\"$other_file_n\\" using 2:3 index i with l title names2[i+1];" END_MESSAGE system $message_png; @@ -698,8 +698,9 @@ sub mimosis_dacscan_sf sub send_params_scurve { - my ($yi, $rowTrain) = @_; - my $frameWr = "START-" . $yi . "-" . $rowTrain . "-END"; + my ($state, $yi, $rowTrain, $xLow, $xHig, $region, $vcasn, $vphfine) = @_; + $vphfine = defined $vphfine ? $vphfine : 0; + my $frameWr = "START-" . $state . "-" . $yi . "-" . $rowTrain . "-" . $xLow . "-" . $xHig . "-" . $region . "-" . $vcasn . "-" . $vphfine . "-END"; my $pipeNameWr = "/tmp/scurveipipe"; my $fdPipeWr = POSIX::open($pipeNameWr, &POSIX::O_WRONLY); POSIX::write($fdPipeWr,$frameWr,length($frameWr)); @@ -708,6 +709,22 @@ sub send_params_scurve +sub kill_proc_by_pid_file +{ + my ($pidName) = @_; + + my $pidFile = POSIX::open($pidName, &POSIX::O_RDONLY) or die "hldprint already killed probably\n"; + my $buf; + my $bytes = POSIX::read($pidFile,$buf,10); + POSIX::close($pidFile); + + kill 15, $buf; + + unlink($pidName) or die "Can't delete $pidName: $!\n"; +} + + + sub await_ack { my $pipeNameRd = "/tmp/scurveapipe"; @@ -723,7 +740,6 @@ sub await_ack } } POSIX::close($fdPipeRd); - print "ACK received\n"; } @@ -755,7 +771,7 @@ sub mimosis_scan_region defined $fpga or die "Mimosis::mimosis_scan_region: Must provide $fpga."; defined $region or die "Mimosis::mimosis_scan_region: Must provide $region."; - my %collim = ( + my %colLim = ( 'A' => [ 0, 127 ], 'B' => [ 128, 511 ], 'C' => [ 512, 895 ], @@ -805,6 +821,7 @@ sub mimosis_scan_region $yOff+=$yTra ) { my $y = $yOff; + for ( ; $y < $yOff+$yTra && $y <= $yEnd; $y+=1 ) { @@ -821,33 +838,150 @@ sub mimosis_scan_region Mimosis::mimosis_instr_write( $fpga, 0x3e ); usleep($slow); #INSTR unselect all pixels } - send_params_scurve($yOff, $yTra); + unless($pulseonly) + { + my $yTraSend = $yEnd-$yOff<$yTra ? $yEnd-$yOff : $yTra; + send_params_scurve("TAKEDATA", $yOff, $yTraSend, $colLim{$region}[0], $colLim{$region}[1], $region, 0); + await_ack(); + + my $setCnt = 0; + for my $set (reverse ($setSta .. $setEnd) ) + { + $setCnt = $setCnt + 1; + if( ($setCnt-1)%$setDiv != 0) { next; } + + send_params_scurve("NEXTVPH", 0, 0, 0, 0, 0, 0, $set); + await_ack(); + + my $pulseMsg = ($set << 24) + 0x00c00000; + trb_register_write_mem( $fpga, 0xa209, 0, [ $pulseMsg ], 1 ); usleep($slow); + # Mimosis::mimosis_register_write( $fpga, 0x0046, $set, $a ); usleep($setTime); + Mimosis::mimosis_register_write( $fpga, 0x0046, $set, $a ); + + if( $printset || $printall ) { printf("set: $set\n"); } + } + + Mimosis::mimosis_instr_write( $fpga, 0x3f ); usleep($slow); + Mimosis::mimosis_instr_write( $fpga, 0x04 ); usleep($slow); #INSTR set mask pulse + Mimosis::mimosis_instr_write( $fpga, 0x3e ); usleep($slow); #INSTR set mask pulse + + trb_register_write_mem( $fpga, 0xa209, 0, [ 0x00400000 ], 1 ); usleep($slow); + send_params_scurve("WAITDAQ", 0, 0, 0, 0, 0, 0); + await_ack(); + trb_register_write_mem( $fpga, 0xa209, 0, [ 0x00000000 ], 1 ); usleep($slow); + } + } +} + + + +sub mimosis_scan_pixel +{ + my %params = @_; + my $fpga = $params{'fpga'}; + my $x = $params{'x'}; + my $y = $params{'y'}; + my $add = $params{'add'}; + my $pulseonly = $params{'pulseonly'}; + my $setSta = $params{'firstset'}; + my $setEnd = $params{'lastset'}; + my $setDiv = $params{'setdiv'}; + my $setTime = $params{'settime'}; + my $slow = $params{'slow'}; + my $a = $params{'a'}; + my $printset = $params{'printset'}; + my $printall = $params{'printall'}; + my $analogAlimA = $params{'analogAlimA'}; + my $analogAlimB = $params{'analogAlimB'}; + my $analogDlimA = $params{'analogDlimA'}; + my $analogDlimB = $params{'analogDlimB'}; + my $modpulse = $params{'modpulse'}; + + defined $fpga or die "Mimosis::mimosis_scan_region: Must provide --fpga."; + defined $x or die "Mimosis::mimosis_scan_region: Must provide --x."; + defined $y or die "Mimosis::mimosis_scan_region: Must provide --y."; + + $setSta = defined $setSta ? $setSta : 0x0; + $setEnd = defined $setEnd ? $setEnd : 0xff; + $setDiv = defined $setDiv ? $setDiv : 1; + $setTime = defined $setTime ? $setTime : 1000; + $slow = defined $slow ? $slow : 10000; + $a = defined $a ? $a : 0; + $printset = defined $printset ? 1 : 0; + $printall = defined $printall ? 1 : 0; + $pixpulseA_A = defined $pixpulseA_A ? $pixpulseA_A : 25; + $pixpulseA_B = defined $pixpulseA_B ? $pixpulseA_B : 75; + $pixpulseD_A = defined $pixpulseD_A ? $pixpulseD_A : 0; + $pixpulseD_B = defined $pixpulseD_B ? $pixpulseD_B : 0; + $modpulse = defined $modpulse ? $modpulse : 3; + + Mimosis::mimosis_register_write( $fpga, 0x0020, 0x40, $a ); usleep($slow); #EN_PIXELMASK to 0 for pulse + + unless(defined $add) + { + Mimosis::mimosis_instr_write( $fpga, 0x3f ); usleep($slow); #INSTR select all pixels + Mimosis::mimosis_instr_write( $fpga, 0x04 ); usleep($slow); #INSTR reset mask + Mimosis::mimosis_instr_write( $fpga, 0x3e ); usleep($slow); #INSTR unselect all pixels + } + + Mimosis::mimosis_register_write( $fpga, 0x0066, $pixpulseA_A & 0x00ff , $a ); usleep($slow); #analog pulsing pulse A, limit A + Mimosis::mimosis_register_write( $fpga, 0x0166, ( $pixpulseA_A & 0xff00 ) >> 8, $a ); usleep($slow); + Mimosis::mimosis_register_write( $fpga, 0x0076, $pixpulseA_B & 0x00ff , $a ); usleep($slow); # analog pulsing pulse A, limit B + Mimosis::mimosis_register_write( $fpga, 0x0176, ( $pixpulseA_B & 0xff00 ) >> 8, $a ); usleep($slow); + Mimosis::mimosis_register_write( $fpga, 0x0067, $pixpulseD_A & 0x00ff , $a ); usleep($slow); # analog pulsing pulse D, limit A + Mimosis::mimosis_register_write( $fpga, 0x0167, ( $pixpulseD_A & 0xff00 ) >> 8, $a ); usleep($slow); + Mimosis::mimosis_register_write( $fpga, 0x0077, $pixpulseD_B & 0x00ff , $a ); usleep($slow); # analog pulsing pulse D, limit B + Mimosis::mimosis_register_write( $fpga, 0x0177, ( $pixpulseD_B & 0xff00 ) >> 8, $a ); usleep($slow); + Mimosis::mimosis_register_write( $fpga, 0x007d, $modpulse, $a ); usleep($slow); #set modpulse. possible values: 1f/1, 1f/2, 1f/4, 1f/8, 1f/16, 1f/32, 1f/64, 1f/128 + + { + my $regAdd = $x/16; #region address + my $regBit = ($x/2)%8; #double column in region + my $regWord = $regAdd << 8; + if (($x%2 == 1)) { $regWord += 0x82; } + elsif (($x%2 == 0)) { $regWord += 0x81; } + Mimosis::mimosis_register_write( $fpga, $regWord, ( 0x1 << $regBit ), $a ); usleep($slow); + } + + { + my $regAdd = $y/8; + my $regBit = $y%8; + my $regWord = ( $regAdd << 8 ) + 0x84; + Mimosis::mimosis_register_write( $fpga, $regWord, ( 0x1 << $regBit ), $a ); usleep($slow); + } + + Mimosis::mimosis_instr_write( $fpga, 0x05 ); usleep($slow); #INSTR set mask pulse + Mimosis::mimosis_register_write( $fpga, 0x4087, 0x0, $a ); usleep($slow); #unselect all pixels (register wise) + + unless($pulseonly) + { + send_params_scurve("TAKEDATA", $y, 1, $x, $x+1, 0, 0); await_ack(); - # unless($pulseonly) - # { - # # my $setCnt = 0; - # for my $set (reverse ($setSta .. $setEnd) ) - # { - # # $setCnt = $setCnt + 1; - # # if( ($setCnt-1)%$setDiv != 0) { next; } - - # my $pulseMsg = ($set << 24) + 0x00c00000; - # trb_register_write_mem( $fpga, 0xa209, 0, [ $pulseMsg ], 1 ); usleep($slow); - # Mimosis::mimosis_register_write( $fpga, 0x0046, $set, $a ); usleep($setTime); - - # if( $printset || $printall ) { printf("set: $set\n"); } - # } - - # Mimosis::mimosis_instr_write( $fpga, 0x3f ); usleep($slow); - # Mimosis::mimosis_instr_write( $fpga, 0x04 ); usleep($slow); #INSTR set mask pulse - # Mimosis::mimosis_instr_write( $fpga, 0x3e ); usleep($slow); #INSTR set mask pulse - # } - # indicate end of current rows - if($y == $yEnd) { - trb_register_write_mem( $fpga, 0xa209, 0, [ 0x00800000 ], 1 ); usleep($slow); - print "check\n"; + my $setCnt = 0; + for my $set (reverse ($setSta .. $setEnd) ) + { + $setCnt = $setCnt + 1; + if( ($setCnt-1)%$setDiv != 0) { next; } + + my $pulseMsg = ($set << 24) + 0x00c00000; + trb_register_write_mem( $fpga, 0xa209, 0, [ $pulseMsg ], 1 ); usleep($slow); + Mimosis::mimosis_register_write( $fpga, 0x0046, $set, $a ); usleep($setTime); + + if( $printset || $printall ) { printf("set: $set\n"); } } + + unless(defined $add) + { + Mimosis::mimosis_instr_write( $fpga, 0x3f ); usleep($slow); #INSTR select all pixels + Mimosis::mimosis_instr_write( $fpga, 0x04 ); usleep($slow); #INSTR reset mask + Mimosis::mimosis_instr_write( $fpga, 0x3e ); usleep($slow); #INSTR unselect all pixels + } + + trb_register_write_mem( $fpga, 0xa209, 0, [ 0x00400000 ], 1 ); usleep($slow); + send_params_scurve("WAITDAQ", 0, 0, 0, 0, 0, 0); + await_ack(); + trb_register_write_mem( $fpga, 0xa209, 0, [ 0x00000000 ], 1 ); usleep($slow); } } @@ -870,7 +1004,6 @@ sub mimosis_mask my $square = $params{'square'}; my $printall = $params{'printall'}; - defined $fpga or die "Mimosis::mimosis_mask: Must provide $fpga."; $slow = defined $slow ? $slow : 10000; @@ -1131,6 +1264,9 @@ sub help_scurves { usage: mimosis [GLOBAL OPTIONS] scurves [COMMAND OPTIONS] +The data will be priveded in a folder in the current directory with the time started as name. +The data is sorted by the VCASN, if --vcasn is not provided, or by + GLOBAL OPTIONS are: -f, --fpga=HEX -> Hex address of the FPGA. Defaults to 0xa000. -s, --slow=NUM -> Execute I2C commands with a pause of NUM microseconds in between. @@ -1138,33 +1274,35 @@ GLOBAL OPTIONS are: -h, --help -> Print this or specific help. COMMAND OPTIONS are: - --colpix X -> x value of a single pixel to pulse. - --rowpix Y -> y value of a single pixel to pulse. - --pulseonly -> if set, mark specified pixels only for pulsing and dont do a scan. - -r, --region A|B|C|D -> Region to pulse. + -r, --region A|B|C|D -> Region to pulse. Most be provided. + --firstrow Y -> First row to scan. --lastrow Y -> Last row to scan. --rowdiv ROWDIV -> Just pulse every ROWDIV row. - --firstcol X -> First column to scan. - --lastcol X -> Last column to scan. - --coldiv COLDIV -> Just pulse every COLDIV column. + --nrows N -> How many rows to pulse at once. Default depends on region. For A,D: N = 4, for B,D: N = 2. + --firstset S -> Start s-curve scan at VPH_FINE=S --lastset S -> Stop s-curve scan at VPH_FINE=S --setdiv SETDIV -> Just use every SETDIV value of VPH_FINE. --settime T -> Take data for each VPH_FINE for T milliseconds. - --vcasn A|B|C|D -> VACSN to vary. Default is the same as specified with --region. + --firstvcasn V -> Start s-curve taking with VCASN=V. --lastvcasn V -> Stop s-curve taking at VCASN=V. --vcasndiv V -> Take s-curve every V steps. - --nrows N -> How many rows to pulse at once. Default depends on region. For A,D: N = 4, for B,D: N = 2. + + --pulseonly -> If set, mark specified pixels only for pulsing and dont do a scan. + --modpulse MOD -> Exponent of the power of two, which gives the divider of the frames to pulse. + + --printdac -> Print the current setting of the DAC. --printset -> Print the current VPH_FINE setting. --printrow -> Print current row to set. -p, --printall -> Print all informations available. + --analogAlimA -> Not implemented yet. --analogAlimB -> Not implemented yet. --analogDlimA -> Not implemented yet. --analogDlimB -> Not implemented yet. - --modpulse MOD -> Exponent of the power of two, which gives the divider of the frames to pulse. + -h, --help -> Print this help. END_MESSAGE diff --git a/scripts/cli/mimosis b/scripts/cli/mimosis index 2645c2f..c7ef7f5 100755 --- a/scripts/cli/mimosis +++ b/scripts/cli/mimosis @@ -9,7 +9,10 @@ use Data::Dump qw(dump); use File::Copy; -$SIG{INT} = sub { die "\nAbort.\n" }; +$SIG{INT} = sub { + Mimosis::kill_proc_by_pid_file("/tmp/hldprint-pid"); + die "\nAbort.\n" +}; #global @@ -22,10 +25,10 @@ my ( $printall_load, $printwrong_load ); my ( $ikf, $name, $imagefileonly, $cleanup_dacscan, $printall_dacscan ); #scurves -my ( $colpix_scurves, $rowpix_scurves, $pulseOnlySc, $regionSc, +my ( $pulseOnlySc, $regionSc, $xSc, $ySc, $addSc, $resetSc, $yStaSc, $yEndSc, $yStepSc, $setStaSc, $setEndSc, - $setStepSc, $vcasnSc, $vcasnStaSc, $vcasnEndSc, + $setStepSc, $vcasnSc, $vcasnStaSc, $vcasnEndSc, $vcasnStepSc, $setTimeSc, $yTraSc, $printSetSc, $printDacSc, $printRowSc, $printAllSc, $analogAlimASc, $analogAlimBSc, $analogDlimASc, $analogDlimBSc, $modpulseSc ); @@ -71,10 +74,12 @@ my $res = GetOptions ( }, scurves => { options => { - "colpix=s" => \$colpix_scurves, - "rowpix=s" => \$rowpix_scurves, "pulseonly" => \$pulseOnlySc, "region|r=s" => \$regionSc, + "x=s" => \$xSc, + "y=s" => \$ySc, + "add" => \$addSc, + "reset" => \$resetSc, "firstrow=s" => \$yStaSc, "lastrow=s" => \$yEndSc, "rowdiv=s" => \$yStepSc, @@ -257,14 +262,16 @@ elsif( $res->{subcommand}[0] eq 'scurves' ) if( defined $regionSc ) { - $vcasnSc = defined $vcasnSc ? $vcasnSc : $regionSc; - my $vcasnStr = $regCharToStr{$vcasnSc}; + my $vcasnStr = $regCharToStr{$regionSc}; my $vcasnVal = Mimosis::mimosis_register_read( $fpga, $dacs{$vcasnStr}, $a ); $vcasnStaSc = defined $vcasnStaSc ? $vcasnStaSc : $vcasnVal; $vcasnEndSc = defined $vcasnEndSc ? $vcasnEndSc : $vcasnStaSc; $vcasnStepSc = defined $vcasnStepSc ? $vcasnStepSc : 1; - # system("/d/jspc37/mimosis/analysis/mbs/dabc/build/bin/hldprint mbss://localhost:36789 &"); + unless($pulseOnlySc) + { + system("/d/jspc37/mimosis/analysis/mbs/dabc/build/bin/hldprint mbss://localhost:36789 &"); + } for ( my $vcasnSet = $vcasnStaSc; $vcasnSet <= $vcasnEndSc; @@ -279,6 +286,7 @@ elsif( $res->{subcommand}[0] eq 'scurves' ) slow => $slow, a => $a, pulseonly => $pulseOnlySc, + add => $addSc, region => $regionSc, firstrow => $yStaSc, lastrow => $yEndSc, @@ -297,11 +305,82 @@ elsif( $res->{subcommand}[0] eq 'scurves' ) analogDlimB => $analogDlimBSc, modpulse => $modpulseSc, ); - trb_register_write_mem( $fpga, 0xa209, 0, [ 0x00400000 + ($vcasnSet & 0xFF) ], 1 ); usleep($slow); + + unless($pulseOnlySc) + { + Mimosis::send_params_scurve("FIT", 0,0,0,0,$regCharToStr{$regionSc},$vcasnSet); + Mimosis::await_ack(); + } } - trb_register_write_mem( $fpga, 0xa209, 0, [ 0x00300000 ], 1 ); usleep($s); + unless($pulseOnlySc) + { + Mimosis::send_params_scurve("DONE", 0,0,0,0,0,0); + Mimosis::await_ack(); + Mimosis::kill_proc_by_pid_file("/tmp/hldprint-pid"); + } exit 0; + + } elsif (defined $xSc && defined $ySc && defined $vcasnSc) { + + my $vcasnVal = Mimosis::mimosis_register_read( $fpga, $dacs{$vcasnSc}, $a ); + $vcasnStaSc = defined $vcasnStaSc ? $vcasnStaSc : $vcasnVal; + $vcasnEndSc = defined $vcasnEndSc ? $vcasnEndSc : $vcasnStaSc; + $vcasnStepSc = defined $vcasnStepSc ? $vcasnStepSc : 1; + + unless($pulseOnlySc) + { + system("/d/jspc37/mimosis/analysis/mbs/dabc/build/bin/hldprint mbss://localhost:36789 &"); + } + + for ( my $vcasnSet = $vcasnStaSc; + $vcasnSet <= $vcasnEndSc; + $vcasnSet += $vcasnStepSc ) { + #set vcasn + Mimosis::mimosis_register_write( $fpga, $dacs{$vcasnSc}, $vcasnSet, $a ); usleep($slow); + + if( $printDacSc || $printAllSc ) { printf("dac: $vcasnSet\n"); } + + Mimosis::mimosis_scan_pixel( + fpga => $fpga, + slow => $slow, + a => $a, + x => $xSc, + y => $ySc, + pulseonly => $pulseOnlySc, + firstset => $setStaSc, + lastset => $setEndSc, + setdiv => $setStepSc, + settime => $setTimeSc, + printset => $printSetSc, + printrow => $printRowSc, + printall => $printAllSc, + analogAlimA => $analogAlimASc, + analogAlimB => $analogAlimBSc, + analogDlimA => $analogDlimASc, + analogDlimB => $analogDlimBSc, + modpulse => $modpulseSc, + ); + + unless($pulseOnlySc) + { + Mimosis::send_params_scurve("FIT", 0,0,0,0,$vcasnSc,$vcasnSet); + Mimosis::await_ack(); + } + } + + unless($pulseOnlySc) + { + Mimosis::send_params_scurve("DONE", 0,0,0,0,0,0); + Mimosis::await_ack(); + Mimosis::kill_proc_by_pid_file("/tmp/hldprint-pid"); + } + exit 0; + + } else { + + print "Mimosis::mimosis_scan_region: Must provide --region A|B|C|D or --x X and --y Y.\n"; + exit 1; } } diff --git a/scripts/pulse/curves b/scripts/legacy/curves.py similarity index 100% rename from scripts/pulse/curves rename to scripts/legacy/curves.py diff --git a/scripts/pulse/fpn b/scripts/legacy/fpn.py similarity index 100% rename from scripts/pulse/fpn rename to scripts/legacy/fpn.py diff --git a/scripts/pulse/fit-raw.py b/scripts/pulse/fit-raw.py new file mode 100644 index 0000000..535e4ab --- /dev/null +++ b/scripts/pulse/fit-raw.py @@ -0,0 +1,74 @@ +import numpy as np +import matplotlib.pyplot as plt +import pandas as pd +from scipy.optimize import curve_fit +from scipy import special +import sys + + + +def error_func(x, mean, sig, ampl): + return ampl*(1 + special.erf((x-mean)/(np.sqrt(2*sig)))) + + + +def gauss_func(x, mean, sig, ampl): + return ampl*np.exp(-1*(((x-mean)**2)/(2*sig**2))) + + + +f = sys.argv[1] +df = pd.read_csv(f, delimiter='\t',header=None) + +x = np.linspace(0, 255, num=255) + +fpn = np.zeros(255) + +for i in range(len(df.loc[:])): + + xS = [] + for j in range(255): + if df.loc[i][j] != 0: + xS.append(j) + + print(xS) + + if sum(df.loc[i][0:255]) != 0: + + hist = df.loc[i][0:255] + + guess = [130, 25, 400] + params = [] + try: + params, tmp = curve_fit(error_func, x, hist) + print(params) + except RuntimeError: + continue + + mean = int(round(params[0])) + if mean < 255 and mean >= 0: + fpn[mean] += 1 + + plt.bar(x,hist,width=1) + plt.plot(x,error_func(x,params[0],params[1],params[2]),color="red") + + plt.savefig("raw-fit-" + str(i) + ".png") + plt.clf() + plt.cla() + plt.close() + + +# plot fpn +params = [] +#guess = [75, 25, 10] +guess = [10, 10, 10] +params, tmp = curve_fit(gauss_func, x, fpn,guess) +print("\n\nFPN: " + str(params[1]) + "\n\n") +print(params) +print() +print() + +plt.bar(x,fpn,width=1) +plt.plot(x,gauss_func(x,params[0],params[1],params[2]),color="red") +plt.savefig("fpn.png") + diff --git a/scripts/pulse/plot-raw.py b/scripts/pulse/plot-raw.py new file mode 100755 index 0000000..82fc7e5 --- /dev/null +++ b/scripts/pulse/plot-raw.py @@ -0,0 +1,20 @@ +#!/usr/bin/env python3 + +import matplotlib.pyplot as plt +import numpy as np +import pandas as pd +import sys + +f = sys.argv[1] +df = pd.read_csv(f, delimiter='\t',header=None) + +x = np.linspace(0, 255, num=255) + +for i in range(len(df.loc[:])): + if sum(df.loc[i][0:255]) != 0: + hist = df.loc[i][0:255] + plt.bar(x,hist,width=1) + plt.savefig("fpn-" + str(i) + ".png") + plt.clf() + plt.cla() + plt.close() diff --git a/scripts/pulse/plot-root.py b/scripts/pulse/plot-root.py new file mode 100755 index 0000000..70b658d --- /dev/null +++ b/scripts/pulse/plot-root.py @@ -0,0 +1,83 @@ +import matplotlib.pylab as plt +import numpy as np +import os +import re +import uproot +import sys + + +allData = np.zeros(1024*504*256) + +xLow = 512 +xHig = 890 +yLow = 100 +yHig = 400 + + + +def dir_to_scurves(dataDir): + + p = re.compile('VPH_fine_(.*)_VTH') + vphArr = [] + + for f in os.listdir(dataDir): + + print(f) + vph = int(p.findall(f)[0]) + if vph not in vphArr: + vphArr.append(vph) + + if f.endswith(".root"): + + fullName = os.path.join(dataDir, f) + infile = uproot.open(fullName) + matrix = infile['h2_integrated_frame_matrix;1'].values() + + for x in range(len(matrix)): + if x > xLow and x < xHig: + for y in range(len(matrix[x])): + if y > yLow and y < yHig: + allData[(y*1024+x)*256+vph] = matrix[x][y] + + # plt.imshow(matrix, interpolation='none') + # plt.savefig(os.path.basename(fullName) + ".png") + + vphArr.sort() + return vphArr + + + +#dataDir = sys.argv[1] + +#dataDir = '/d/pepper/maps/ben/BackupMIMOSIS1SCurves/MIMOSIS1_DataConverter_unix/outputData/run_9412004/' +dataDir = '/d/pepper/maps/ben/BackupMIMOSIS1SCurves/MIMOSIS1_DataConverter_unix/outputData/run_413137/' + +vphfine = dir_to_scurves(dataDir) + + +for x in range(1024): + if x > xLow and x < xHig: + for y in range(504): + if y > yLow and y < yHig: + + arr = [] + s = 0 + for i in vphfine: + val = allData[(y*1024+x)*256+i] + arr.append(val) + s += val + + if s < 50: + continue + + plt.bar(vphfine,arr,width=1) + plt.savefig("raw-" + str(x) + "-" + str(y) + ".png") + plt.clf() + plt.cla() + plt.close() + + + +# fileName = '/d/pepper/maps/ben/BackupMIMOSIS1SCurves/MIMOSIS1_DataConverter_unix/outputData/run_9412004/mimosis1_run9412004_VBB_3000_VPH_fine_65_VTH_106_noPLL.root' +# print(infile.classnames()) +# events = infile['h2_integrated_frame_matrix;1'].all_members diff --git a/scripts/pulse/requirements.txt b/scripts/pulse/requirements.txt new file mode 100644 index 0000000..b56483f --- /dev/null +++ b/scripts/pulse/requirements.txt @@ -0,0 +1,22 @@ +awkward==2.6.2 +awkward-cpp==30 +contourpy==1.2.0 +cramjam==2.8.3 +cycler==0.12.1 +fonttools==4.50.0 +fsspec==2024.3.1 +importlib_metadata==7.1.0 +kiwisolver==1.4.5 +matplotlib==3.8.3 +numpy==1.26.4 +packaging==24.0 +pandas==2.2.1 +pillow==10.2.0 +pyparsing==3.1.2 +python-dateutil==2.9.0.post0 +pytz==2024.1 +scipy==1.12.0 +six==1.16.0 +tzdata==2024.1 +uproot==5.3.2 +zipp==3.18.1 diff --git a/scripts/DACscan.py b/scripts/qa/DACscan.py similarity index 100% rename from scripts/DACscan.py rename to scripts/qa/DACscan.py diff --git a/scripts/test-mask.sh b/scripts/test-mask.sh deleted file mode 100755 index 4e0042f..0000000 --- a/scripts/test-mask.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/bin/bash - -fpga=0xa100 - -mimosis -f "${fpga}" -a reg 0x0020 0x42 -mimosis -f "${fpga}" -a instr 0x3f -mimosis -f "${fpga}" -a instr 0x04 -mimosis -f "${fpga}" -a instr 0x3e -mimosis -f "${fpga}" -a reg 0x0066 0x19 #analog pulsing pulse A, limit A -mimosis -f "${fpga}" -a reg 0x0166 0x00 -mimosis -f "${fpga}" -a reg 0x0076 0x4b # analog pulsing pulse A, limit B -mimosis -f "${fpga}" -a reg 0x0176 0x00 -mimosis -f "${fpga}" -a reg 0x0067 0x00 # analog pulsing pulse D, limit A -mimosis -f "${fpga}" -a reg 0x0167 0x00 -mimosis -f "${fpga}" -a reg 0x0077 0x00 # analog pulsing pulse D, limit B -mimosis -f "${fpga}" -a reg 0x0177 0x00 -mimosis -f "${fpga}" -a reg 0x007d 0x03 #set modpulse. possible values: 1f/1, 1f/2, 1f/4, 1f/8, 1f/16, 1f/32, 1f/64, 1f/128 -mimosis -f "${fpga}" -a instr 0x27 #select all columns -mimosis -f "${fpga}" -a reg 0x0584 0xff #select some rows -mimosis -f "${fpga}" -a instr 0x05 #INSTR set mask pulse -mimosis -f "${fpga}" -a instr 0x3e #INSTR unselect all pixels -mimosis -f "${fpga}" -a reg 0x4087 0x0 #unselect all pixels (register wise) - -# mimosis -f "${fpga}" -a instr 0x3e #INSTR unselect all pixels -# mimosis -f "${fpga}" -a reg 0x4087 0x0 #unselect all pixels (register wise) -# mimosis -f "${fpga}" -a instr 0x27 #select all columns -# mimosis -f "${fpga}" -a reg 0x0584 0xff #select some rows -# mimosis -f "${fpga}" -a instr 0x05 #INSTR set mask pulse -# mimosis -f "${fpga}" -a instr 0x3e #INSTR unselect all pixels -# mimosis -f "${fpga}" -a reg 0x4087 0x0 #unselect all pixels (register wise) diff --git a/trbnet/start.sh b/trbnet/start.sh index f628a46..efad7cd 100755 --- a/trbnet/start.sh +++ b/trbnet/start.sh @@ -29,5 +29,3 @@ trbcmd w 0xfe82 0xde05 0x100 #Mimosis reset echo "done" trbcmd i 0xffff - -bash -i -- 2.43.0