merge from origin master
This commit is contained in:
commit
f68d26de65
12
.gitignore
vendored
12
.gitignore
vendored
|
@ -3,6 +3,8 @@
|
|||
*.root
|
||||
*.bin
|
||||
|
||||
core.*
|
||||
|
||||
FSUDAQr
|
||||
FSUDAQ_Qt6
|
||||
test
|
||||
|
@ -22,16 +24,20 @@ DAQLock.dat
|
|||
DumpFSU2ROOT
|
||||
SettingsExplorer
|
||||
AggSeparator
|
||||
FSU2CAEN
|
||||
Bin2Root
|
||||
|
||||
data
|
||||
|
||||
splitpole.C
|
||||
splitpole.h
|
||||
Data
|
||||
raw_binary
|
||||
|
||||
*.d
|
||||
*.pcm
|
||||
|
||||
*.txt
|
||||
*.tar
|
||||
*.tar.gz
|
||||
*.BIN
|
||||
|
||||
*~
|
||||
*.autosave
|
||||
|
|
58
.vscode/settings.json
vendored
58
.vscode/settings.json
vendored
|
@ -82,39 +82,36 @@
|
|||
}
|
||||
],
|
||||
"files.associations": {
|
||||
"mainWindow.C": "cpp",
|
||||
"Scope.C": "cpp",
|
||||
"new": "cpp",
|
||||
"allocator": "cpp",
|
||||
"array": "cpp",
|
||||
"istream": "cpp",
|
||||
"ostream": "cpp",
|
||||
"sstream": "cpp",
|
||||
"limits": "cpp",
|
||||
"atomic": "cpp",
|
||||
"bit": "cpp",
|
||||
"*.tcc": "cpp",
|
||||
"bitset": "cpp",
|
||||
"*.C": "cpp",
|
||||
"*.pro": "makefile",
|
||||
"regex": "cpp",
|
||||
"cctype": "cpp",
|
||||
"chrono": "cpp",
|
||||
"clocale": "cpp",
|
||||
"cmath": "cpp",
|
||||
"codecvt": "cpp",
|
||||
"compare": "cpp",
|
||||
"concepts": "cpp",
|
||||
"condition_variable": "cpp",
|
||||
"cstdarg": "cpp",
|
||||
"cstddef": "cpp",
|
||||
"cstdint": "cpp",
|
||||
"cstdio": "cpp",
|
||||
"cstdlib": "cpp",
|
||||
"cstring": "cpp",
|
||||
"ctime": "cpp",
|
||||
"cwchar": "cpp",
|
||||
"cwctype": "cpp",
|
||||
"array": "cpp",
|
||||
"atomic": "cpp",
|
||||
"bit": "cpp",
|
||||
"*.tcc": "cpp",
|
||||
"bitset": "cpp",
|
||||
"charconv": "cpp",
|
||||
"chrono": "cpp",
|
||||
"codecvt": "cpp",
|
||||
"compare": "cpp",
|
||||
"concepts": "cpp",
|
||||
"condition_variable": "cpp",
|
||||
"cstdint": "cpp",
|
||||
"deque": "cpp",
|
||||
"list": "cpp",
|
||||
"map": "cpp",
|
||||
"set": "cpp",
|
||||
"string": "cpp",
|
||||
"unordered_map": "cpp",
|
||||
"unordered_set": "cpp",
|
||||
|
@ -129,38 +126,35 @@
|
|||
"optional": "cpp",
|
||||
"random": "cpp",
|
||||
"ratio": "cpp",
|
||||
"source_location": "cpp",
|
||||
"string_view": "cpp",
|
||||
"system_error": "cpp",
|
||||
"tuple": "cpp",
|
||||
"type_traits": "cpp",
|
||||
"utility": "cpp",
|
||||
"format": "cpp",
|
||||
"fstream": "cpp",
|
||||
"future": "cpp",
|
||||
"initializer_list": "cpp",
|
||||
"iomanip": "cpp",
|
||||
"iosfwd": "cpp",
|
||||
"iostream": "cpp",
|
||||
"istream": "cpp",
|
||||
"limits": "cpp",
|
||||
"mutex": "cpp",
|
||||
"new": "cpp",
|
||||
"numbers": "cpp",
|
||||
"ostream": "cpp",
|
||||
"semaphore": "cpp",
|
||||
"shared_mutex": "cpp",
|
||||
"span": "cpp",
|
||||
"sstream": "cpp",
|
||||
"stdexcept": "cpp",
|
||||
"stop_token": "cpp",
|
||||
"streambuf": "cpp",
|
||||
"thread": "cpp",
|
||||
"cinttypes": "cpp",
|
||||
"typeinfo": "cpp",
|
||||
"variant": "cpp",
|
||||
"qmainwindow": "cpp",
|
||||
"qchartview": "cpp",
|
||||
"qthread": "cpp",
|
||||
"qrandomgenerator": "cpp",
|
||||
"source_location": "cpp",
|
||||
"splitpole.C": "cpp",
|
||||
"forward_list": "cpp",
|
||||
"fstream": "cpp",
|
||||
"Analyzer.C": "cpp",
|
||||
"process_Run.C": "cpp",
|
||||
"EncoreAnalyzer.C": "cpp",
|
||||
"qfiledialog": "cpp"
|
||||
"variant": "cpp"
|
||||
}
|
||||
}
|
|
@ -20,7 +20,7 @@ struct FileInfo{
|
|||
|
||||
};
|
||||
|
||||
#define NMINARG 5
|
||||
#define NMINARG 4
|
||||
#define debug 0
|
||||
|
||||
//^#############################################################
|
||||
|
@ -32,14 +32,13 @@ int main(int argc, char **argv) {
|
|||
printf("=========================================\n");
|
||||
if (argc < NMINARG) {
|
||||
printf("Incorrect number of arguments:\n");
|
||||
printf("%s [timeWindow] [withTrace] [format] [inFile1] [inFile2] .... \n", argv[0]);
|
||||
printf("%s [timeWindow] [withTrace] [inFile1] [inFile2] .... \n", argv[0]);
|
||||
printf(" timeWindow : in ns, -1 = no event building \n");
|
||||
printf(" withTrace : 0 for no trace, 1 for trace \n");
|
||||
printf(" format : 0 for root, 1 for CoMPASS binary \n");
|
||||
printf(" Output file name is contructed from inFile1 \n");
|
||||
printf("\n");
|
||||
printf(" Example: %s -1 0 0 '\\ls -1 *001*.fsu' (no event build, no trace, no verbose)\n", argv[0]);
|
||||
printf(" %s 100 0 0 '\\ls -1 *001*.fsu' (event build with 100 ns, no trace, no verbose)\n", argv[0]);
|
||||
printf(" Example: %s -1 0 '\\ls -1 *001*.fsu' (no event build, no trace, no verbose)\n", argv[0]);
|
||||
printf(" %s 100 0 '\\ls -1 *001*.fsu' (event build with 100 ns, no trace, no verbose)\n", argv[0]);
|
||||
printf("\n\n");
|
||||
|
||||
return 1;
|
||||
|
@ -51,7 +50,7 @@ int main(int argc, char **argv) {
|
|||
long timeWindow = atoi(argv[1]);
|
||||
bool traceOn = atoi(argv[2]);
|
||||
// unsigned int debug = atoi(argv[3]);
|
||||
unsigned short format = atoi(argv[3]);
|
||||
// unsigned short format = atoi(argv[3]);
|
||||
unsigned int batchSize = 2* DEFAULT_HALFBUFFERSIZE;
|
||||
int nFile = argc - NMINARG + 1;
|
||||
TString inFileName[nFile];
|
||||
|
@ -67,13 +66,9 @@ int main(int argc, char **argv) {
|
|||
outFileName += "_" + ( timeWindow >= 0 ? std::to_string(timeWindow) : "single");
|
||||
|
||||
TString outFileFullName;
|
||||
if( format == 0 ){
|
||||
outFileFullName = outFileName + ".root";
|
||||
}else{
|
||||
outFileFullName = outFileName + ".bin";
|
||||
}
|
||||
outFileFullName = outFileName + ".root";
|
||||
|
||||
uint16_t header = 0; // for caen bin
|
||||
// uint16_t header = 0; // for caen bin
|
||||
|
||||
printf("-------> Out file name : %s \n", outFileFullName.Data());
|
||||
printf("========================================= Number of Files : %d \n", nFile);
|
||||
|
@ -94,6 +89,8 @@ int main(int argc, char **argv) {
|
|||
FSUReader * readerA = new FSUReader(inFileName[0].Data(), 1, 1);
|
||||
readerA->ScanNumBlock(0,0);
|
||||
if( readerA->GetOptimumBatchSize() > batchSize ) batchSize = readerA->GetOptimumBatchSize();
|
||||
//printf("Hit count : %7ld | opt. batch size : %7ld\n", readerA->GetTotalHitCount(), readerA->GetOptimumBatchSize());
|
||||
|
||||
FileInfo fileInfo = {inFileName[0].Data(), readerA->GetSN() * 1000 + readerA->GetFileOrder(), readerA->GetTotalHitCount()};
|
||||
fileList.push_back(fileInfo);
|
||||
totalHitCount += readerA->GetTotalHitCount();
|
||||
|
@ -101,7 +98,9 @@ int main(int argc, char **argv) {
|
|||
for( int i = 1; i < nFile; i++){
|
||||
FSUReader * readerB = new FSUReader(inFileName[i].Data(), 1, 1);
|
||||
readerB->ScanNumBlock(0,0);
|
||||
if( readerB->GetOptimumBatchSize() > batchSize ) batchSize = readerB->GetOptimumBatchSize();
|
||||
// if( readerB->GetOptimumBatchSize() > batchSize ) batchSize = readerB->GetOptimumBatchSize();
|
||||
batchSize = readerB->GetOptimumBatchSize();
|
||||
//printf("Hit count : %7ld | opt. batch size : %7ld\n", readerB->GetTotalHitCount(), readerB->GetOptimumBatchSize());
|
||||
|
||||
totalHitCount += readerB->GetTotalHitCount();
|
||||
fileInfo = {inFileName[i].Data(), readerB->GetSN() * 1000 + readerB->GetFileOrder(), readerB->GetTotalHitCount()};
|
||||
|
@ -147,39 +146,27 @@ int main(int argc, char **argv) {
|
|||
unsigned short traceLength[MAX_MULTI];
|
||||
short trace[MAX_MULTI][MAX_TRACE_LENGTH];
|
||||
|
||||
FILE * caen = nullptr;
|
||||
// //*====================================== create tree
|
||||
outRootFile = new TFile(outFileFullName, "recreate");
|
||||
tree = new TTree("tree", outFileFullName);
|
||||
|
||||
if( format == 0 ){
|
||||
// //*====================================== create tree
|
||||
outRootFile = new TFile(outFileFullName, "recreate");
|
||||
tree = new TTree("tree", outFileFullName);
|
||||
|
||||
tree->Branch("evID", &evID, "event_ID/l");
|
||||
tree->Branch("multi", &multi, "multi/i");
|
||||
tree->Branch("sn", sn, "sn[multi]/s");
|
||||
tree->Branch("ch", ch, "ch[multi]/s");
|
||||
tree->Branch("e", e, "e[multi]/s");
|
||||
tree->Branch("e2", e2, "e2[multi]/s");
|
||||
tree->Branch("e_t", e_t, "e_t[multi]/l");
|
||||
tree->Branch("e_f", e_f, "e_f[multi]/s");
|
||||
tree->Branch("traceLength", traceLength, "traceLength[multi]/s");
|
||||
|
||||
if( traceOn ) {
|
||||
tree->Branch("trace", trace,"trace[multi][MAX_TRACE_LENGTH]/S");
|
||||
tree->GetBranch("trace")->SetCompressionSettings(205);
|
||||
}
|
||||
}else{
|
||||
|
||||
caen = fopen(outFileFullName.Data(), "wb");
|
||||
if( caen == nullptr ){
|
||||
perror("Failed to open file");
|
||||
return -1;
|
||||
}
|
||||
tree->Branch("evID", &evID, "event_ID/l");
|
||||
tree->Branch("multi", &multi, "multi/i");
|
||||
tree->Branch("sn", sn, "sn[multi]/s");
|
||||
tree->Branch("ch", ch, "ch[multi]/s");
|
||||
tree->Branch("e", e, "e[multi]/s");
|
||||
tree->Branch("e2", e2, "e2[multi]/s");
|
||||
tree->Branch("e_t", e_t, "e_t[multi]/l");
|
||||
tree->Branch("e_f", e_f, "e_f[multi]/s");
|
||||
tree->Branch("traceLength", traceLength, "traceLength[multi]/s");
|
||||
|
||||
if( traceOn ) {
|
||||
tree->Branch("trace", trace,"trace[multi][MAX_TRACE_LENGTH]/S");
|
||||
tree->GetBranch("trace")->SetCompressionSettings(205);
|
||||
}
|
||||
|
||||
//*======================================= Open files
|
||||
printf("========================================= Open files & Build Events.\n");
|
||||
printf("========================================= Open files & reading 1st batch.\n");
|
||||
|
||||
const short nGroup = fileGroupList.size();
|
||||
std::vector<Hit> hitList[nGroup];
|
||||
|
@ -192,7 +179,7 @@ int main(int argc, char **argv) {
|
|||
fList.push_back( fileGroupList[i][j].fileName );
|
||||
}
|
||||
reader[i] = new FSUReader(fList, 1024, debug); // 1024 is the maximum event / agg.
|
||||
hitList[i] = reader[i]->ReadBatch(batchSize, debug );
|
||||
hitList[i] = reader[i]->ReadBatch(batchSize, traceOn, debug );
|
||||
reader[i]->PrintHitListInfo(&hitList[i], "hitList-" + std::to_string(reader[i]->GetSN()));
|
||||
ID[i] = 0;
|
||||
if( debug ) {
|
||||
|
@ -227,6 +214,7 @@ int main(int argc, char **argv) {
|
|||
std::vector<Hit> events;
|
||||
|
||||
unsigned long long hitProcessed = 0;
|
||||
printf("========================================= Start Building Events....\n");
|
||||
|
||||
do{
|
||||
|
||||
|
@ -241,7 +229,7 @@ int main(int argc, char **argv) {
|
|||
|
||||
//chekc if reached the end of hitList
|
||||
if( ID[ig] >= hitList[ig].size() ) {
|
||||
hitList[ig] = reader[ig]->ReadBatch(batchSize, debug + 1);
|
||||
hitList[ig] = reader[ig]->ReadBatch(batchSize, traceOn, debug + 1);
|
||||
if( debug ) reader[ig]->PrintHitListInfo( &hitList[ig], "hitList-" + std::to_string(ig));
|
||||
ID[ig] = 0;
|
||||
if( hitList[ig].size() == 0 ) continue;
|
||||
|
@ -251,8 +239,8 @@ int main(int argc, char **argv) {
|
|||
|
||||
do{
|
||||
|
||||
if( (long int)(hitList[ig].at(ID[ig]).timestamp - t0) <= timeWindow ){
|
||||
events.push_back(hitList[ig].at(ID[ig]));
|
||||
if( (long int)(hitList[ig][ID[ig]].timestamp - t0) <= timeWindow ){
|
||||
events.push_back(hitList[ig][ID[ig]]);
|
||||
ID[ig] ++;
|
||||
}else{
|
||||
break;
|
||||
|
@ -260,7 +248,7 @@ int main(int argc, char **argv) {
|
|||
|
||||
//check if reached the end of hitList
|
||||
if( ID[ig] >= hitList[ig].size() ) {
|
||||
hitList[ig] = reader[ig]->ReadBatch(batchSize, debug);
|
||||
hitList[ig] = reader[ig]->ReadBatch(batchSize, traceOn, debug);
|
||||
if( debug ) reader[ig]->PrintHitListInfo( &hitList[ig], "hitList-" + std::to_string(ig));
|
||||
ID[ig] = 0;
|
||||
if( hitList[ig].size() == 0 ) break;
|
||||
|
@ -291,6 +279,9 @@ int main(int argc, char **argv) {
|
|||
multi = events.size() ;
|
||||
if( events.size() >= MAX_MULTI ) {
|
||||
printf("\033[31m event %lld has size = %d > MAX_MULTI = %d \033[0m\n", evID, multi, MAX_MULTI);
|
||||
for( int po = 0 ; po < 10 ; po ++){
|
||||
events[po].Print();
|
||||
}
|
||||
multi = MAX_MULTI;
|
||||
}
|
||||
if( debug ) printf("=================================== filling data | %u \n", multi);
|
||||
|
@ -318,27 +309,10 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
}
|
||||
|
||||
if( format == 0 ){
|
||||
outRootFile->cd();
|
||||
tree->Fill();
|
||||
// tree->Write();
|
||||
}else{
|
||||
if( caen ) {
|
||||
|
||||
if( header == 0 ){
|
||||
header = 0xCAE1; // default to have the energy only
|
||||
if( events[0].energy2 > 0 ) header += 0x4;
|
||||
if( events[0].traceLength > 0 && traceOn ) header += 0x8;
|
||||
size_t dummy = fwrite(&header, 2, 1, caen);
|
||||
if( dummy != 1 ) printf("file write error.\n");
|
||||
}
|
||||
|
||||
for( size_t gg = 0; gg < events.size(); gg++ ){
|
||||
events[gg].WriteHitsToCAENBinary(caen, header);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
outRootFile->cd();
|
||||
tree->Fill();
|
||||
// tree->Write();
|
||||
|
||||
multi = 0;
|
||||
evID ++;
|
||||
|
||||
|
@ -363,7 +337,7 @@ int main(int argc, char **argv) {
|
|||
continue;
|
||||
}else{
|
||||
if( ID[i] >= hitList[i].size( )) {
|
||||
hitList[i] = reader[i]->ReadBatch(batchSize, debug);
|
||||
hitList[i] = reader[i]->ReadBatch(batchSize, traceOn, debug);
|
||||
ID[i] = 0;
|
||||
if( hitList[i].size() == 0 ) nFileFinished ++;
|
||||
}
|
||||
|
@ -373,7 +347,7 @@ int main(int argc, char **argv) {
|
|||
|
||||
}while( nFileFinished < nGroup);
|
||||
|
||||
if( format == 0 ) tree->Write();
|
||||
tree->Write();
|
||||
|
||||
uInt runEndTime = getTime_us();
|
||||
double runTime = (runEndTime - runStartTime) * 1e-6;
|
||||
|
@ -387,15 +361,12 @@ int main(int argc, char **argv) {
|
|||
printf(" total data duration = %.2f sec = %.2f min\n", tDuration_sec, tDuration_sec/60.);
|
||||
printf("========================================> saved to %s \n", outFileFullName.Data());
|
||||
|
||||
if( format == 0 ){
|
||||
TMacro info;
|
||||
info.AddLine(Form("tStart= %20llu ns",tStart));
|
||||
info.AddLine(Form(" tEnd= %20llu ns",tEnd));
|
||||
info.Write("info");
|
||||
outRootFile->Close();
|
||||
}else{
|
||||
fclose(caen);
|
||||
}
|
||||
TMacro info;
|
||||
info.AddLine(Form("tStart= %20llu ns",tStart));
|
||||
info.AddLine(Form(" tEnd= %20llu ns",tEnd));
|
||||
info.Write("info");
|
||||
outRootFile->Close();
|
||||
|
||||
|
||||
for( int i = 0; i < nGroup; i++) delete reader[i];
|
||||
delete [] reader;
|
||||
|
|
305
Aux/FSU2CAEN.cpp
Normal file
305
Aux/FSU2CAEN.cpp
Normal file
|
@ -0,0 +1,305 @@
|
|||
#include "fsuReader.h"
|
||||
|
||||
struct FileInfo{
|
||||
std::string fileName;
|
||||
int fileevID;
|
||||
unsigned long hitCount;
|
||||
int sn;
|
||||
int numCh;
|
||||
int runNum;
|
||||
};
|
||||
|
||||
#define minNARG 3
|
||||
|
||||
//^#############################################################
|
||||
//^#############################################################
|
||||
int main(int argc, char **argv) {
|
||||
|
||||
printf("=========================================\n");
|
||||
printf("=== *.fsu to CoMPASS bin ===\n");
|
||||
printf("=========================================\n");
|
||||
if (argc < minNARG) {
|
||||
printf("Incorrect number of arguments:\n");
|
||||
printf("%s [tar] [inFile1] [inFile2] .... \n", argv[0]);
|
||||
printf(" tar : output tar, 0 = no, 1 = yes \n");
|
||||
printf("\n");
|
||||
printf(" Example: %s 0 '\\ls -1 *001*.fsu'\n", argv[0]);
|
||||
printf("\n\n");
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
unsigned int debug = false;
|
||||
uInt runStartTime = getTime_us();
|
||||
|
||||
///============= read input
|
||||
// long timeWindow = atoi(argv[1]);
|
||||
// bool traceOn = atoi(argv[2]);
|
||||
bool tarFlag = atoi(argv[1]);
|
||||
unsigned int batchSize = 2* DEFAULT_HALFBUFFERSIZE;
|
||||
int nFile = argc - minNARG + 1;
|
||||
std::string inFileName[nFile];
|
||||
for( int i = 0 ; i < nFile ; i++){ inFileName[i] = argv[i+ minNARG - 1];}
|
||||
|
||||
printf("========================================= Number of Files : %d \n", nFile);
|
||||
for( int i = 0; i < nFile; i++) printf("%2d | %s \n", i, inFileName[i].c_str());
|
||||
printf("=========================================\n");
|
||||
printf(" Batch size = %d events/file\n", batchSize);
|
||||
// printf(" Out file name = %s \n", outFileName.c_str());
|
||||
printf(" Is tar output = %s \n", tarFlag ? "Yes" : "No");
|
||||
printf("========================================= Grouping files\n");
|
||||
|
||||
std::vector<std::vector<FileInfo>> fileGroupList; // fileName and evID = SN * 1000 + index
|
||||
std::vector<FileInfo> fileList;
|
||||
|
||||
unsigned long long int totalHitCount = 0;
|
||||
|
||||
FSUReader * readerA = new FSUReader(inFileName[0], 1, 1);
|
||||
readerA->ScanNumBlock(0,0);
|
||||
if( readerA->GetOptimumBatchSize() > batchSize ) batchSize = readerA->GetOptimumBatchSize();
|
||||
FileInfo fileInfo = {inFileName[0], readerA->GetSN() * 1000 + readerA->GetFileOrder(), readerA->GetTotalHitCount(), readerA->GetSN(), readerA->GetNumCh(), readerA->GetRunNum()};
|
||||
fileList.push_back(fileInfo);
|
||||
totalHitCount += readerA->GetTotalHitCount();
|
||||
|
||||
for( int i = 1; i < nFile; i++){
|
||||
FSUReader * readerB = new FSUReader(inFileName[i], 1, 1);
|
||||
readerB->ScanNumBlock(0,0);
|
||||
if( readerB->GetOptimumBatchSize() > batchSize ) batchSize = readerB->GetOptimumBatchSize();
|
||||
|
||||
totalHitCount += readerB->GetTotalHitCount();
|
||||
fileInfo = {inFileName[i], readerB->GetSN() * 1000 + readerB->GetFileOrder(), readerB->GetTotalHitCount(), readerB->GetSN(), readerB->GetNumCh(), readerB->GetRunNum()};
|
||||
|
||||
if( readerA->GetSN() == readerB->GetSN() ){
|
||||
fileList.push_back(fileInfo);
|
||||
}else{
|
||||
fileGroupList.push_back(fileList);
|
||||
fileList.clear();
|
||||
fileList.push_back(fileInfo);
|
||||
}
|
||||
|
||||
delete readerA;
|
||||
readerA = readerB;
|
||||
}
|
||||
fileGroupList.push_back(fileList);
|
||||
delete readerA;
|
||||
|
||||
printf("======================= total Hit Count : %llu\n", totalHitCount);
|
||||
|
||||
for( size_t i = 0; i < fileGroupList.size(); i++){
|
||||
printf("group ----- %ld \n", i);
|
||||
|
||||
//sort by evID
|
||||
std::sort(fileGroupList[i].begin(), fileGroupList[i].end(), [](const FileInfo & a, const FileInfo & b) {
|
||||
return a.fileevID < b.fileevID;
|
||||
});
|
||||
|
||||
for( size_t j = 0; j < fileGroupList[i].size(); j++){
|
||||
printf("%3ld | %8d | %9lu| %s \n", j, fileGroupList[i][j].fileevID, fileGroupList[i][j].hitCount, fileGroupList[i][j].fileName.c_str() );
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//*====================================== format output files
|
||||
|
||||
const short numFileGroup = fileGroupList.size();
|
||||
|
||||
FILE ** outFile[numFileGroup];
|
||||
|
||||
std::vector<std::string> outFileName[numFileGroup];
|
||||
std::vector<uint16_t> header[numFileGroup];
|
||||
std::vector<unsigned int> flags[numFileGroup];
|
||||
|
||||
for( int i = 0; i < numFileGroup; i++ ){
|
||||
outFile[i] = new FILE * [fileGroupList[i][0].numCh];
|
||||
for( int ch = 0; ch < fileGroupList[i][0].numCh; ch++ ){
|
||||
std::string dudu = "Data_CH" + std::to_string(ch) + "@DIGI_" + std::to_string(fileGroupList[i][0].sn) + "_run_" + std::to_string(fileGroupList[i][0].runNum) + ".BIN";
|
||||
// printf("|%s| \n", dudu.c_str());
|
||||
outFile[i][ch] = fopen(dudu.c_str(), "wb");
|
||||
outFileName[i].push_back(dudu);
|
||||
header[i].push_back(0);
|
||||
flags[i].push_back(0);
|
||||
}
|
||||
}
|
||||
|
||||
// std::string temp = inFileName[0];
|
||||
// size_t pos = temp.find('_');
|
||||
// pos = temp.find('_', pos + 1);
|
||||
// std::string outFile_prefix = temp.substr(0, pos);
|
||||
// std::string outFileName = outFile_prefix + ".BIN";
|
||||
|
||||
//*======================================= Open files
|
||||
printf("========================================= Open files & Build Events.\n");
|
||||
|
||||
const short nGroup = fileGroupList.size();
|
||||
std::vector<Hit> hitList[nGroup];
|
||||
|
||||
FSUReader ** reader = new FSUReader * [nGroup];
|
||||
ulong evID[nGroup];
|
||||
for( short i = 0; i < nGroup; i++){
|
||||
std::vector<std::string> fList;
|
||||
for( size_t j = 0; j < fileGroupList[i].size(); j++){
|
||||
fList.push_back( fileGroupList[i][j].fileName );
|
||||
}
|
||||
reader[i] = new FSUReader(fList, 600, debug);
|
||||
hitList[i] = reader[i]->ReadBatch(batchSize, debug );
|
||||
reader[i]->PrintHitListInfo(&hitList[i], "hitList-" + std::to_string(reader[i]->GetSN()));
|
||||
evID[i] = 0;
|
||||
if( debug ) {
|
||||
|
||||
for( size_t p = 0; p < 10; p ++ ){
|
||||
if( hitList[i].size() <= p ) break;
|
||||
hitList[i][p].Print();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
unsigned long long tStart = 0;
|
||||
unsigned long long tEnd = 0;
|
||||
|
||||
unsigned long long t0 = -1;
|
||||
short g0 = 0 ;
|
||||
int nFileFinished = 0;
|
||||
unsigned long long hitProcessed = 0;
|
||||
|
||||
do{
|
||||
|
||||
// find the earlist time
|
||||
t0 = -1;
|
||||
for( short i = 0; i < nGroup; i++){
|
||||
|
||||
if( hitList[i].size() == 0 ) continue;
|
||||
|
||||
//chekc if reached the end of hitList
|
||||
if( evID[i] >= hitList[i].size() ) {
|
||||
hitList[i] = reader[i]->ReadBatch(batchSize, debug + 1);
|
||||
if( debug ) reader[i]->PrintHitListInfo( &hitList[i], "hitList-" + std::to_string(i));
|
||||
evID[i] = 0;
|
||||
if( hitList[i].size() == 0 ) continue;
|
||||
}
|
||||
|
||||
if( hitList[i][evID[i]].timestamp < t0 ) {
|
||||
t0 = hitList[i][evID[i]].timestamp;
|
||||
g0 = i;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Set file header
|
||||
int p_ch = hitList[g0][evID[g0]].ch; // present ch
|
||||
|
||||
if( header[g0][p_ch] == 0 ) {
|
||||
header[g0][p_ch] = 0xCAE1;
|
||||
if( hitList[g0][evID[g0]].energy2 > 0 ) header[g0][p_ch] += 4;
|
||||
if( hitList[g0][evID[g0]].traceLength > 0 ) header[g0][p_ch] += 8;
|
||||
if( hitList[g0][evID[g0]].pileUp ) flags[g0][p_ch] += 0x8000;
|
||||
if( hitList[g0][evID[g0]].fineTime > 0 ) flags[g0][p_ch] += 0x4000;
|
||||
|
||||
fwrite(&(header[g0][p_ch]), 2, 1, outFile[g0][p_ch]);
|
||||
}
|
||||
|
||||
hitList[g0][evID[g0]].WriteHitsToCAENBinary(outFile[g0][p_ch], header[g0][p_ch]);
|
||||
|
||||
// fwrite(&(hitList[g0][evID[g0]].sn), 2, 1, outFile);
|
||||
// fwrite(&(hitList[g0][evID[g0]].ch), 2, 1, outFile);
|
||||
// unsigned psTimestamp = hitList[g0][evID[g0]].timestamp * 1000 + hitList[g0][evID[g0]].fineTime;
|
||||
// fwrite(&(psTimestamp), 8, 1, outFile);
|
||||
// fwrite(&(hitList[g0][evID[g0]].energy), 2, 1, outFile);
|
||||
// if( hitList[g0][evID[g0]].energy2 > 0 ) fwrite(&(hitList[g0][evID[g0]].energy2), 2, 1, outFile);
|
||||
// fwrite(&(flags), 4, 1, outFile);
|
||||
// if( hitList[g0][evID[g0]].traceLength > 0 ){
|
||||
// char waveCode = 1;
|
||||
// fwrite(&(waveCode), 1, 1, outFile);
|
||||
// fwrite(&(hitList[g0][evID[g0]].traceLength), 4, 1, outFile);
|
||||
|
||||
// for( int i = 0; i < hitList[g0][evID[g0]].traceLength; i++ ){
|
||||
// fwrite(&(hitList[g0][evID[g0]].trace[i]), 2, 1, outFile);
|
||||
// }
|
||||
// }
|
||||
|
||||
evID[g0]++;
|
||||
if( hitProcessed == 0) tStart = hitList[g0][evID[g0]].timestamp;
|
||||
hitProcessed ++;
|
||||
if( hitProcessed % 10000 == 0 ) printf("hit Porcessed %llu/%llu hit....%.2f%%\n\033[A\r", hitProcessed, totalHitCount, hitProcessed*100./totalHitCount);
|
||||
|
||||
if( hitProcessed == totalHitCount -1 ) tEnd = hitList[g0][evID[g0]].timestamp;
|
||||
|
||||
//*=============
|
||||
nFileFinished = 0;
|
||||
for( int i = 0 ; i < nGroup; i++) {
|
||||
if( hitList[i].size() == 0 ) {
|
||||
nFileFinished ++;
|
||||
continue;
|
||||
}else{
|
||||
if( evID[i] >= hitList[i].size( )) {
|
||||
hitList[i] = reader[i]->ReadBatch(batchSize, debug);
|
||||
evID[i] = 0;
|
||||
if( hitList[i].size() == 0 ) nFileFinished ++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if( debug > 1 ) printf("========== nFileFinished : %d\n", nFileFinished);
|
||||
|
||||
}while( nFileFinished < nGroup);
|
||||
|
||||
uInt runEndTime = getTime_us();
|
||||
double runTime = (runEndTime - runStartTime) * 1e-6;
|
||||
printf("========================================= finished.\n");
|
||||
printf(" event building time = %.2f sec = %.2f min\n", runTime, runTime/60.);
|
||||
printf(" total hit = %llu \n", hitProcessed);
|
||||
double tDuration_sec = (tEnd - tStart) * 1e-9;
|
||||
printf(" first timestamp = %20llu ns\n", tStart);
|
||||
printf(" last timestamp = %20llu ns\n", tEnd);
|
||||
printf(" total data duration = %.2f sec = %.2f min\n", tDuration_sec, tDuration_sec/60.);
|
||||
|
||||
for( int i = 0; i < nGroup; i++) delete reader[i];
|
||||
delete [] reader;
|
||||
|
||||
//============================== delete empty files and close FILE
|
||||
std::vector<std::string> nonEmptyFileList;
|
||||
|
||||
printf("================= Removing Empty Files ....\n");
|
||||
printf("============================> saved to ....");
|
||||
|
||||
if( tarFlag == false ) printf("\n");
|
||||
|
||||
for( int i = 0; i < numFileGroup; i++ ){
|
||||
for( int ch = 0; ch < fileGroupList[i][0].numCh; ch++){
|
||||
if( ftell(outFile[i][ch]) == 0 ){
|
||||
int dummy = std::system(("rm -f " + outFileName[i][ch]).c_str());
|
||||
// printf("Remove %s.\n", outFileName[i][ch].c_str());
|
||||
}else{
|
||||
nonEmptyFileList.push_back(outFileName[i][ch]);
|
||||
if( tarFlag == false ) printf("%s\n", outFileName[i][ch].c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( tarFlag ){
|
||||
std::string tarFileName = "run_" + std::to_string(fileGroupList[0][0].runNum) + ".tar.gz";
|
||||
|
||||
printf("%s\n", tarFileName.c_str());
|
||||
printf("============================> tar.gz the BIN\n");
|
||||
std::string command = "tar -czf " + tarFileName + " ";
|
||||
for( size_t i = 0; i < nonEmptyFileList.size(); i++ ){
|
||||
command += nonEmptyFileList[i] + " ";
|
||||
}
|
||||
int result = std::system(command.c_str());
|
||||
|
||||
if (result == 0) {
|
||||
printf("Archive created successfully: %s\n", tarFileName.c_str());
|
||||
for( size_t i = 0; i < nonEmptyFileList.size(); i++ ){
|
||||
int dummy = std::system(("rm -f " + nonEmptyFileList[i]).c_str());
|
||||
// printf("Remove %s.\n", nonEmptyFileList[i].c_str());
|
||||
}
|
||||
} else {
|
||||
printf("Error creating archive\n");
|
||||
}
|
||||
}
|
||||
|
||||
printf("============================================== end of program\n");
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
18
Aux/Makefile
18
Aux/Makefile
|
@ -5,8 +5,8 @@
|
|||
|
||||
CC = g++
|
||||
|
||||
#COPTS = -fPIC -DLINUX -O2 -std=c++17 -lpthread
|
||||
COPTS = -fPIC -DLINUX -g -O0 -Wall -std=c++17 -lpthread
|
||||
COPTS = -fPIC -DLINUX -O2 -std=c++17 -lpthread
|
||||
# COPTS = -fPIC -DLINUX -g -O0 -Wall -std=c++17 -lpthread
|
||||
|
||||
CAENLIBS = -lCAENDigitizer -lCAENVME
|
||||
|
||||
|
@ -14,7 +14,7 @@ ROOTLIBS = `root-config --cflags --glibs`
|
|||
|
||||
OBJS = ClassDigitizer.o MultiBuilder.o ClassInfluxDB.o
|
||||
|
||||
ALL = test EventBuilder DataReader DumpFSU2ROOT SettingsExplorer
|
||||
ALL = test EventBuilder DataReader DumpFSU2ROOT SettingsExplorer FSU2CAEN
|
||||
|
||||
#########################################################################
|
||||
|
||||
|
@ -34,7 +34,7 @@ ClassInfluxDB.o : ../ClassInfluxDB.cpp ../ClassInfluxDB.h
|
|||
|
||||
test : test.cpp ../ClassDigitizer.o ../MultiBuilder.o ../ClassInfluxDB.o
|
||||
@echo "--------- making test"
|
||||
$(CC) $(COPTS) -o test test.cpp ../ClassDigitizer.o ../MultiBuilder.o ../ClassInfluxDB.o $(CAENLIBS) $(ROOTLIBS) -lcurl
|
||||
$(CC) -fPIC -DLINUX -O0 -std=c++17 -lpthread -g -o test test.cpp ../ClassDigitizer.o ../MultiBuilder.o ../ClassInfluxDB.o $(CAENLIBS) $(ROOTLIBS) -lcurl
|
||||
|
||||
# test_indep : test_indep.cpp ../RegisterAddress.h ../macro.h
|
||||
# @echo "--------- making test_indep"
|
||||
|
@ -44,17 +44,13 @@ DataReader : DataReaderScript.cpp ../ClassData.h MultiBuilder.o
|
|||
@echo "--------- making DataReader"
|
||||
$(CC) $(COPTS) -o DataReader DataReaderScript.cpp ../ClassData.h MultiBuilder.o
|
||||
|
||||
# EventBuilder_old : EventBuilder_old.cpp ../ClassData.h MultiBuilder.o fsuReader.h
|
||||
# @echo "--------- making EventBuilder"
|
||||
# $(CC) $(COPTS) -o EventBuilder_old EventBuilder_old.cpp MultiBuilder.o $(ROOTLIBS)
|
||||
|
||||
EventBuilder : EventBuilder.cpp ../ClassData.h fsuReader.h ../Hit.h
|
||||
@echo "--------- making EventBuilder"
|
||||
$(CC) $(COPTS) -o EventBuilder EventBuilder.cpp $(ROOTLIBS)
|
||||
|
||||
# EventBuilderNoTrace : EventBuilderNoTrace.cpp ../ClassData.h fsuReader.h ../Hit.h
|
||||
# @echo "--------- making EventBuilderNoTrace"
|
||||
# $(CC) $(COPTS) -o EventBuilderNoTrace EventBuilderNoTrace.cpp $(ROOTLIBS)
|
||||
FSU2CAEN : FSU2CAEN.cpp ../ClassData.h fsuReader.h ../Hit.h
|
||||
@echo "--------- making FSU2CAEN"
|
||||
$(CC) $(COPTS) -o FSU2CAEN FSU2CAEN.cpp
|
||||
|
||||
DumpFSU2ROOT : DumpFSU2ROOT.cpp ../ClassData.h MultiBuilder.o
|
||||
@echo "--------- making DumpFSU2ROOT"
|
||||
|
|
|
@ -37,18 +37,16 @@ With this approach, it is guaranteed that the output hitList_A is always time-so
|
|||
This defines the EventBuilder. The arguments are
|
||||
|
||||
```sh
|
||||
./EventBuilder [timeWindow] [withTrace] [verbose] [batchSize] [inFile1] [inFile2] ....
|
||||
./EventBuilder [timeWindow] [withTrace] [inFile1] [inFile2] ....
|
||||
timeWindow : in ns, -1 = no event building
|
||||
withTrace : 0 for no trace, 1 for trace
|
||||
verbose : > 0 for debug
|
||||
batchSize : the size of hit in a batch
|
||||
Output file name is contructed from inFile1
|
||||
```
|
||||
|
||||
as an example,
|
||||
|
||||
```sh
|
||||
/EventBuilder 0 0 0 1000000 '\ls -1 test_001*.fsu'
|
||||
/EventBuilder 0 0'\ls -1 test_001*.fsu'
|
||||
```
|
||||
|
||||
setting the timeWindow to be -1, will split out a timesorted Hit.
|
||||
|
@ -115,6 +113,16 @@ Evenbuilder output is standard information, an example structure is
|
|||
*............................................................................*
|
||||
```
|
||||
|
||||
# FSU2CAEN.cpp
|
||||
|
||||
This convert the *.fsu to Data_CHXX@DIGI_YYYYY_run_ZZ.BIN. the BIN is CoMPASS format and could be useful for couple with existing analysis routine.
|
||||
|
||||
|
||||
```sh
|
||||
./FSU2CAEN [tarFlag] [inFile1] [inFile2] ....
|
||||
targFlag : if 1, tar ball all output files.
|
||||
```
|
||||
|
||||
|
||||
# SettingsExplorer.cpp
|
||||
|
||||
|
|
|
@ -64,13 +64,14 @@ void keyPressCommand(){
|
|||
if( RegList[i].GetRWType() == RW::ReadONLY ) typeStr = "R ";
|
||||
if( RegList[i].GetRWType() == RW::WriteONLY ) typeStr = " W";
|
||||
|
||||
unsigned int value = digi->GetSettingFromMemory(RegList[i], 0);
|
||||
|
||||
printf("%2d | 0x%04X %30s %s 0x%08X = %u\n", i,
|
||||
printf("%2d | 0x%04X %30s %s 0x%08X = %10u\n", i,
|
||||
RegList[i].GetAddress(),
|
||||
RegList[i].GetNameChar(),
|
||||
typeStr.c_str(),
|
||||
digi->GetSettingFromMemory(RegList[i], 0),
|
||||
digi->GetSettingFromMemory(RegList[i], 0));
|
||||
value,
|
||||
value);
|
||||
}
|
||||
|
||||
std::string input = "-1";
|
||||
|
@ -143,12 +144,15 @@ void keyPressCommand(){
|
|||
|
||||
RegList[i].ActualAddress(ch);
|
||||
|
||||
printf("%2d | 0x%04X %30s %s 0x%08X = %u\n", i,
|
||||
unsigned int value = digi->GetSettingFromMemory(RegList[i], ch);
|
||||
|
||||
printf("%2d | 0x%04X %30s %s 0x%08X = %10u : %d\n", i,
|
||||
RegList[i].GetAddress(),
|
||||
RegList[i].GetNameChar(),
|
||||
typeStr.c_str(),
|
||||
digi->GetSettingFromMemory(RegList[i], ch),
|
||||
digi->GetSettingFromMemory(RegList[i], ch));
|
||||
value,
|
||||
value,
|
||||
value * abs(RegList[i].GetPartialStep()));
|
||||
}
|
||||
|
||||
do{
|
||||
|
|
274
Aux/SplitPolePlotter.C
Normal file
274
Aux/SplitPolePlotter.C
Normal file
|
@ -0,0 +1,274 @@
|
|||
#ifndef SPLITPOLEPLOTTER
|
||||
#define SPLITPOLEPLOTTER
|
||||
|
||||
#include "TFile.h"
|
||||
#include "TChain.h"
|
||||
#include "TH1F.h"
|
||||
#include "TTreeReader.h"
|
||||
#include "TTreeReaderValue.h"
|
||||
#include "TTreeReaderArray.h"
|
||||
#include "TClonesArray.h"
|
||||
#include "TGraph.h"
|
||||
#include "TCutG.h"
|
||||
#include "TH2.h"
|
||||
#include "TCanvas.h"
|
||||
#include "TStyle.h"
|
||||
#include "TStopwatch.h"
|
||||
#include "TMath.h"
|
||||
|
||||
#include "vector"
|
||||
#include "../analyzers/SplitPoleHit.h"
|
||||
|
||||
|
||||
namespace ChMap{
|
||||
|
||||
const short ScinR = 0;
|
||||
const short ScinL = 1;
|
||||
const short dFR = 9;
|
||||
const short dFL = 8;
|
||||
const short dBR = 11;
|
||||
const short dBL = 10;
|
||||
const short Cathode = 7;
|
||||
const short AnodeF = 13;
|
||||
const short AnodeB = 15;
|
||||
|
||||
};
|
||||
|
||||
const double c = 299.792458; // mm/ns
|
||||
const double pi = M_PI;
|
||||
const double deg2rad = pi/180.;
|
||||
|
||||
SplitPoleHit hit;
|
||||
|
||||
TH2F * PID;
|
||||
TH2F * coin;
|
||||
|
||||
TH1F * hMulti;
|
||||
|
||||
TH1F * hF;
|
||||
TH1F * hB;
|
||||
TH1F * hXavg;
|
||||
|
||||
TH2F * hFocal;
|
||||
|
||||
TH2F * hXavg_Q;
|
||||
TH2F * hXavg_Theta;
|
||||
|
||||
TH2F * hRay;
|
||||
TH1F * hEx;
|
||||
|
||||
TH2F * hEx_Multi;
|
||||
|
||||
ULong64_t t1, t2;
|
||||
|
||||
#define XMIN -200
|
||||
#define XMAX 200
|
||||
|
||||
//^###########################################
|
||||
|
||||
void SplitPolePlotter(TChain *tree, TCutG * pidCut = nullptr, double rhoOffset = 0, double rhoScaling = 1, bool isFSUDAQ = true){
|
||||
|
||||
printf("#####################################################################\n");
|
||||
printf("################# SplitPolePlotter.C ####################\n");
|
||||
printf("#####################################################################\n");
|
||||
|
||||
TObjArray * fileList = tree->GetListOfFiles();
|
||||
printf("\033[0;31m========================================== Number of Files : %2d\n",fileList->GetEntries());
|
||||
fileList->Print();
|
||||
printf("========================================== Number of Files : %2d\033[0m\n",fileList->GetEntries());
|
||||
|
||||
printf("///////////////////////////////////////////////////////////////////\n");
|
||||
printf(" Total Number of entries : %llu \n", tree->GetEntries());
|
||||
printf("///////////////////////////////////////////////////////////////////\n");
|
||||
|
||||
if( tree->GetEntries() == 0 ) {
|
||||
printf("========= no events. Abort.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
//*====================================================== histograms
|
||||
|
||||
coin = new TH2F("hCoin", "Coincident ", 16, 0, 16, 16, 0, 16);
|
||||
hMulti = new TH1F("hMulti", "Multiplicity", 16, 0, 16);
|
||||
|
||||
if( isFSUDAQ ){
|
||||
PID = new TH2F("hPID", "PID; Scin_X ; AnodeB", 200, 0, 20000, 100, 0, 40000);
|
||||
hXavg_Q = new TH2F("hXavg_Q", "Xavg vs Q ", 200, XMIN, XMAX, 200, 0, 40000);
|
||||
}else{
|
||||
PID = new TH2F("hPID", "PID; Scin_X ; AnodeB", 200, 0, 4000, 100, 0, 5000);
|
||||
hXavg_Q = new TH2F("hXavg_Q", "Xavg vs Q ", 200, XMIN, XMAX, 200, 0, 5000);
|
||||
}
|
||||
|
||||
|
||||
hF = new TH1F("hF", "Front delay line position", 600, XMIN, XMAX);
|
||||
hB = new TH1F("hB", "Back delay line position", 600, XMIN, XMAX);
|
||||
hXavg = new TH1F("hAvg", "Xavg", 600, XMIN, XMAX);
|
||||
|
||||
hFocal = new TH2F("hFocal", "Front vs Back ", 200, XMIN, XMAX, 200, XMIN, XMAX);
|
||||
hXavg_Theta = new TH2F("hXavg_Theta", "Xavg vs Theta ", 200, XMIN, XMAX, 200, 0.5, 1.4);
|
||||
|
||||
hRay = new TH2F("hRay", "Ray plot", 400, XMIN, XMAX, 400, -50, 50);
|
||||
|
||||
hEx = new TH1F("hEx", "Ex; Ex [MeV]; count/10 keV", 600, -1, 5);
|
||||
|
||||
hEx_Multi = new TH2F("hEx_Multi", "Ex vs Multi; Ex; Multi", 600, -1, 5, 16, 0, 16);
|
||||
|
||||
hit.SetMassTablePath("../analyzers/mass20.txt");
|
||||
hit.CalConstants("12C", "d", "p", 16, 18); // 80MeV, 5 deg
|
||||
hit.CalZoffset(0.750); // 1.41 T
|
||||
|
||||
t1 = 0;
|
||||
t2 = 0;
|
||||
|
||||
|
||||
//*====================================================== Tree Reader
|
||||
TTreeReader reader(tree);
|
||||
|
||||
TTreeReaderValue<ULong64_t> evID = {reader, "evID"};
|
||||
TTreeReaderValue<UInt_t> multi = {reader, "multi"};
|
||||
TTreeReaderArray<UShort_t> sn = {reader, "sn"};
|
||||
TTreeReaderArray<UShort_t> ch = {reader, "ch"};
|
||||
TTreeReaderArray<UShort_t> e = {reader, "e"};
|
||||
TTreeReaderArray<UShort_t> e2 = {reader, "e2"};
|
||||
TTreeReaderArray<ULong64_t> e_t = {reader, "e_t"};
|
||||
TTreeReaderArray<UShort_t> e_f = {reader, "e_f"};
|
||||
|
||||
ULong64_t NumEntries = tree->GetEntries();
|
||||
|
||||
//^###########################################################
|
||||
//^ * Process
|
||||
//^###########################################################
|
||||
printf("############################################### Processing...\n");
|
||||
fflush(stdout); // flush out any printf
|
||||
|
||||
ULong64_t processedEntries = 0;
|
||||
float Frac = 0.1;
|
||||
TStopwatch StpWatch;
|
||||
StpWatch.Start();
|
||||
|
||||
while (reader.Next()) {
|
||||
|
||||
// if( processedEntries > 10 ) break;
|
||||
// printf("============== %5llu | multi : %d (%zu) \n", processedEntries, multi.Get()[0], sn.GetSize());
|
||||
// for( int i = 0; i < multi.Get()[0]; i++ ){
|
||||
// printf(" %d | %5d %2d %7d %10llu\n", i, sn[i], ch[i], e[i], e_t[i]);
|
||||
// }
|
||||
|
||||
hit.ClearData();
|
||||
hMulti->Fill(*multi);
|
||||
|
||||
// if( *multi != 9 ) continue;
|
||||
|
||||
for( int i = 0; i < *multi; i++){
|
||||
|
||||
t2 = e_t[i];
|
||||
if( t2 < t1 ) printf("entry %lld-%d, timestamp is not in order. %llu, %llu\n", processedEntries, i, t2, t1);
|
||||
if( i == 0 ) t1 = e_t[i];
|
||||
|
||||
// if( e[i] == 65535 ) continue;
|
||||
|
||||
if( ch[i] == ChMap::ScinR ) {hit.eSR = e[i]; hit.tSR = e_t[i] + e_f[i]/1000;}
|
||||
if( ch[i] == ChMap::ScinL ) {hit.eSL = e[i]; hit.tSL = e_t[i] + e_f[i]/1000;}
|
||||
if( ch[i] == ChMap::dFR ) {hit.eFR = e[i]; hit.tFR = e_t[i] + e_f[i]/1000;}
|
||||
if( ch[i] == ChMap::dFL ) {hit.eFL = e[i]; hit.tFL = e_t[i] + e_f[i]/1000;}
|
||||
if( ch[i] == ChMap::dBR ) {hit.eBR = e[i]; hit.tBR = e_t[i] + e_f[i]/1000;}
|
||||
if( ch[i] == ChMap::dBL ) {hit.eBL = e[i]; hit.tBL = e_t[i] + e_f[i]/1000;}
|
||||
if( ch[i] == ChMap::Cathode ) {hit.eCath = e[i]; hit.tCath = e_t[i] + e_f[i]/1000;}
|
||||
if( ch[i] == ChMap::AnodeF ) {hit.eAF = e[i]; hit.tAF = e_t[i] + e_f[i]/1000;}
|
||||
if( ch[i] == ChMap::AnodeB ) {hit.eAB = e[i]; hit.tAB = e_t[i] + e_f[i]/1000;}
|
||||
|
||||
for( int j = i+1; j < sn.GetSize(); j++){
|
||||
coin->Fill(ch[i], ch[j]);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int dQ = hit.eAB; // delta Q
|
||||
unsigned int Qt = hit.eSL; // total Q
|
||||
|
||||
if( Qt > 0 && dQ > 0 ) {
|
||||
PID->Fill(Qt, dQ);
|
||||
}
|
||||
|
||||
//=============== PID gate cut
|
||||
if( pidCut ){
|
||||
if( !pidCut->IsInside(Qt, dQ) ) continue;
|
||||
}
|
||||
|
||||
hit.CalData(2);
|
||||
|
||||
if( hit.theta > 1.2 || 0.5 > hit.theta ) continue;
|
||||
|
||||
if( (!TMath::IsNaN(hit.x1) || !TMath::IsNaN(hit.x2)) ) {
|
||||
hFocal->Fill(hit.x1, hit.x2);
|
||||
hF->Fill(hit.x1);
|
||||
hB->Fill(hit.x2);
|
||||
hXavg->Fill(hit.xAvg);
|
||||
|
||||
hXavg_Q->Fill(hit.xAvg, dQ);
|
||||
hXavg_Theta->Fill( hit.xAvg, hit.theta);
|
||||
|
||||
for( int i = 0; i < 400; i++){
|
||||
double z = -50 + 100/400.*i;
|
||||
|
||||
double x = (z/42.8625 + 0.5)* ( hit.x2-hit.x1) + hit.x1;
|
||||
|
||||
hRay->Fill(x,z);
|
||||
}
|
||||
|
||||
double ex = hit.Rho2Ex( ((hit.xAvg - rhoOffset)/1000/rhoScaling + hit.GetRho0() ) );
|
||||
//if( XMIN < hit.xAvg && hit.xAvg < XMAX) printf("x1 : %6.2f, x2 : %6.2f, xAvg %6.2f cm , ex : %f \n", hit.x1, hit.x2, hit.xAvg, ex);
|
||||
hEx->Fill(ex);
|
||||
|
||||
hEx_Multi->Fill(ex, *multi);
|
||||
}
|
||||
|
||||
//*============================================ Progress Bar
|
||||
processedEntries ++;
|
||||
if (processedEntries >= NumEntries*Frac - 1 ) {
|
||||
TString msg; msg.Form("%llu", NumEntries/1000);
|
||||
int len = msg.Sizeof();
|
||||
printf(" %3.0f%% (%*llu/%llu k) processed in %6.1f sec | expect %6.1f sec\n",
|
||||
Frac*100, len, processedEntries/1000,NumEntries/1000,StpWatch.RealTime(), StpWatch.RealTime()/Frac);
|
||||
fflush(stdout);
|
||||
StpWatch.Start(kFALSE);
|
||||
Frac += 0.1;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
//^###########################################################
|
||||
//^ * Plot
|
||||
//^###########################################################
|
||||
TCanvas * canvas = new TCanvas("cc", "Split-Pole", 2500, 1000);
|
||||
|
||||
gStyle->SetOptStat("neiou");
|
||||
|
||||
canvas->Divide(5, 2);
|
||||
|
||||
canvas->cd(1); {
|
||||
PID->Draw("colz");
|
||||
if( pidCut ) pidCut->Draw("same");
|
||||
}
|
||||
|
||||
canvas->cd(2); hRay->Draw("colz");
|
||||
|
||||
canvas->cd(3); hF->Draw();
|
||||
canvas->cd(4); hB->Draw();
|
||||
|
||||
canvas->cd(5); hXavg_Q->Draw("colz");
|
||||
|
||||
canvas->cd(6); hXavg->Draw("colz");
|
||||
|
||||
canvas->cd(7); hEx->Draw();
|
||||
|
||||
//canvas->cd(8); coin->Draw("colz");
|
||||
canvas->cd(8); hEx_Multi->Draw("colz");
|
||||
|
||||
canvas->cd(9); canvas->cd(9)->SetLogy(); hMulti->Draw();
|
||||
|
||||
canvas->cd(10); hXavg_Theta->Draw("colz");
|
||||
|
||||
}
|
||||
|
||||
#endif
|
194
Aux/SplitPolePlotter_MT.C
Normal file
194
Aux/SplitPolePlotter_MT.C
Normal file
|
@ -0,0 +1,194 @@
|
|||
#include <TROOT.h>
|
||||
#include "TTreeReader.h"
|
||||
#include "TTreeReaderValue.h"
|
||||
#include "TTreeReaderArray.h"
|
||||
#include <ROOT/TTreeProcessorMP.hxx>
|
||||
#include <ROOT/TTreeProcessorMT.hxx>
|
||||
#include "ROOT/TProcessExecutor.hxx"
|
||||
#include "ROOT/TThreadedObject.hxx"
|
||||
|
||||
#include "TH2F.h"
|
||||
#include "TH1F.h"
|
||||
#include "TCutG.h"
|
||||
#include "TCanvas.h"
|
||||
|
||||
#include "SplitPolePlotter.C"
|
||||
#include "../analyzers/SplitPoleHit.h"
|
||||
|
||||
|
||||
void SplotPolePlotter_MT(TChain * chain, const int nThread, TCutG * pidCut = nullptr, double rhoOffset = 0, double rhoScaling = 1, bool isFSUDAQ = true){
|
||||
|
||||
//^====================== Thread Object, destoryed when merge
|
||||
ROOT::TThreadedObject<TH2F> pCoin("hCoin", "Coincident ", 16, 0, 16, 16, 0, 16);
|
||||
ROOT::TThreadedObject<TH1F> phMulti("hMulti", "Multiplicity", 16, 0, 16);
|
||||
ROOT::TThreadedObject<TH2F> pPID("hPID", "PID; Scin_X ; AnodeB", 200, 0, 20000, 100, 0, isFSUDAQ ? 40000 : 5000);
|
||||
ROOT::TThreadedObject<TH2F> phXavg_Q("hXavg_Q", "Xavg vs Q ", 200, XMIN, XMAX, 200, 0, isFSUDAQ ? 40000 : 5000);
|
||||
ROOT::TThreadedObject<TH1F> phF("hF", "Front delay line position", 600, XMIN, XMAX);
|
||||
ROOT::TThreadedObject<TH1F> phB("hB", "Back delay line position", 600, XMIN, XMAX);
|
||||
ROOT::TThreadedObject<TH1F> phXavg("hAvg", "Xavg", 600, XMIN, XMAX);
|
||||
ROOT::TThreadedObject<TH2F> phFocal("hFocal", "Front vs Back ", 200, XMIN, XMAX, 200, XMIN, XMAX);
|
||||
ROOT::TThreadedObject<TH2F> phXavg_Theta("hXavg_Theta", "Xavg vs Theta ", 200, XMIN, XMAX, 200, 0.5, 1.4);
|
||||
ROOT::TThreadedObject<TH2F> phRay("hRay", "Ray plot", 400, XMIN, XMAX, 400, -50, 50);
|
||||
ROOT::TThreadedObject<TH1F> phEx("hEx", "Ex; Ex [MeV]; count/10 keV", 600, -1, 5);
|
||||
ROOT::TThreadedObject<TH2F> phEx_Multi("hEx_Multi", "Ex vs Multi; Ex; Multi", 600, -1, 5, 16, 0, 16);
|
||||
|
||||
|
||||
//^==================== TTreeProcessorMT
|
||||
ROOT::EnableImplicitMT(nThread);
|
||||
|
||||
std::vector<std::string_view> fileList_view;
|
||||
std::vector<std::string> fileList;
|
||||
for( int k = 0; k < chain->GetNtrees(); k++){
|
||||
fileList_view.push_back(chain->GetListOfFiles()->At(k)->GetTitle());
|
||||
fileList.push_back(chain->GetListOfFiles()->At(k)->GetTitle());
|
||||
}
|
||||
ROOT::TTreeProcessorMT tp(fileList_view, "tree");
|
||||
// tp.SetTasksPerWorkerHint(1);
|
||||
|
||||
std::mutex mutex;
|
||||
|
||||
int count = 0;
|
||||
|
||||
//^======================= Define process
|
||||
auto ProcessTask = [&](TTreeReader &reader){
|
||||
|
||||
TTreeReaderValue<ULong64_t> evID = {reader, "evID"};
|
||||
TTreeReaderValue<UInt_t> multi = {reader, "multi"};
|
||||
TTreeReaderArray<UShort_t> sn = {reader, "sn"};
|
||||
TTreeReaderArray<UShort_t> ch = {reader, "ch"};
|
||||
TTreeReaderArray<UShort_t> e = {reader, "e"};
|
||||
TTreeReaderArray<UShort_t> e2 = {reader, "e2"};
|
||||
TTreeReaderArray<ULong64_t> e_t = {reader, "e_t"};
|
||||
TTreeReaderArray<UShort_t> e_f = {reader, "e_f"};
|
||||
|
||||
mutex.lock();
|
||||
count++;
|
||||
printf("-------------- Thread_ID: %d \n", count);
|
||||
mutex.unlock();
|
||||
|
||||
SplitPoleHit hit;
|
||||
hit.SetMassTablePath("../analyzers/mass20.txt");
|
||||
hit.CalConstants("12C", "d", "p", 16, 18); // 80MeV, 5 deg
|
||||
hit.CalZoffset(0.750); // 1.41 T
|
||||
|
||||
|
||||
while (reader.Next()) {
|
||||
|
||||
hit.ClearData();
|
||||
|
||||
phMulti->Fill(*multi);
|
||||
|
||||
// if( *multi != 9 ) continue;
|
||||
|
||||
for( int i = 0; i < *multi; i++){
|
||||
|
||||
// t2 = e_t[i];
|
||||
// if( t2 < t1 ) printf("entry %lld-%d, timestamp is not in order. %llu, %llu\n", processedEntries, i, t2, t1);
|
||||
if( i == 0 ) t1 = e_t[i];
|
||||
// if( e[i] == 65535 ) continue;
|
||||
|
||||
if( ch[i] == ChMap::ScinR ) {hit.eSR = e[i]; hit.tSR = e_t[i] + e_f[i]/1000;}
|
||||
if( ch[i] == ChMap::ScinL ) {hit.eSL = e[i]; hit.tSL = e_t[i] + e_f[i]/1000;}
|
||||
if( ch[i] == ChMap::dFR ) {hit.eFR = e[i]; hit.tFR = e_t[i] + e_f[i]/1000;}
|
||||
if( ch[i] == ChMap::dFL ) {hit.eFL = e[i]; hit.tFL = e_t[i] + e_f[i]/1000;}
|
||||
if( ch[i] == ChMap::dBR ) {hit.eBR = e[i]; hit.tBR = e_t[i] + e_f[i]/1000;}
|
||||
if( ch[i] == ChMap::dBL ) {hit.eBL = e[i]; hit.tBL = e_t[i] + e_f[i]/1000;}
|
||||
if( ch[i] == ChMap::Cathode ) {hit.eCath = e[i]; hit.tCath = e_t[i] + e_f[i]/1000;}
|
||||
if( ch[i] == ChMap::AnodeF ) {hit.eAF = e[i]; hit.tAF = e_t[i] + e_f[i]/1000;}
|
||||
if( ch[i] == ChMap::AnodeB ) {hit.eAB = e[i]; hit.tAB = e_t[i] + e_f[i]/1000;}
|
||||
|
||||
for( int j = i+1; j < sn.GetSize(); j++){
|
||||
pCoin->Fill(ch[i], ch[j]);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int dQ = hit.eAB; // delta Q
|
||||
unsigned int Qt = hit.eSL; // total Q
|
||||
|
||||
if( Qt > 0 && dQ > 0 ) {
|
||||
pPID->Fill(Qt, dQ);
|
||||
}
|
||||
|
||||
//=============== PID gate cut
|
||||
if( pidCut ){
|
||||
if( !pidCut->IsInside(Qt, dQ) ) continue;
|
||||
}
|
||||
|
||||
hit.CalData(2);
|
||||
|
||||
if( hit.theta > 1.2 || 0.5 > hit.theta ) continue;
|
||||
|
||||
if( (!TMath::IsNaN(hit.x1) || !TMath::IsNaN(hit.x2)) ) {
|
||||
phFocal->Fill(hit.x1, hit.x2);
|
||||
phF->Fill(hit.x1);
|
||||
phB->Fill(hit.x2);
|
||||
phXavg->Fill(hit.xAvg);
|
||||
phXavg_Q->Fill(hit.xAvg, dQ);
|
||||
phXavg_Theta->Fill( hit.xAvg, hit.theta);
|
||||
|
||||
for( int i = 0; i < 400; i++){
|
||||
double z = -50 + 100/400.*i;
|
||||
|
||||
double x = (z/42.8625 + 0.5)* ( hit.x2-hit.x1) + hit.x1;
|
||||
|
||||
phRay->Fill(x,z);
|
||||
}
|
||||
|
||||
double ex = hit.Rho2Ex( ((hit.xAvg - rhoOffset)/1000/rhoScaling + hit.GetRho0() ) );
|
||||
//if( XMIN < hit.xAvg && hit.xAvg < XMAX) printf("x1 : %6.2f, x2 : %6.2f, xAvg %6.2f cm , ex : %f \n", hit.x1, hit.x2, hit.xAvg, ex);
|
||||
|
||||
phEx->Fill(ex);
|
||||
phEx_Multi->Fill(ex, *multi);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
};
|
||||
|
||||
//^============================ Run TP
|
||||
tp.Process(ProcessTask);
|
||||
|
||||
//^============================ Merge all ThreadedObject
|
||||
auto coin = pCoin.Merge();
|
||||
auto hMulti= phMulti.Merge();
|
||||
auto hEx = phEx.Merge();
|
||||
auto hEx_Multi = phEx_Multi.Merge();
|
||||
auto PID = pPID.Merge();
|
||||
auto hFocal = phFocal.Merge();
|
||||
auto hF = phF.Merge();
|
||||
auto hB = phB.Merge();
|
||||
auto hXavg = phXavg.Merge();
|
||||
auto hXavg_Q = phXavg_Q.Merge();
|
||||
auto hXavg_Theta = phXavg_Theta.Merge();
|
||||
auto hRay = phRay.Merge();
|
||||
|
||||
//^============================== Plot
|
||||
gStyle->SetOptStat("neiou");
|
||||
|
||||
TCanvas * canvas = new TCanvas("cc", "Split-Pole", 2500, 1000);
|
||||
canvas->Divide(5, 2);
|
||||
|
||||
canvas->cd(1); {
|
||||
PID->DrawCopy("colz");
|
||||
if( pidCut ) pidCut->Draw("same");
|
||||
}
|
||||
|
||||
canvas->cd(2); hRay->DrawCopy("colz");
|
||||
|
||||
canvas->cd(3); hF->DrawCopy();
|
||||
canvas->cd(4); hB->DrawCopy();
|
||||
|
||||
canvas->cd(5); hXavg_Q->DrawCopy("colz");
|
||||
|
||||
canvas->cd(6); hXavg->DrawCopy("colz");
|
||||
|
||||
canvas->cd(7); hEx->DrawCopy();
|
||||
|
||||
//canvas->cd(8); coin->DrawCopy("colz");
|
||||
canvas->cd(8); hEx_Multi->DrawCopy("colz");
|
||||
|
||||
canvas->cd(9); canvas->cd(9)->SetLogy(); hMulti->DrawCopy();
|
||||
|
||||
canvas->cd(10); hXavg_Theta->DrawCopy("colz");
|
||||
|
||||
}
|
|
@ -3,7 +3,7 @@
|
|||
#include <algorithm>
|
||||
#include <filesystem>
|
||||
|
||||
#define DEFAULT_HALFBUFFERSIZE 500000
|
||||
#define DEFAULT_HALFBUFFERSIZE 5000000
|
||||
|
||||
class FSUReader{
|
||||
|
||||
|
@ -49,6 +49,7 @@ class FSUReader{
|
|||
int GetNumCh() const{return numCh;}
|
||||
int GetFileOrder() const{return order;}
|
||||
int GetChMask() const{return chMask;}
|
||||
int GetRunNum() const{return runNum;}
|
||||
unsigned long GetFileByteSize() const {return inFileSize;}
|
||||
|
||||
void ClearHitList() { hit.clear();}
|
||||
|
@ -63,7 +64,7 @@ class FSUReader{
|
|||
void ClearTotalHitCount() {totalHitCount = 0;}
|
||||
ulong GetTotalHitCount() const{return totalHitCount;}
|
||||
|
||||
std::vector<Hit> ReadBatch(unsigned int batchSize = 1000000, bool verbose = false); // output the sorted Hit
|
||||
std::vector<Hit> ReadBatch(unsigned int batchSize = 1000000, bool traceOn = false, bool verbose = false); // output the sorted Hit
|
||||
|
||||
void PrintHit(ulong numHit = -1, ulong startIndex = 0) {
|
||||
for( ulong i = startIndex; i < std::min(numHit, totalHitCount); i++){
|
||||
|
@ -116,6 +117,7 @@ class FSUReader{
|
|||
uShort order;
|
||||
uShort chMask;
|
||||
uShort numCh;
|
||||
uShort runNum;
|
||||
|
||||
std::vector<unsigned int> blockPos;
|
||||
std::vector<unsigned int > blockTimeStamp;
|
||||
|
@ -262,14 +264,17 @@ inline void FSUReader::OpenFile(std::string fileName, uInt dataSize, int verbose
|
|||
std::string token;
|
||||
|
||||
while (std::getline(iss, token, '_')) { tokens.push_back(token); }
|
||||
sn = atoi(tokens[2].c_str());
|
||||
tick2ns = atoi(tokens[4].c_str());
|
||||
order = atoi(tokens[5].c_str());
|
||||
short token_size = tokens.size();
|
||||
// for( short i = 0; i < token_size; i ++ ) printf("%d | %s\n", i, tokens[i].c_str());
|
||||
runNum = atoi(tokens[token_size-5].c_str());
|
||||
sn = atoi(tokens[token_size-4].c_str());
|
||||
tick2ns = atoi(tokens[token_size-2].c_str());
|
||||
order = atoi(tokens[token_size-1].c_str());
|
||||
|
||||
DPPType = 0;
|
||||
if( fileName.find("PHA") != std::string::npos ) DPPType = DPPTypeCode::DPP_PHA_CODE;
|
||||
if( fileName.find("PSD") != std::string::npos ) DPPType = DPPTypeCode::DPP_PSD_CODE;
|
||||
if( fileName.find("QDC") != std::string::npos ) DPPType = DPPTypeCode::DPP_QDC_CODE;
|
||||
if( fileName.find("PHA") != std::string::npos ) { printf("Using PHA decode.\n"); DPPType = DPPTypeCode::DPP_PHA_CODE;}
|
||||
if( fileName.find("PSD") != std::string::npos ) { printf("Using PSD decode.\n"); DPPType = DPPTypeCode::DPP_PSD_CODE;}
|
||||
if( fileName.find("QDC") != std::string::npos ) { printf("Using QDC decode.\n"); DPPType = DPPTypeCode::DPP_QDC_CODE;}
|
||||
if( DPPType == 0 ){
|
||||
fclose(inFile);
|
||||
inFile = nullptr;
|
||||
|
@ -291,7 +296,7 @@ inline int FSUReader::ReadNextBlock(bool traceON, int verbose, uShort saveData){
|
|||
if( inFile == NULL ) return -1;
|
||||
if( feof(inFile) || filePos >= inFileSize) {
|
||||
if( fileID >= 0 && fileID + 1 < (short) fileList.size() ){
|
||||
printf("-------------- next file\n");
|
||||
printf("-------------- next file | hit size : %zu\n", hit.size());
|
||||
fileID ++;
|
||||
OpenFile(fileList[fileID], data->GetDataSize(), 1 );
|
||||
}else{
|
||||
|
@ -365,12 +370,16 @@ inline int FSUReader::ReadNextBlock(bool traceON, int verbose, uShort saveData){
|
|||
|
||||
for( int i = start; i < start + data->NumEventsDecoded[ch]; i++ ){
|
||||
int k = i % data->GetDataSize();
|
||||
|
||||
|
||||
temp.sn = sn;
|
||||
temp.ch = ch;
|
||||
temp.energy = data->GetEnergy(ch, k);
|
||||
temp.energy2 = data->GetEnergy2(ch, k);
|
||||
|
||||
temp.timestamp = data->GetTimestamp(ch, k);
|
||||
// unsigned long long offset = 1000000;
|
||||
// if( sn == 405 && ch == 0) temp.timestamp -= offset;
|
||||
|
||||
temp.fineTime = data->GetFineTime(ch, k);
|
||||
temp.pileUp = data->GetPileUp(ch, k);
|
||||
if( saveData > 1 ) {
|
||||
|
@ -381,6 +390,8 @@ inline int FSUReader::ReadNextBlock(bool traceON, int verbose, uShort saveData){
|
|||
if( temp.trace.size() > 0 ) temp.trace.clear();
|
||||
}
|
||||
|
||||
// temp.Print();
|
||||
|
||||
hit.push_back(temp);
|
||||
}
|
||||
}
|
||||
|
@ -491,7 +502,7 @@ inline void FSUReader::ScanNumBlock(int verbose, uShort saveData){
|
|||
}
|
||||
|
||||
//^==============================================================
|
||||
inline std::vector<Hit> FSUReader::ReadBatch(unsigned int batchSize, bool verbose){
|
||||
inline std::vector<Hit> FSUReader::ReadBatch(unsigned int batchSize, bool traceOn, bool verbose){
|
||||
|
||||
// printf("%s sn:%d. filePos : %lu\n", __func__, sn, ftell(inFile));
|
||||
|
||||
|
@ -505,7 +516,7 @@ inline std::vector<Hit> FSUReader::ReadBatch(unsigned int batchSize, bool verbos
|
|||
if( hit.size() == 0 ){
|
||||
int res = 0;
|
||||
do{
|
||||
res = ReadNextBlock(true, 0, 3);
|
||||
res = ReadNextBlock(traceOn, 0, 3);
|
||||
}while ( hit.size() < batchSize && res == 0);
|
||||
SortHit();
|
||||
uLong t0_B = hit.at(0).timestamp;
|
||||
|
@ -531,7 +542,7 @@ inline std::vector<Hit> FSUReader::ReadBatch(unsigned int batchSize, bool verbos
|
|||
|
||||
int res = 0;
|
||||
do{
|
||||
res = ReadNextBlock(true, 0, 3);
|
||||
res = ReadNextBlock(traceOn, 0, 3);
|
||||
}while ( hit.size() < batchSize && res == 0);
|
||||
SortHit();
|
||||
uLong t0_B = hit.at(0).timestamp;
|
||||
|
|
|
@ -81,7 +81,7 @@ int main(int argc, char **argv) {
|
|||
tempInfo.fileName = inFileName[i];
|
||||
tempInfo.readerID = i;
|
||||
tempInfo.SN = reader[i]->GetSN();
|
||||
tempInfo.hitCount = reader[i]->GetHitCount();
|
||||
tempInfo.hitCount = reader[i]->GetTotalHitCount();
|
||||
tempInfo.fileSize = reader[i]->GetFileByteSize();
|
||||
tempInfo.tick2ns = reader[i]->GetTick2ns();
|
||||
tempInfo.DPPType = reader[i]->GetDPPType();
|
||||
|
@ -208,7 +208,7 @@ int main(int argc, char **argv) {
|
|||
}else{
|
||||
group[gpID].hitID = 0;
|
||||
uShort rID = group[gpID].readerIDList[group[gpID].currentID];
|
||||
group[gpID].hitCount = reader[rID]->GetHitCount();
|
||||
group[gpID].hitCount = reader[rID]->GetTotalHitCount();
|
||||
printf("-----> go to the next file, %s \n", fileInfo[rID].fileName.c_str() );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -110,7 +110,7 @@ int main(int argc, char **argv) {
|
|||
tempInfo.fileName = outFileName;
|
||||
tempInfo.readerID = i;
|
||||
tempInfo.SN = reader[i]->GetSN();
|
||||
tempInfo.hitCount = reader[i]->GetHitCount();
|
||||
tempInfo.hitCount = reader[i]->GetTotalHitCount();
|
||||
tempInfo.fileSize = reader[i]->GetTSFileSize();
|
||||
tempInfo.tick2ns = reader[i]->GetTick2ns();
|
||||
tempInfo.DPPType = reader[i]->GetDPPType();
|
||||
|
|
170
Aux/script.C
170
Aux/script.C
|
@ -1,90 +1,114 @@
|
|||
#include "fsuReader.h"
|
||||
#include "../MultiBuilder.cpp"
|
||||
// #include "../MultiBuilder.cpp"
|
||||
|
||||
#include "SplitPolePlotter.C"
|
||||
#include "SplitPolePlotter_MT.C"
|
||||
|
||||
void script(){
|
||||
|
||||
FSUReader * reader = new FSUReader("~/ExpData/testing/.fsu", 16);
|
||||
Data * data = reader->GetData();
|
||||
data->tick2ns = 4;
|
||||
TChain * chain = new TChain("tree");
|
||||
// chain->Add("raw_binary/run_13/run013_3000.root");
|
||||
// chain->Add("data/run*_3000.root");
|
||||
chain->Add("data/12C_dp_*_3000.root");
|
||||
|
||||
reader->ScanNumBlock();
|
||||
// TFile * pidCutFile = new TFile("cut_proton.root");
|
||||
TFile * pidCutFile = new TFile("cut_proton_FSU.root");
|
||||
TCutG * pidCut = (TCutG *) pidCutFile->Get("protons");
|
||||
|
||||
// SplitPolePlotter(chain, pidCut, 123.307, 2.75, false); // for CoMPASS data
|
||||
// SplitPolePlotter(chain, pidCut, 123.307, 2.75, true); // faster then MT?
|
||||
|
||||
// for( int i = 0; i < 500 ; i++ ) reader->ReadNextBlock(0, 0);
|
||||
|
||||
// int ch = 5;
|
||||
// std::vector<unsigned long long > tList;
|
||||
// int nEvent = 0;
|
||||
// for( int i = 0; i < data->TotNumNonPileUpEvents[ch]; i++){
|
||||
// tList.push_back(data->Timestamp[ch][i]);
|
||||
// printf("%3d | %d %llu \n", i, data->Energy[ch][i], data->Timestamp[ch][i]);
|
||||
// nEvent ++;
|
||||
// }
|
||||
|
||||
// std::sort(tList.begin(), tList.end());
|
||||
|
||||
// unsigned long long dTime = tList.back() - tList.front();
|
||||
// double sec = dTime * data->tick2ns / 1e9;
|
||||
|
||||
// printf("=========== %llu, %llu = %llu | %f sec | %f Hz\n", tList.back(), tList.front(), dTime, sec, nEvent/sec );
|
||||
|
||||
//data->PrintStat(0);
|
||||
SplotPolePlotter_MT(chain, 5, pidCut, 123.307, 2.75, true);
|
||||
|
||||
|
||||
data->ClearData();
|
||||
data->ClearTriggerRate();
|
||||
//^=====================================================
|
||||
|
||||
// FSUReader * reader = new FSUReader("data/12C_dp_002_19555_PSD_4_000.fsu", 10000, 2);
|
||||
|
||||
// reader->ScanNumBlock(1, 0);
|
||||
|
||||
// reader->ReadNextBlock(0, 9);
|
||||
|
||||
// for( int i = 0; i < 10 ; i++ ) reader->ReadNextBlock(0, 9);
|
||||
|
||||
// std::vector<Hit> hitList = reader->ReadBatch(10, true);
|
||||
|
||||
// for ( int i = 0; i < 10 ; i ++) hitList[i].Print();
|
||||
|
||||
// // int ch = 5;
|
||||
// // std::vector<unsigned long long > tList;
|
||||
// // int nEvent = 0;
|
||||
// // for( int i = 0; i < data->TotNumNonPileUpEvents[ch]; i++){
|
||||
// // tList.push_back(data->Timestamp[ch][i]);
|
||||
// // printf("%3d | %d %llu \n", i, data->Energy[ch][i], data->Timestamp[ch][i]);
|
||||
// // nEvent ++;
|
||||
// // }
|
||||
|
||||
// // std::sort(tList.begin(), tList.end());
|
||||
|
||||
// // unsigned long long dTime = tList.back() - tList.front();
|
||||
// // double sec = dTime * data->tick2ns / 1e9;
|
||||
|
||||
// // printf("=========== %llu, %llu = %llu | %f sec | %f Hz\n", tList.back(), tList.front(), dTime, sec, nEvent/sec );
|
||||
|
||||
// //data->PrintStat(0);
|
||||
|
||||
|
||||
MultiBuilder * mb = new MultiBuilder(data, reader->GetDPPType(), 334);
|
||||
mb->SetTimeWindow(10000);
|
||||
|
||||
unsigned long totNumBlock = reader->GetTotNumBlock();
|
||||
|
||||
int lastDataIndex = 0;
|
||||
int lastLoopIndex = 0;
|
||||
|
||||
for( unsigned long i = 0; i < 2; i++){
|
||||
|
||||
reader->ReadNextBlock();
|
||||
|
||||
// int maxDataIndex = 0;
|
||||
// int maxLoopIndex = 0;
|
||||
|
||||
// for( int ch = 0; ch < 16 ; ch++){
|
||||
// if( data->DataIndex[ch] > maxDataIndex ) maxDataIndex = data->DataIndex[ch];
|
||||
// if( data->LoopIndex[ch] > maxLoopIndex ) maxLoopIndex = data->LoopIndex[ch];
|
||||
// }
|
||||
|
||||
// if( (maxLoopIndex * MaxNData + maxDataIndex) - (lastLoopIndex * MaxNData + lastDataIndex) > MaxNData * 0.05){
|
||||
|
||||
// printf("Agg ID : %lu \n", i );
|
||||
|
||||
// data->PrintStat();
|
||||
// data->PrintAllData();
|
||||
|
||||
// mb->BuildEvents();
|
||||
// mb->PrintAllEvent();
|
||||
// mb->PrintStat();
|
||||
|
||||
// lastDataIndex = maxDataIndex;
|
||||
// lastLoopIndex = maxLoopIndex;
|
||||
// }
|
||||
|
||||
}
|
||||
// data->ClearData();
|
||||
// data->ClearTriggerRate();
|
||||
|
||||
|
||||
data->PrintStat();
|
||||
data->PrintAllData();
|
||||
|
||||
|
||||
//mb->BuildEvents(true);
|
||||
// MultiBuilder * mb = new MultiBuilder(data, reader->GetDPPType(), 334);
|
||||
// mb->SetTimeWindow(10000);
|
||||
|
||||
// unsigned long totNumBlock = reader->GetTotNumBlock();
|
||||
|
||||
// int lastDataIndex = 0;
|
||||
// int lastLoopIndex = 0;
|
||||
|
||||
mb->BuildEventsBackWard(300);
|
||||
// for( unsigned long i = 0; i < 2; i++){
|
||||
|
||||
mb->PrintAllEvent();
|
||||
mb->PrintStat();
|
||||
// reader->ReadNextBlock();
|
||||
|
||||
// // int maxDataIndex = 0;
|
||||
// // int maxLoopIndex = 0;
|
||||
|
||||
// // for( int ch = 0; ch < 16 ; ch++){
|
||||
// // if( data->DataIndex[ch] > maxDataIndex ) maxDataIndex = data->DataIndex[ch];
|
||||
// // if( data->LoopIndex[ch] > maxLoopIndex ) maxLoopIndex = data->LoopIndex[ch];
|
||||
// // }
|
||||
|
||||
// // if( (maxLoopIndex * MaxNData + maxDataIndex) - (lastLoopIndex * MaxNData + lastDataIndex) > MaxNData * 0.05){
|
||||
|
||||
// // printf("Agg ID : %lu \n", i );
|
||||
|
||||
// // data->PrintStat();
|
||||
// // data->PrintAllData();
|
||||
|
||||
// // mb->BuildEvents();
|
||||
// // mb->PrintAllEvent();
|
||||
// // mb->PrintStat();
|
||||
|
||||
// // lastDataIndex = maxDataIndex;
|
||||
// // lastLoopIndex = maxLoopIndex;
|
||||
// // }
|
||||
|
||||
// }
|
||||
|
||||
|
||||
delete mb;
|
||||
delete reader;
|
||||
// data->PrintStat();
|
||||
// data->PrintAllData();
|
||||
|
||||
|
||||
// //mb->BuildEvents(true);
|
||||
|
||||
}
|
||||
// mb->BuildEventsBackWard(300);
|
||||
|
||||
// mb->PrintAllEvent();
|
||||
// mb->PrintStat();
|
||||
|
||||
|
||||
// delete mb;
|
||||
// delete reader;
|
||||
|
||||
}
|
||||
|
|
132
Aux/test.cpp
132
Aux/test.cpp
|
@ -321,82 +321,82 @@ int TestDigitizerRaw(){
|
|||
|
||||
}
|
||||
|
||||
|
||||
void Compare_CAEN_Decoder(){
|
||||
|
||||
std::unique_ptr<Digitizer> digi = std::make_unique<Digitizer>(0, 49093, false, true);
|
||||
Data * data = digi->GetData();
|
||||
|
||||
int ret;
|
||||
int handle = digi->GetHandle();
|
||||
CAEN_DGTZ_DPP_PSD_Event_t *Events[16]; /// events buffer
|
||||
uint32_t NumEvents[16];
|
||||
|
||||
uint32_t AllocatedSize = 0;
|
||||
|
||||
ret |= CAEN_DGTZ_MallocDPPEvents(handle, reinterpret_cast<void**>(&Events), &AllocatedSize) ;
|
||||
printf("allowcated %d byte for Events\n", AllocatedSize);
|
||||
|
||||
|
||||
printf("======================== start ACQ \n");
|
||||
digi->StartACQ();
|
||||
|
||||
int ch = 0;
|
||||
for( int i = 0; i < 5; i ++ ){
|
||||
usleep(1000*1000); // every 1 second
|
||||
|
||||
digi->ReadData();
|
||||
// data->CopyBuffer(cpBuffer, bufferSize);
|
||||
data->DecodeBuffer(false, 4);
|
||||
|
||||
if( data->nByte > 0 ){
|
||||
ret = (CAEN_DGTZ_ErrorCode) CAEN_DGTZ_GetDPPEvents(handle, data->buffer, data->nByte, reinterpret_cast<void**>(&Events), NumEvents);
|
||||
if (ret) {
|
||||
printf("Error when getting events from data %d\n", ret);
|
||||
continue;
|
||||
}
|
||||
|
||||
printf("============ %u\n", NumEvents[0]);
|
||||
|
||||
for( int ev = 0; ev < NumEvents[0]; ev++ ){
|
||||
|
||||
printf("-------- ev %d\n", ev);
|
||||
printf( " Format : 0x%04x\n", Events[ch][ev].Format);
|
||||
printf( "TimeTag : 0x%08x\n", Events[ch][ev].TimeTag);
|
||||
printf(" E_short : 0x%04x\n", Events[ch][ev].ChargeShort);
|
||||
printf(" E_long : 0x%04x\n", (Events[ch][ev].ChargeLong & 0xffff));
|
||||
printf("Baseline : 0x%04x\n", (Events[ch][ev].Baseline & 0xffff));
|
||||
printf(" Pur : 0x%04x\n", Events[ch][ev].Pur);
|
||||
printf(" Extra : 0x%08x\n", Events[ch][ev].Extras);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
digi->StopACQ();
|
||||
|
||||
printf("======================== ACQ Stopped.\n");
|
||||
|
||||
}
|
||||
|
||||
//^======================================
|
||||
int main(int argc, char* argv[]){
|
||||
|
||||
TestDigitizerRaw();
|
||||
|
||||
// CheckBufferSize(5, 4);
|
||||
Compare_CAEN_Decoder();
|
||||
|
||||
//GetOneAgg();
|
||||
// Data * data = digi->GetData();
|
||||
|
||||
// MultiBuilder * builder = new MultiBuilder(data, DPPType::DPP_PHA_CODE, digi->GetSerialNumber());
|
||||
// builder->SetTimeWindow(100);
|
||||
|
||||
|
||||
|
||||
// digi->WriteRegister(DPP::QDC::PreTrigger, 60, -1);
|
||||
|
||||
// digi->WriteRegister(DPP::QDC::TriggerThreshold_sub2, 17, -1);
|
||||
// digi->SetBits(DPP::QDC::DPPAlgorithmControl, DPP::QDC::Bit_DPPAlgorithmControl::ChargeSensitivity, 0, -1);
|
||||
// digi->SetBits(DPP::QDC::DPPAlgorithmControl, DPP::QDC::Bit_DPPAlgorithmControl::InputSmoothingFactor, 4, -1);
|
||||
// digi->SetBits(DPP::QDC::DPPAlgorithmControl, DPP::QDC::Bit_DPPAlgorithmControl::BaselineAvg, 2, -1);
|
||||
|
||||
// digi->WriteRegister(DPP::QDC::GateWidth, 608/16, -1);
|
||||
|
||||
// digi->WriteRegister(DPP::QDC::GroupEnableMask, 0x01);
|
||||
|
||||
// digi->WriteRegister(DPP::QDC::NumberEventsPerAggregate, 10, -1);
|
||||
// digi->WriteRegister(DPP::AggregateOrganization, 0, -1);
|
||||
// digi->WriteRegister(DPP::MaxAggregatePerBlockTransfer, 100, -1);
|
||||
|
||||
// digi->SetBits(DPP::QDC::DPPAlgorithmControl, DPP::QDC::Bit_DPPAlgorithmControl::Polarity, 0, -1);
|
||||
|
||||
/*
|
||||
digi->SetBits(DPP::BoardConfiguration, DPP::Bit_BoardConfig::EnableExtra2, 1, -1);
|
||||
digi->SetBits(DPP::BoardConfiguration, DPP::Bit_BoardConfig::RecordTrace, 0, -1);
|
||||
|
||||
Data * data = digi->GetData();
|
||||
|
||||
MultiBuilder * builder = new MultiBuilder(data, DPPType::DPP_PHA_CODE, digi->GetSerialNumber());
|
||||
builder->SetTimeWindow(100);
|
||||
|
||||
//remove("haha_*.fsu");
|
||||
//data->OpenSaveFile("haha");
|
||||
|
||||
digi->StartACQ();
|
||||
|
||||
for( int i = 0; i < 5; i ++ ){
|
||||
usleep(1000*1000);
|
||||
digi->ReadData();
|
||||
data->DecodeBuffer(true, 0);
|
||||
//data->DecodeBuffer(false, 2);
|
||||
//data->SaveData();
|
||||
//data->PrintStat();
|
||||
|
||||
data->PrintAllData(true);
|
||||
|
||||
//builder->BuildEvents(false, true, true);
|
||||
builder->BuildEventsBackWard(20, true);
|
||||
|
||||
builder->PrintStat();
|
||||
// int index = data->NumEventsDecoded[0];
|
||||
// printf("-------------- %ld \n", data->Waveform1[0][index].size());
|
||||
|
||||
}
|
||||
digi->StopACQ();
|
||||
|
||||
//data->CloseSaveFile();
|
||||
builder->BuildEvents(true, true, true);
|
||||
|
||||
data->PrintAllData();
|
||||
|
||||
builder->PrintAllEvent(); // TODO
|
||||
*/
|
||||
|
||||
// digi->CloseDigitizer();
|
||||
// delete digi;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
//*********************************
|
||||
//*********************************
|
||||
|
||||
|
|
45
ClassData.h
45
ClassData.h
|
@ -90,6 +90,7 @@ class Data{
|
|||
|
||||
unsigned short GetNChannel() const {return numInputCh;}
|
||||
|
||||
void PrintBuffer();
|
||||
void CopyBuffer( const char * buffer, const unsigned int size);
|
||||
|
||||
void DecodeBuffer(bool fastDecode, int verbose = 0); /// fastDecode will not save waveform
|
||||
|
@ -310,7 +311,7 @@ inline void Data::ClearData(){
|
|||
if( ch >= numInputCh) break;
|
||||
for( int j = 0; j < dataSize; j++){
|
||||
Timestamp[ch][j] = 0;
|
||||
fineTime[ch][j] = 0;
|
||||
fineTime[ch][j] = -1;
|
||||
Energy[ch][j] = 0;
|
||||
Energy2[ch][j] = 0;
|
||||
Waveform1[ch][j].clear();
|
||||
|
@ -330,6 +331,8 @@ inline void Data::ClearData(){
|
|||
tempDigiWaveform3.clear();
|
||||
tempDigiWaveform4.clear();
|
||||
|
||||
outFileIndex = 0;
|
||||
|
||||
ClearNumEventsDecoded();
|
||||
ClearTriggerRate();
|
||||
|
||||
|
@ -344,7 +347,10 @@ inline void Data::ClearBuffer(){
|
|||
}
|
||||
|
||||
inline void Data::CopyBuffer(const char * buffer, const unsigned int size){
|
||||
if( this->buffer ) delete this->buffer;
|
||||
this->buffer = (char*) malloc(size);
|
||||
std::memcpy(this->buffer, buffer, size);
|
||||
this->nByte = size;
|
||||
}
|
||||
|
||||
inline void Data::ClearReferenceTime(){
|
||||
|
@ -557,12 +563,21 @@ inline void Data::PrintChData(unsigned short ch, unsigned int maxRowDisplay) con
|
|||
|
||||
//^#######################################################
|
||||
//^####################################################### Decode
|
||||
inline void Data::PrintBuffer(){
|
||||
if( buffer == NULL || nByte == 0 ) return;
|
||||
printf("============== Received nByte : %u\n", nByte);
|
||||
for( unsigned int i = 0; i < nByte/4; i++ ) {
|
||||
ReadBuffer(i, 2);
|
||||
printf("\n");
|
||||
}
|
||||
}
|
||||
|
||||
inline unsigned int Data::ReadBuffer(unsigned int nWord, int verbose){
|
||||
if( buffer == NULL ) return 0;
|
||||
|
||||
unsigned int word = 0;
|
||||
for( int i = 0 ; i < 4 ; i++) word += ((buffer[i + 4 * nWord] & 0xFF) << 8*i);
|
||||
if( verbose >= 2) printf("%6d | 0x%08X | ", nWord, word);
|
||||
if( verbose >= 2) printf("%6d | 0x%08X |", nWord, word);
|
||||
return word;
|
||||
}
|
||||
|
||||
|
@ -882,7 +897,11 @@ inline int Data::DecodePHADualChannelBlock(unsigned int ChannelMask, bool fastDe
|
|||
|
||||
Energy[channel][DataIndex[channel]] = energy;
|
||||
Timestamp[channel][DataIndex[channel]] = timeStamp * tick2ns;
|
||||
if(extra2Option == 2 ) fineTime[channel][DataIndex[channel]] = (extra2 & 0x03FF );
|
||||
if(extra2Option == 2 ) {
|
||||
fineTime[channel][DataIndex[channel]] = (extra2 & 0x03FF ) * tick2ns; // in ps, the tick2ns is a conversion factor
|
||||
}else{
|
||||
fineTime[channel][DataIndex[channel]] = -1;
|
||||
}
|
||||
PileUp[channel][DataIndex[channel]] = pileUp;
|
||||
NumEventsDecoded[channel] ++;
|
||||
|
||||
|
@ -1085,7 +1104,11 @@ inline int Data::DecodePSDDualChannelBlock(unsigned int ChannelMask, bool fastDe
|
|||
Energy2[channel][DataIndex[channel]] = Qshort;
|
||||
Energy[channel][DataIndex[channel]] = Qlong;
|
||||
Timestamp[channel][DataIndex[channel]] = timeStamp * tick2ns;
|
||||
if( extraOption == 2 ) fineTime[channel][DataIndex[channel]] = extra & 0x3FF;
|
||||
if( extraOption == 2 ) {
|
||||
fineTime[channel][DataIndex[channel]] = (extra & 0x3FF) * tick2ns; //in ps, tick2ns is justa conversion factor
|
||||
}else{
|
||||
fineTime[channel][DataIndex[channel]] = -1; //in ps, tick2ns is justa conversion factor
|
||||
}
|
||||
|
||||
NumEventsDecoded[channel] ++;
|
||||
if( !pileup){
|
||||
|
@ -1110,10 +1133,16 @@ inline int Data::DecodePSDDualChannelBlock(unsigned int ChannelMask, bool fastDe
|
|||
//if( DataIndex[channel] >= dataSize ) ClearData();
|
||||
|
||||
//if( verbose >= 2 ) printf("extra : 0x%08x, Qshort : %d, Qlong : %d \n", extra, Qshort, Qlong);
|
||||
if( verbose == 1 ) printf("ch : %2d, Qshort : %6d, Qlong : %6d, timestamp : %llu\n",
|
||||
channel, Qshort, Qlong, timeStamp * tick2ns);
|
||||
if( verbose >= 2 ) printf("Qshort : %6d, Qlong : %6d, timestamp : %llu\n",
|
||||
Qshort, Qlong, timeStamp * tick2ns);
|
||||
if( verbose >= 1 ) {
|
||||
if( extraOption == 0){
|
||||
printf("Qshort : %6d, Qlong : %6d, timestamp : %llu, baseline : %u\n",
|
||||
Qshort, Qlong, timeStamp * tick2ns, (extra & 0xFFFF) * 4);
|
||||
}
|
||||
if( extraOption == 2){
|
||||
printf("Qshort : %6d, Qlong : %6d, timestamp : %llu, fineTime : %u\n",
|
||||
Qshort, Qlong, timeStamp * tick2ns, (extra & 0x3FF) * tick2ns);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -183,7 +183,6 @@ int Digitizer::OpenDigitizer(int boardID, int portID, bool program, bool verbose
|
|||
/// change address 0xEF08 (5 bits), this will reflected in the 2nd word of the Board Agg. header.
|
||||
ret = CAEN_DGTZ_WriteRegister(handle, DPP::BoardID, (DPPType & 0xF));
|
||||
|
||||
|
||||
//TODO somehow the bdInfo does not work, use DPPType to set it
|
||||
uint32_t bdInfo = GetSettingFromMemory(DPP::BoardInfo_R);
|
||||
uint32_t haha = ((bdInfo >> 8 ) & 0xFF);
|
||||
|
@ -258,6 +257,7 @@ int Digitizer::OpenDigitizer(int boardID, int portID, bool program, bool verbose
|
|||
ErrorMsg("end of OpenDigitizer");
|
||||
|
||||
softwareDisable = false;
|
||||
AcqRun = false;
|
||||
|
||||
if( isConnected ) isDummy = false;
|
||||
|
||||
|
@ -278,16 +278,18 @@ int Digitizer::CloseDigitizer(){
|
|||
isConnected = false;
|
||||
ret = CAEN_DGTZ_SWStopAcquisition(handle);
|
||||
printf("-------- Closing Digtizer Board : %d Port : %d \n", boardID, portID);
|
||||
printf(" Model %s with handle %d using %s\n", BoardInfo.ModelName, handle, LinkType == CAEN_DGTZ_USB ? "USB" : "Optical Link");
|
||||
if( LinkType == CAEN_DGTZ_USB ) printf(" Model %s with handle %d using USB\n", BoardInfo.ModelName, handle);
|
||||
if( LinkType == CAEN_DGTZ_OpticalLink ) printf(" Model %s with handle %d using Optical Fiber\n", BoardInfo.ModelName, handle);
|
||||
if( LinkType == CAEN_DGTZ_USB_A4818 ) printf(" Model %s with handle %d using A4818\n", BoardInfo.ModelName, handle);
|
||||
ret |= CAEN_DGTZ_CloseDigitizer(handle);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
void Digitizer::SetRegChannelMask(uint32_t mask){
|
||||
DebugPrint("%s", "Digitizer");
|
||||
if( softwareDisable ) return;
|
||||
if( AcqRun ) return;
|
||||
if( !isConnected ) return;
|
||||
regChannelMask = mask;
|
||||
ret |= CAEN_DGTZ_SetChannelEnableMask(handle, regChannelMask);
|
||||
|
@ -309,6 +311,7 @@ bool Digitizer::GetInputChannelOnOff(unsigned ch) {
|
|||
void Digitizer::SetRegChannelOnOff(unsigned short ch, bool onOff){
|
||||
DebugPrint("%s", "Digitizer");
|
||||
if( softwareDisable ) return;
|
||||
if( AcqRun ) return;
|
||||
if( !isConnected ) return;
|
||||
regChannelMask = ((regChannelMask & ~( 1 << ch) ) | ( onOff << ch)) ;
|
||||
SetRegChannelMask(regChannelMask);
|
||||
|
@ -316,6 +319,8 @@ void Digitizer::SetRegChannelOnOff(unsigned short ch, bool onOff){
|
|||
|
||||
void Digitizer::ProgramBoard(){
|
||||
DebugPrint("%s", "Digitizer");
|
||||
if( softwareDisable ) return;
|
||||
if( AcqRun ) return;
|
||||
if( DPPType == DPPTypeCode::DPP_PHA_CODE ) ProgramBoard_PHA();
|
||||
if( DPPType == DPPTypeCode::DPP_PSD_CODE ) ProgramBoard_PSD();
|
||||
if( DPPType == DPPTypeCode::DPP_QDC_CODE ) ProgramBoard_QDC();
|
||||
|
@ -323,7 +328,6 @@ void Digitizer::ProgramBoard(){
|
|||
|
||||
int Digitizer::ProgramBoard_PHA(){
|
||||
DebugPrint("%s", "Digitizer");
|
||||
if( softwareDisable ) return 0;
|
||||
|
||||
printf("===== Digitizer::%s\n", __func__);
|
||||
|
||||
|
@ -402,8 +406,6 @@ int Digitizer::ProgramBoard_PHA(){
|
|||
}
|
||||
|
||||
int Digitizer::ProgramBoard_PSD(){
|
||||
if( softwareDisable ) return 0;
|
||||
|
||||
printf("===== Digitizer::%s\n", __func__);
|
||||
|
||||
//ret = CAEN_DGTZ_Reset(handle);
|
||||
|
@ -437,6 +439,12 @@ int Digitizer::ProgramBoard_PSD(){
|
|||
ret |= CAEN_DGTZ_SetChannelDCOffset(handle, 0xF, 0xAAAA);
|
||||
}
|
||||
|
||||
ret |= CAEN_DGTZ_WriteRegister(handle, (uint32_t)(DPP::PSD::DPPAlgorithmControl2_G) + 0x7000 , 0x00000200 ); // use fine time
|
||||
|
||||
ret |= CAEN_DGTZ_WriteRegister(handle, (uint32_t)(DPP::DPPAlgorithmControl) + 0x7000 , 0x00100000 ); // baseline 16 sample
|
||||
|
||||
ret |= CAEN_DGTZ_WriteRegister(handle, (uint32_t)(DPP::PSD::TriggerThreshold) + 0x7000 , 100 );
|
||||
|
||||
ret |= CAEN_DGTZ_WriteRegister(handle, (uint32_t)(DPP::PreTrigger) + 0x7000 , 20 );
|
||||
ret |= CAEN_DGTZ_WriteRegister(handle, (uint32_t)(DPP::RecordLength_G) + 0x7000 , 80 );
|
||||
|
||||
|
@ -461,8 +469,6 @@ int Digitizer::ProgramBoard_PSD(){
|
|||
}
|
||||
|
||||
int Digitizer::ProgramBoard_QDC(){
|
||||
if( softwareDisable ) return 0;
|
||||
|
||||
printf("===== Digitizer::%s\n", __func__);
|
||||
Reset();
|
||||
|
||||
|
@ -568,14 +574,13 @@ void Digitizer::StartACQ(){
|
|||
|
||||
}
|
||||
|
||||
AcqRun = true;
|
||||
data->ClearTriggerRate();
|
||||
data->ClearData();
|
||||
|
||||
if( DPPType == DPPTypeCode::DPP_QDC_CODE ) SetOptimialAggOrg();
|
||||
|
||||
printf(" ACQ mode : %s (%d), TRG-OUT mode : %s (%d) \n", acqStr.c_str(), acqID, trgOutStr.c_str(), trgOutID);
|
||||
|
||||
AcqRun = true;
|
||||
usleep(1000); // wait for 1 msec to start/Arm ACQ;
|
||||
|
||||
ret = CAEN_DGTZ_SWStartAcquisition(handle);
|
||||
|
@ -603,6 +608,8 @@ void Digitizer::StopACQ(){
|
|||
data->ClearBuffer();
|
||||
data->ClearReferenceTime();
|
||||
data->ZeroTotalFileSize();
|
||||
|
||||
ReadACQStatus();
|
||||
}
|
||||
|
||||
unsigned int Digitizer::CalByteForBuffer(bool verbose){
|
||||
|
@ -667,7 +674,7 @@ unsigned int Digitizer::CalByteForBufferCAEN(){
|
|||
uint32_t AllocatedSize;
|
||||
ret = CAEN_DGTZ_MallocReadoutBuffer(handle, &BufferCAEN, &AllocatedSize);
|
||||
|
||||
delete BufferCAEN;
|
||||
if( BufferCAEN) delete BufferCAEN;
|
||||
return AllocatedSize;
|
||||
|
||||
}
|
||||
|
@ -723,6 +730,7 @@ void Digitizer::ReadAndPrintACQStatue(){
|
|||
//===========================================================
|
||||
void Digitizer::WriteRegister (Reg registerAddress, uint32_t value, int ch, bool isSave2MemAndFile){
|
||||
if( softwareDisable ) return;
|
||||
if( AcqRun ) return;
|
||||
printf("WRITE|%30s[0x%04X](digi-%d,ch-%02d) [0x%04X]: 0x%08X \n", registerAddress.GetNameChar(), registerAddress.GetAddress(),GetSerialNumber(), ch, registerAddress.ActualAddress(ch), value);
|
||||
|
||||
if( !isConnected ) {
|
||||
|
@ -769,6 +777,7 @@ void Digitizer::WriteRegister (Reg registerAddress, uint32_t value, int ch, bool
|
|||
uint32_t Digitizer::ReadRegister(Reg registerAddress, unsigned short ch, bool isSave2MemAndFile, std::string str ){
|
||||
DebugPrint("%s", "Digitizer");
|
||||
if( softwareDisable ) return 0;
|
||||
if( AcqRun ) return 0;
|
||||
if( !isConnected ) return 0;
|
||||
if( registerAddress.GetRWType() == RW::WriteONLY ) return 0;
|
||||
// if( registerAddress == DPP::QDC::RecordLength_W ) return 0;
|
||||
|
@ -857,8 +866,8 @@ Reg Digitizer::FindRegister(uint32_t address){
|
|||
|
||||
void Digitizer::ReadAllSettingsFromBoard(bool force){
|
||||
if( softwareDisable ) return;
|
||||
if( !isConnected ) return;
|
||||
if( AcqRun ) return;
|
||||
if( !isConnected ) return;
|
||||
if( isSettingFilledinMemeory && !force) return;
|
||||
|
||||
printf("===== Digitizer(%d)::%s \n", GetSerialNumber(), __func__);
|
||||
|
@ -917,6 +926,7 @@ void Digitizer::ReadAllSettingsFromBoard(bool force){
|
|||
void Digitizer::ProgramSettingsToBoard(){
|
||||
DebugPrint("%s", "Digitizer");
|
||||
if( softwareDisable ) return;
|
||||
if( AcqRun ) return;
|
||||
if( !isConnected || isDummy ) return;
|
||||
|
||||
printf("========== %s \n", __func__);
|
||||
|
@ -1005,6 +1015,7 @@ void Digitizer::ProgramSettingsToBoard(){
|
|||
}
|
||||
|
||||
void Digitizer::SetSettingToMemory(Reg registerAddress, unsigned int value, unsigned short ch ){
|
||||
if( AcqRun ) return;
|
||||
DebugPrint("%s", "Digitizer");
|
||||
unsigned short index = registerAddress.Index(ch);
|
||||
if( index > SETTINGSIZE ) return;
|
||||
|
@ -1300,6 +1311,7 @@ void Digitizer::ErrorMsg(std::string header){
|
|||
void Digitizer::SetDPPAlgorithmControl(uint32_t bit, int ch){
|
||||
DebugPrint("%s", "Digitizer");
|
||||
if( softwareDisable ) return;
|
||||
if( AcqRun ) return;
|
||||
WriteRegister( DPP::DPPAlgorithmControl, bit, ch);
|
||||
if( ret != 0 ) ErrorMsg(__func__);
|
||||
}
|
||||
|
@ -1307,6 +1319,7 @@ void Digitizer::SetDPPAlgorithmControl(uint32_t bit, int ch){
|
|||
unsigned int Digitizer::ReadBits(Reg address, unsigned int bitLength, unsigned int bitSmallestPos, int ch ){
|
||||
DebugPrint("%s", "Digitizer");
|
||||
if( softwareDisable ) return 0;
|
||||
if( AcqRun ) return 0;
|
||||
int tempCh = ch;
|
||||
if (ch < 0 && address < 0x8000 ) tempCh = 0; /// take ch-0
|
||||
uint32_t bit = ReadRegister(address, tempCh);
|
||||
|
@ -1317,6 +1330,7 @@ unsigned int Digitizer::ReadBits(Reg address, unsigned int bitLength, unsigned i
|
|||
void Digitizer::SetBits(Reg address, unsigned int bitValue, unsigned int bitLength, unsigned int bitSmallestPos, int ch){
|
||||
DebugPrint("%s", "Digitizer");
|
||||
if( softwareDisable ) return;
|
||||
if( AcqRun ) return;
|
||||
///printf("address : 0x%X, value : 0x%X, len : %d, pos : %d, ch : %d \n", address, bitValue, bitLength, bitSmallestPos, ch);
|
||||
uint32_t bit ;
|
||||
uint32_t bitmask = (uint(pow(2, bitLength)-1) << bitSmallestPos);
|
||||
|
@ -1361,7 +1375,6 @@ void Digitizer::SetOptimialAggOrg(){
|
|||
printf(" Record Length (bit) : %u = %u sample = %u ns\n", RecordLen, RecordLen*8, RecordLen*8*16);
|
||||
printf("==============================================================\n");
|
||||
|
||||
|
||||
int eventSize = 6 + 2 * Ex + traceOn * RecordLen * 8; // sample
|
||||
printf(" estimated event size : %d sample \n", eventSize);
|
||||
double maxAggOrg = log2( MemorySizekSample * 1024 / eventSize / EventAgg );
|
||||
|
|
|
@ -206,6 +206,10 @@ class Digitizer{
|
|||
return returnData;
|
||||
}
|
||||
|
||||
void SetTrace(bool onOff){
|
||||
SetBits(DPP::BoardConfiguration, DPP::Bit_BoardConfig::RecordTrace, onOff, -1);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -69,7 +69,6 @@ public:
|
|||
digi->WriteRegister(DPP::SoftwareClear_W, 1);
|
||||
digi->GetData()->ClearData();
|
||||
}
|
||||
digi->ReadACQStatus();
|
||||
digiMTX[ID].unlock();
|
||||
emit sendMsg("Digi-" + QString::number(digi->GetSerialNumber()) + " ACQ off.");
|
||||
stop = true;
|
||||
|
@ -119,6 +118,7 @@ public:
|
|||
waitTime = 20; // multiple of 100 mili sec
|
||||
stop = false;
|
||||
}
|
||||
bool isStopped() const {return stop;}
|
||||
void Stop() { this->stop = true;}
|
||||
void SetWaitTimeinSec(float sec) {waitTime = sec * 10 ;}
|
||||
float GetWaitTimeinSec() const {return waitTime/10.;}
|
||||
|
|
|
@ -7,6 +7,8 @@
|
|||
#include <QDir>
|
||||
#include <QFileDialog>
|
||||
#include <QSortFilterProxyModel>
|
||||
#include <QApplication>
|
||||
#include <QScreen>
|
||||
|
||||
#define ComBoxMixed "Mixed"
|
||||
// bit = 0, bit = 1
|
||||
|
@ -38,7 +40,16 @@ DigiSettingsPanel::DigiSettingsPanel(Digitizer ** digi, unsigned int nDigi, QStr
|
|||
enableSignalSlot = false;
|
||||
|
||||
setWindowTitle("Digitizer Settings");
|
||||
setGeometry(0, 0, 1700, 850);
|
||||
|
||||
//====== resize window if screen too small
|
||||
QScreen * screen = QGuiApplication::primaryScreen();
|
||||
QRect screenGeo = screen->geometry();
|
||||
if( screenGeo.width() < 1700 || screenGeo.height() < 850) {
|
||||
setGeometry(0, 0, screenGeo.width() - 100, screenGeo.height() - 100);
|
||||
}else{
|
||||
setGeometry(0, 0, 1700, 850);
|
||||
}
|
||||
// setGeometry(0, 0, 1700, 850);
|
||||
|
||||
tabWidget = new QTabWidget(this);
|
||||
setCentralWidget(tabWidget);
|
||||
|
@ -185,9 +196,9 @@ DigiSettingsPanel::DigiSettingsPanel(Digitizer ** digi, unsigned int nDigi, QStr
|
|||
|
||||
{//^======================= Buttons
|
||||
|
||||
QWidget * buttonsWidget = new QWidget(tab);
|
||||
tabLayout_V1->addWidget(buttonsWidget);
|
||||
QGridLayout * buttonLayout = new QGridLayout(buttonsWidget);
|
||||
buttonsWidget[iDigi] = new QWidget(tab);
|
||||
tabLayout_V1->addWidget(buttonsWidget[iDigi]);
|
||||
QGridLayout * buttonLayout = new QGridLayout(buttonsWidget[iDigi]);
|
||||
buttonLayout->setSpacing(2);
|
||||
|
||||
int rowID = 0 ;
|
||||
|
@ -258,7 +269,7 @@ DigiSettingsPanel::DigiSettingsPanel(Digitizer ** digi, unsigned int nDigi, QStr
|
|||
// connect(bnSaveSettingsToText, &QPushButton::clicked, this, [=](){ SaveSetting(1);});
|
||||
|
||||
//checkBox, to coupled or decouple the setting file.
|
||||
chkCoupledSettingFile = new QCheckBox("Update Setting", this);
|
||||
chkCoupledSettingFile = new QCheckBox("Live Setting Update", this);
|
||||
buttonLayout->addWidget(chkCoupledSettingFile, rowID, 2);
|
||||
chkCoupledSettingFile->setCheckState(Qt::CheckState::Unchecked);
|
||||
connect(chkCoupledSettingFile, &QCheckBox::stateChanged, this, [=](int state){
|
||||
|
@ -358,7 +369,8 @@ DigiSettingsPanel::DigiSettingsPanel(Digitizer ** digi, unsigned int nDigi, QStr
|
|||
//If any digitizer is running ACQ, disable the panel.
|
||||
for( unsigned int iDigi = 0; iDigi < nDigi; iDigi ++){
|
||||
if( digi[iDigi]->IsRunning() ) {
|
||||
this->setEnabled(false);
|
||||
// this->setEnabled(false);
|
||||
EnableButtons(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -1366,6 +1378,7 @@ void DigiSettingsPanel::SetUpChannelMask(unsigned int digiID){
|
|||
|
||||
connect(bnChEnableMask[digiID][i], &QPushButton::clicked, this, [=](){
|
||||
if( !enableSignalSlot) return;
|
||||
if( digi[digiID]->IsRunning() ) return;
|
||||
|
||||
if( bnChEnableMask[digiID][i]->styleSheet() == "" ){
|
||||
bnChEnableMask[digiID][i]->setStyleSheet("background-color : green;");
|
||||
|
@ -2486,7 +2499,7 @@ void DigiSettingsPanel::SetUpChannel_PSD(){
|
|||
QLabel * lb4 = new QLabel("Veto Width", this); lb4->setAlignment(Qt::AlignHCenter); tabLayout->addWidget(lb4, 0, 6);
|
||||
QLabel * lb5 = new QLabel("Veto Step", this); lb5->setAlignment(Qt::AlignHCenter); tabLayout->addWidget(lb5, 0, 8);
|
||||
}
|
||||
SetUpComboBoxBit(cbVetoSource[ID][ch], "", tabLayout, ch + 1, 1, DPP::PHA::Bit_DPPAlgorithmControl2::ListVetoSource, DPP::PHA::DPPAlgorithmControl2_G, DPP::PHA::Bit_DPPAlgorithmControl2::VetoSource, 1, ch);
|
||||
SetUpComboBoxBit(cbVetoSource[ID][ch], "", tabLayout, ch + 1, 1, DPP::PSD::Bit_DPPAlgorithmControl2::ListVetoSource, DPP::PSD::DPPAlgorithmControl2_G, DPP::PSD::Bit_DPPAlgorithmControl2::VetoSource, 1, ch);
|
||||
SetUpComboBoxBit(cbVetoMode[ID][ch], "", tabLayout, ch + 1, 3, DPP::PSD::Bit_DPPAlgorithmControl2::ListVetoMode, DPP::PSD::DPPAlgorithmControl2_G, DPP::PSD::Bit_DPPAlgorithmControl2::VetoMode, 1, ch);
|
||||
SetUpSpinBox(sbVetoWidth[ID][ch], "", tabLayout, ch + 1, 5, DPP::VetoWidth, ch);
|
||||
SetUpComboBoxBit(cbVetoStep[ID][ch], "", tabLayout, ch + 1, 7, DPP::Bit_VetoWidth::ListVetoStep, DPP::VetoWidth, DPP::Bit_VetoWidth::VetoStep, 1, ch);
|
||||
|
@ -2497,8 +2510,8 @@ void DigiSettingsPanel::SetUpChannel_PSD(){
|
|||
QLabel * lb2 = new QLabel("Extra Option [G]", this); lb2->setAlignment(Qt::AlignHCenter); tabLayout->addWidget(lb2, 0, 2);
|
||||
QLabel * lb3 = new QLabel("TRG-OUT Ch. Prb. [G]", this); lb3->setAlignment(Qt::AlignHCenter); tabLayout->addWidget(lb3, 0, 4);
|
||||
}
|
||||
SetUpComboBoxBit(cbExtra2Option[ID][ch], "", tabLayout, ch + 1, 1, DPP::PHA::Bit_DPPAlgorithmControl2::ListExtra2, DPP::PHA::DPPAlgorithmControl2_G, DPP::PHA::Bit_DPPAlgorithmControl2::Extra2Option, 2, ch);
|
||||
SetUpComboBoxBit(cbTRGOUTChannelProbe[ID][ch], "", tabLayout, ch + 1, 3, DPP::PSD::Bit_DPPAlgorithmControl2::ListChannelProbe, DPP::PSD::DPPAlgorithmControl2_G, DPP::PSD::Bit_DPPAlgorithmControl2::ChannelProbe, 2, ch);
|
||||
SetUpComboBoxBit(cbExtra2Option[ID][ch], "", tabLayout, ch + 1, 1, DPP::PSD::Bit_DPPAlgorithmControl2::ListExtraWordOpt, DPP::PSD::DPPAlgorithmControl2_G, DPP::PSD::Bit_DPPAlgorithmControl2::ExtraWordOption, 1, ch);
|
||||
SetUpComboBoxBit(cbTRGOUTChannelProbe[ID][ch], "", tabLayout, ch + 1, 3, DPP::PSD::Bit_DPPAlgorithmControl2::ListChannelProbe, DPP::PSD::DPPAlgorithmControl2_G, DPP::PSD::Bit_DPPAlgorithmControl2::ChannelProbe, 1, ch);
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -3620,6 +3633,20 @@ void DigiSettingsPanel::SyncCheckBox(QCheckBox *(&chk)[][MaxRegChannel+1]){
|
|||
}
|
||||
}
|
||||
|
||||
void DigiSettingsPanel::EnableButtons(bool enable){
|
||||
for( int i = 0; i < nDigi; i++ ){
|
||||
if( !enable ) {
|
||||
leSaveFilePath[i]->setText("changing setting is disabled due to ACQ is running.");
|
||||
leSaveFilePath[i]->setStyleSheet("color:red;");
|
||||
}else{
|
||||
leSaveFilePath[i]->setText((QString::fromStdString(digi[i]->GetSettingFileName())));
|
||||
leSaveFilePath[i]->setStyleSheet("");
|
||||
|
||||
}
|
||||
buttonsWidget[i]->setEnabled(enable);
|
||||
}
|
||||
}
|
||||
|
||||
void DigiSettingsPanel::SyncAllChannelsTab_PHA(){
|
||||
DebugPrint("%s", "DigiSettingsPanel");
|
||||
SyncSpinBox(sbRecordLength);
|
||||
|
@ -3836,16 +3863,16 @@ void DigiSettingsPanel::UpdateSettings_PSD(){
|
|||
chkRejOverRange[ID][ch]->setChecked( Digitizer::ExtractBits(dpp, DPP::Bit_DPPAlgorithmControl_PSD::RejectOverRange));
|
||||
chkTestPule[ID][ch]->setChecked( Digitizer::ExtractBits(dpp, DPP::Bit_DPPAlgorithmControl_PSD::InternalTestPulse));
|
||||
|
||||
chkDisableOppositePulse[ID][ch]->setChecked( Digitizer::ExtractBits(dpp, DPP::Bit_DPPAlgorithmControl_PSD::DisableOppositePolarityInhibitZeroCrossingOnCFD));
|
||||
chkDisableSelfTrigger[ID][ch]->setChecked( Digitizer::ExtractBits(dpp, DPP::Bit_DPPAlgorithmControl_PSD::DisableSelfTrigger));
|
||||
chkRejPileUp[ID][ch]->setChecked( Digitizer::ExtractBits(dpp, DPP::Bit_DPPAlgorithmControl_PSD::RejectPileup));
|
||||
chkPileUpInGate[ID][ch]->setChecked( Digitizer::ExtractBits(dpp, DPP::Bit_DPPAlgorithmControl_PSD::PileupWithinGate));
|
||||
chkDisableTriggerHysteresis[ID][ch]->setChecked( Digitizer::ExtractBits(dpp, DPP::Bit_DPPAlgorithmControl_PSD::DisableTriggerHysteresis));
|
||||
|
||||
uint32_t dpp2 = digi[ID]->GetSettingFromMemory(DPP::PSD::DPPAlgorithmControl2_G, ch);
|
||||
|
||||
chkDisableOppositePulse[ID][ch]->setChecked( Digitizer::ExtractBits(dpp2, DPP::Bit_DPPAlgorithmControl_PSD::DisableOppositePolarityInhibitZeroCrossingOnCFD));
|
||||
chkDisableSelfTrigger[ID][ch]->setChecked( Digitizer::ExtractBits(dpp2, DPP::Bit_DPPAlgorithmControl_PSD::DisableSelfTrigger));
|
||||
chkRejPileUp[ID][ch]->setChecked( Digitizer::ExtractBits(dpp2, DPP::Bit_DPPAlgorithmControl_PSD::RejectPileup));
|
||||
chkPileUpInGate[ID][ch]->setChecked( Digitizer::ExtractBits(dpp2, DPP::Bit_DPPAlgorithmControl_PSD::PileupWithinGate));
|
||||
chkDisableTriggerHysteresis[ID][ch]->setChecked( Digitizer::ExtractBits(dpp2, DPP::Bit_DPPAlgorithmControl_PSD::DisableTriggerHysteresis));
|
||||
chkMarkSaturation[ID][ch]->setChecked( Digitizer::ExtractBits(dpp2, DPP::PSD::Bit_DPPAlgorithmControl2::MarkSaturation));
|
||||
chkResetTimestampByTRGIN[ID][ch]->setChecked( Digitizer::ExtractBits(dpp2, DPP::PSD::Bit_DPPAlgorithmControl2::ResetTimestampByTRGIN));
|
||||
|
||||
chkMarkSaturation[ID][ch]->setChecked( Digitizer::ExtractBits(dpp, DPP::PSD::Bit_DPPAlgorithmControl2::MarkSaturation));
|
||||
chkResetTimestampByTRGIN[ID][ch]->setChecked( Digitizer::ExtractBits(dpp, DPP::PSD::Bit_DPPAlgorithmControl2::ResetTimestampByTRGIN));
|
||||
|
||||
UpdateComboBoxBit(cbLocalTriggerValid[ID][ch], dpp2, DPP::PSD::Bit_DPPAlgorithmControl2::LocalTrigValidMode);
|
||||
UpdateComboBoxBit(cbAdditionLocalTrigValid[ID][ch], dpp2, DPP::PSD::Bit_DPPAlgorithmControl2::AdditionLocalTrigValid);
|
||||
|
|
|
@ -33,6 +33,8 @@ public slots:
|
|||
void SaveSetting(int opt);
|
||||
void LoadSetting();
|
||||
|
||||
void EnableButtons(bool enable);
|
||||
|
||||
signals:
|
||||
void SendLogMsg(const QString &msg);
|
||||
void UpdateOtherPanels();
|
||||
|
@ -69,7 +71,6 @@ private:
|
|||
void SyncComboBox(RComboBox *(&cb)[][MaxRegChannel+1]);
|
||||
void SyncCheckBox(QCheckBox *(&chk)[][MaxRegChannel+1]);
|
||||
|
||||
|
||||
void SyncAllChannelsTab_PHA();
|
||||
void UpdateSettings_PHA();
|
||||
void SyncAllChannelsTab_PSD();
|
||||
|
@ -102,6 +103,8 @@ private:
|
|||
|
||||
QLineEdit * leSaveFilePath[MaxNDigitizer];
|
||||
|
||||
QWidget * buttonsWidget[MaxNDigitizer];
|
||||
|
||||
QPushButton * bnRefreshSetting; // read setting from board
|
||||
QPushButton * bnProgramPreDefined;
|
||||
QPushButton * bnClearBuffer;
|
||||
|
|
7
FSUDAQ
Executable file
7
FSUDAQ
Executable file
|
@ -0,0 +1,7 @@
|
|||
#!/bin/bash
|
||||
|
||||
timestamp=$(date +%Y%m%d_%H%M%S)
|
||||
|
||||
outFile=program_${timestamp}.log
|
||||
|
||||
stdbuf -oL ./FSUDAQ_Qt6 | tee $outFile
|
558
FSUDAQ.cpp
558
FSUDAQ.cpp
File diff suppressed because it is too large
Load Diff
73
FSUDAQ.h
73
FSUDAQ.h
|
@ -1,5 +1,5 @@
|
|||
#ifndef MAINWINDOW_H
|
||||
#define MAINWINDOW_H
|
||||
#ifndef FSUDAQ_H
|
||||
#define FSUDAQ_H
|
||||
|
||||
#include <QMainWindow>
|
||||
#include <QWidget>
|
||||
|
@ -20,12 +20,14 @@
|
|||
#include "ClassInfluxDB.h"
|
||||
#include "analyzers/Analyser.h"
|
||||
|
||||
//^#===================================================== MainWindow
|
||||
class MainWindow : public QMainWindow{
|
||||
class ScalarWorker; //Forward declaration
|
||||
|
||||
//^#===================================================== FSUDAQ
|
||||
class FSUDAQ : public QMainWindow{
|
||||
Q_OBJECT
|
||||
public:
|
||||
MainWindow(QWidget *parent = nullptr);
|
||||
~MainWindow();
|
||||
FSUDAQ(QWidget *parent = nullptr);
|
||||
~FSUDAQ();
|
||||
|
||||
void closeEvent(QCloseEvent * event){
|
||||
if( scope ) {
|
||||
|
@ -36,9 +38,9 @@ public:
|
|||
delete digiSettings;
|
||||
digiSettings = nullptr;
|
||||
}
|
||||
if( canvas ) {
|
||||
delete canvas;
|
||||
canvas = nullptr;
|
||||
if( singleHistograms ) {
|
||||
delete singleHistograms;
|
||||
singleHistograms = nullptr;
|
||||
}
|
||||
if( onlineAnalyzer ) {
|
||||
delete onlineAnalyzer;
|
||||
|
@ -47,6 +49,9 @@ public:
|
|||
event->accept();
|
||||
}
|
||||
|
||||
public slots:
|
||||
void UpdateScalar();
|
||||
|
||||
private slots:
|
||||
|
||||
void OpenDataPath();
|
||||
|
@ -64,7 +69,6 @@ private slots:
|
|||
void SetupScalar();
|
||||
void CleanUpScalar();
|
||||
void OpenScalar();
|
||||
void UpdateScalar();
|
||||
|
||||
void StartACQ();
|
||||
void StopACQ();
|
||||
|
@ -76,7 +80,7 @@ private slots:
|
|||
|
||||
void OpenDigiSettings();
|
||||
|
||||
void OpenCanvas();
|
||||
void OpenSingleHistograms();
|
||||
|
||||
void OpenAnalyzer();
|
||||
|
||||
|
@ -96,6 +100,7 @@ private:
|
|||
|
||||
Digitizer ** digi;
|
||||
unsigned int nDigi;
|
||||
bool isACQStarted;
|
||||
|
||||
QString programSettingsFilePath;
|
||||
QString rawDataPath;
|
||||
|
@ -145,6 +150,9 @@ private:
|
|||
QLineEdit * leElogIP;
|
||||
QLineEdit * leElogName;
|
||||
|
||||
QCheckBox * chkInflux;
|
||||
QCheckBox * chkElog;
|
||||
|
||||
//@----- log msg
|
||||
QPlainTextEdit * logInfo;
|
||||
void LogMsg(QString msg);
|
||||
|
@ -165,7 +173,13 @@ private:
|
|||
//@----- Scalar
|
||||
QMainWindow * scalar;
|
||||
QGridLayout * scalarLayout;
|
||||
TimingThread * scalarThread;
|
||||
TimingThread * scalarTimingThread;
|
||||
// QThread * scalarThread;
|
||||
// ScalarWorker * scalarWorker;
|
||||
// QTimer * scalarTimer;
|
||||
|
||||
|
||||
// TimingThread * scalarThread;
|
||||
QLineEdit *** leTrigger; // need to delete manually
|
||||
QLineEdit *** leAccept; // need to delete manually
|
||||
QPushButton * runStatus[MaxNDigitizer];
|
||||
|
@ -190,14 +204,45 @@ private:
|
|||
DigiSettingsPanel * digiSettings;
|
||||
|
||||
//@----- SingleSpectra
|
||||
SingleSpectra * canvas;
|
||||
TimingThread * histThread;
|
||||
SingleSpectra * singleHistograms;
|
||||
|
||||
//@----- Analyzer
|
||||
Analyzer * onlineAnalyzer;
|
||||
|
||||
QString maskText(const QString &password) {
|
||||
if (password.length() <= 3) {
|
||||
return password; // No masking needed for short passwords
|
||||
} else if (password.length() <= 10) {
|
||||
QString maskedPassword = password.left(3);
|
||||
maskedPassword += QString("*").repeated(password.length() - 3);
|
||||
return maskedPassword;
|
||||
} else {
|
||||
return password.left(3) + QString("*").repeated(7);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
//^======================== Scalar Worker
|
||||
|
||||
// class ScalarWorker : public QObject{
|
||||
// Q_OBJECT
|
||||
// public:
|
||||
// ScalarWorker(FSUDAQ * parent): SS(parent){}
|
||||
|
||||
// public slots:
|
||||
// void UpdateScalar(){
|
||||
// SS->UpdateScalar();
|
||||
// emit workDone();
|
||||
// }
|
||||
|
||||
// signals:
|
||||
// void workDone();
|
||||
|
||||
// private:
|
||||
// FSUDAQ * SS;
|
||||
// };
|
||||
|
||||
|
||||
#endif // MAINWINDOW_H
|
|
@ -11,9 +11,9 @@ QT += core widgets charts printsupport
|
|||
LIBS += -lCAENDigitizer -lcurl
|
||||
|
||||
#==== for enable GDB debug
|
||||
#QMAKE_CXXFLAGS += -g
|
||||
#QMAKE_CXXFLAGS_RELEASE = -O0
|
||||
#QMAKE_CFLAGS_RELEASE = -O0
|
||||
QMAKE_CXXFLAGS += -g
|
||||
QMAKE_CXXFLAGS_RELEASE = -O0
|
||||
QMAKE_CFLAGS_RELEASE = -O0
|
||||
|
||||
# You can make your code fail to compile if you use deprecated APIs.
|
||||
# In order to do so, uncomment the following line.
|
||||
|
@ -25,34 +25,37 @@ LIBS += -lCAENDigitizer -lcurl
|
|||
# Input
|
||||
HEADERS += ClassData.h \
|
||||
ClassDigitizer.h \
|
||||
ClassInfluxDB.h\
|
||||
CustomThreads.h \
|
||||
CustomWidgets.h \
|
||||
Histogram1D.h \
|
||||
Histogram2D.h \
|
||||
DigiSettingsPanel.h \
|
||||
FSUDAQ.h \
|
||||
macro.h \
|
||||
RegisterAddress.h \
|
||||
ClassInfluxDB.h\
|
||||
Scope.h \
|
||||
SingleSpectra.h \
|
||||
Histogram1D.h \
|
||||
Histogram2D.h \
|
||||
Hit.h \
|
||||
macro.h \
|
||||
MultiBuilder.h \
|
||||
qcustomplot.h \
|
||||
analyzers/Isotope.h \
|
||||
RegisterAddress.h \
|
||||
Scope.h \
|
||||
SingleSpectra.h \
|
||||
analyzers/Analyser.h \
|
||||
analyzers/BeamTune.h\
|
||||
analyzers/CoincidentAnalyzer.h \
|
||||
analyzers/SplitPoleAnalyzer.h \
|
||||
analyzers/Cross.h\
|
||||
analyzers/EncoreAnalyzer.h \
|
||||
analyzers/Isotope.h \
|
||||
analyzers/MCP.h \
|
||||
analyzers/MCPandPSD.h \
|
||||
analyzers/PID.h \
|
||||
analyzers/RAISOR1.h \
|
||||
analyzers/RAISOR2.h \
|
||||
analyzers/TEST.h \
|
||||
analyzers/MCPandPSD.h \
|
||||
analyzers/MCP.h \
|
||||
analyzers/Cross.h\
|
||||
analyzers/SplitPoleAnalyzer.h \
|
||||
analyzers/Target.h\
|
||||
analyzers/BeamTune.h\
|
||||
analyzers/PID.h
|
||||
analyzers/TEST.h \
|
||||
analyzers/MUSICAnalyzer.h \
|
||||
analyzers/NeutronGamma.h
|
||||
|
||||
SOURCES += ClassDigitizer.cpp \
|
||||
DigiSettingsPanel.cpp \
|
||||
FSUDAQ.cpp \
|
||||
|
|
|
@ -15,6 +15,8 @@ public:
|
|||
// DebugPrint("%s", "Histogram1D");
|
||||
isLogY = false;
|
||||
|
||||
for( int i = 0; i < MaxNHist; i++ ) showHist[i] = true;
|
||||
|
||||
for( int i = 0; i < 3; i ++) txt[i] = nullptr;
|
||||
nData = 1;
|
||||
Rebin(xbin, xmin, xmax);
|
||||
|
@ -86,12 +88,15 @@ public:
|
|||
|
||||
QAction * a1 = menu.addAction("UnZoom");
|
||||
QAction * a5 = menu.addAction("Set/UnSet Log-y");
|
||||
QAction * a6 = nullptr;
|
||||
if( nData > 1 ) a6 = menu.addAction("Toggle lines display");
|
||||
QAction * a2 = menu.addAction("Clear hist.");
|
||||
QAction * a3 = menu.addAction("Toggle Stat.");
|
||||
QAction * a4 = menu.addAction("Rebin (clear histogram)");
|
||||
//TODO fitGuass
|
||||
|
||||
QAction *selectedAction = menu.exec(event->globalPosition().toPoint());
|
||||
//*========================================== UnZoom
|
||||
if( selectedAction == a1 ){
|
||||
xAxis->setRangeLower(xMin);
|
||||
xAxis->setRangeUpper(xMax);
|
||||
|
@ -101,11 +106,13 @@ public:
|
|||
usingMenu = false;
|
||||
}
|
||||
|
||||
//*========================================== Clear Hist
|
||||
if( selectedAction == a2 ){
|
||||
Clear();
|
||||
usingMenu = false;
|
||||
}
|
||||
|
||||
//*========================================== Toggle Stat.
|
||||
if( selectedAction == a3 ){
|
||||
for( int i = 0; i < 3; i++){
|
||||
txt[i]->setVisible( !txt[i]->visible());
|
||||
|
@ -113,6 +120,7 @@ public:
|
|||
replot();
|
||||
usingMenu = false;
|
||||
}
|
||||
//*========================================== Rebin
|
||||
if( selectedAction == a4 ){
|
||||
QDialog dialog(this);
|
||||
dialog.setWindowTitle("Rebin histogram");
|
||||
|
@ -145,25 +153,25 @@ public:
|
|||
double number[3];
|
||||
|
||||
QObject::connect(&buttonBox, &QDialogButtonBox::accepted, [&]() {
|
||||
int OKcount = 0;
|
||||
bool conversionOk = true;
|
||||
for( int i = 0; i < 3; i++ ){
|
||||
number[i] = lineEdit[i]->text().toDouble(&conversionOk);
|
||||
if( conversionOk ){
|
||||
OKcount++;
|
||||
}else{
|
||||
msg->setText(nameList[i] + " is invalid.");
|
||||
return;
|
||||
}
|
||||
int OKcount = 0;
|
||||
bool conversionOk = true;
|
||||
for( int i = 0; i < 3; i++ ){
|
||||
number[i] = lineEdit[i]->text().toDouble(&conversionOk);
|
||||
if( conversionOk ){
|
||||
OKcount++;
|
||||
}else{
|
||||
msg->setText(nameList[i] + " is invalid.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if( OKcount == 3 ) {
|
||||
if( number[2] > number[1] ) {
|
||||
dialog.accept();
|
||||
}else{
|
||||
msg->setText(nameList[2] + " is smaller than " + nameList[1]);
|
||||
}
|
||||
if( OKcount == 3 ) {
|
||||
if( number[2] > number[1] ) {
|
||||
dialog.accept();
|
||||
}else{
|
||||
msg->setText(nameList[2] + " is smaller than " + nameList[1]);
|
||||
}
|
||||
}
|
||||
});
|
||||
QObject::connect(&buttonBox, &QDialogButtonBox::rejected, [&]() { dialog.reject();});
|
||||
|
||||
|
@ -174,8 +182,38 @@ public:
|
|||
}
|
||||
|
||||
}
|
||||
if( selectedAction == a5 ){
|
||||
|
||||
//*========================================== Toggle line Display
|
||||
if( selectedAction == a6 ){
|
||||
QDialog dialog(this);
|
||||
dialog.setWindowTitle("Toggle lines Display");
|
||||
|
||||
QFormLayout layout(&dialog);
|
||||
|
||||
QCheckBox ** cbline = new QCheckBox *[nData];
|
||||
for( int i = 0; i < nData; i++ ){
|
||||
cbline[i] = new QCheckBox(graph(i)->name(), &dialog);
|
||||
layout.addRow(cbline[i]);
|
||||
if( showHist[i] ) cbline[i]->setChecked(true);
|
||||
}
|
||||
|
||||
QDialogButtonBox buttonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, &dialog);
|
||||
layout.addRow(&buttonBox);
|
||||
|
||||
QObject::connect(&buttonBox, &QDialogButtonBox::accepted, [&]() {
|
||||
for( int i = 0; i < nData; i++ ){
|
||||
showHist[i] = cbline[i]->isChecked();
|
||||
}
|
||||
dialog.accept();
|
||||
});
|
||||
QObject::connect(&buttonBox, &QDialogButtonBox::rejected, [&]() { dialog.reject();});
|
||||
|
||||
if( dialog.exec() == QDialog::Accepted ){
|
||||
UpdatePlot();
|
||||
}
|
||||
}
|
||||
//*========================================== Set Log y
|
||||
if( selectedAction == a5 ){
|
||||
if( !isLogY ){
|
||||
this->yAxis->setScaleType(QCPAxis::stLogarithmic);
|
||||
isLogY = true;
|
||||
|
@ -206,12 +244,16 @@ public:
|
|||
addGraph();
|
||||
graph(nData - 1)->setName(title);
|
||||
SetColor(color, nData-1);
|
||||
yList[nData-1] = yList[0];
|
||||
yList[nData-1].clear();
|
||||
for( int i = 0; i < xList.count(); i++) yList[nData-1].append(0);
|
||||
}
|
||||
|
||||
void UpdatePlot(){
|
||||
DebugPrint("%s", "Histogram1D");
|
||||
for( int ID = 0 ; ID < nData; ID ++) graph(ID)->setData(xList, yList[ID]);
|
||||
for( int ID = 0 ; ID < nData; ID ++) {
|
||||
graph(ID)->setVisible(showHist[ID]);
|
||||
graph(ID)->setData(xList, yList[ID]);
|
||||
}
|
||||
xAxis->setRangeLower(xMin);
|
||||
xAxis->setRangeUpper(xMax);
|
||||
yAxis->setRangeLower(0);
|
||||
|
@ -222,7 +264,7 @@ public:
|
|||
void Clear(){
|
||||
DebugPrint("%s", "Histogram1D");
|
||||
for( int ID = 0 ; ID < nData; ID ++) {
|
||||
for( int i = 0; i <= yList[ID].count(); i++) yList[ID][i] = 0;
|
||||
for( int i = 0; i < xList.count(); i++) yList[ID][i] = 0;
|
||||
}
|
||||
yMax = 0;
|
||||
txt[0]->setText("Under Flow : 0");
|
||||
|
@ -234,7 +276,7 @@ public:
|
|||
UpdatePlot();
|
||||
}
|
||||
|
||||
void SetXTitle(QString xTitle) { xAxis->setLabel(xTitle); }
|
||||
void SetXTitle(QString xTitle) { xAxis->setLabel(xTitle);}
|
||||
|
||||
void Rebin(int xbin, double xmin, double xmax){
|
||||
// DebugPrint("%s", "Histogram1D");
|
||||
|
@ -283,16 +325,18 @@ public:
|
|||
txt[2]->setText("Over Flow : "+ QString::number(overFlow));
|
||||
return;
|
||||
}
|
||||
}else{
|
||||
if( value < xMin || value > xMax ) return;
|
||||
}
|
||||
|
||||
double bin = (value - xMin)/dX;
|
||||
int index1 = 2*qFloor(bin) + 1;
|
||||
int bin = qFloor((value - xMin)/dX);
|
||||
int index1 = 2*bin + 1;
|
||||
int index2 = index1 + 1;
|
||||
|
||||
if( 0 <= index1 && index1 <= 2*xBin) yList[ID][index1] += 1;
|
||||
if( 0 <= index1 && index2 <= 2*xBin) yList[ID][index2] += 1;
|
||||
|
||||
if( yList[ID][index1] > yMax ) yMax = yList[ID][index1];
|
||||
if( showHist[ID] && yList[ID][index1] > yMax ) yMax = yList[ID][index1];
|
||||
}
|
||||
|
||||
void Print(unsigned int ID = 0){
|
||||
|
@ -324,6 +368,8 @@ private:
|
|||
|
||||
bool usingMenu;
|
||||
|
||||
bool showHist[MaxNHist];
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
|
530
Histogram2D.h
530
Histogram2D.h
|
@ -19,200 +19,20 @@ const QList<QPair<QColor, QString>> colorCycle = { {QColor(Qt::red), "Red"},
|
|||
class Histogram2D : public QCustomPlot{
|
||||
|
||||
public:
|
||||
Histogram2D(QString title, QString xLabel, QString yLabel, int xbin, double xmin, double xmax, int ybin, double ymin, double ymax, QWidget * parent = nullptr) : QCustomPlot(parent){
|
||||
// DebugPrint("%s", "Histogram2D");
|
||||
for( int i = 0; i < 3; i ++ ){
|
||||
for( int j = 0; j < 3; j ++ ){
|
||||
box[i][j] = nullptr;
|
||||
txt[i][j] = nullptr;
|
||||
}
|
||||
}
|
||||
Histogram2D(QString title, QString xLabel, QString yLabel,
|
||||
int xbin, double xmin, double xmax,
|
||||
int ybin, double ymin, double ymax,
|
||||
QWidget * parent = nullptr,
|
||||
QString defaultPath = QDir::homePath());
|
||||
|
||||
isChannelMap = false;
|
||||
tickStep = 1; // only used when isChannelMap = true
|
||||
isLogZ = false;
|
||||
|
||||
axisRect()->setupFullAxesBox(true);
|
||||
xAxis->setLabel(xLabel);
|
||||
yAxis->setLabel(yLabel);
|
||||
|
||||
colorMap = new QCPColorMap(xAxis, yAxis);
|
||||
Rebin(xbin, xmin, xmax, ybin, ymin, ymax);
|
||||
colorMap->setInterpolate(false);
|
||||
|
||||
QCPTextElement *titleEle = new QCPTextElement(this, title, QFont("sans", 12));
|
||||
plotLayout()->insertRow(0);
|
||||
plotLayout()->addElement(0, 0, titleEle);
|
||||
|
||||
colorScale = new QCPColorScale(this);
|
||||
plotLayout()->addElement(1, 1, colorScale);
|
||||
colorScale->setType(QCPAxis::atRight);
|
||||
colorMap->setColorScale(colorScale);
|
||||
|
||||
|
||||
QCPColorGradient color;
|
||||
color.setNanHandling(QCPColorGradient::NanHandling::nhNanColor);
|
||||
color.setNanColor(QColor("white"));
|
||||
color.clearColorStops();
|
||||
// color.setColorStopAt( 0.0, QColor("white" ));
|
||||
color.setColorStopAt( 0.0, QColor("purple" ));
|
||||
color.setColorStopAt( 0.2, QColor("blue"));
|
||||
color.setColorStopAt( 0.4, QColor("cyan"));
|
||||
color.setColorStopAt( 0.6, QColor("green"));
|
||||
color.setColorStopAt( 0.8, QColor("yellow"));
|
||||
color.setColorStopAt( 1.0, QColor("red"));
|
||||
colorMap->setGradient(color);
|
||||
|
||||
double xPosStart = 0.02;
|
||||
double xPosStep = 0.07;
|
||||
double yPosStart = 0.02;
|
||||
double yPosStep = 0.05;
|
||||
|
||||
for( int i = 0; i < 3; i ++ ){
|
||||
for( int j = 0; j < 3; j ++ ){
|
||||
box[i][j] = new QCPItemRect(this);
|
||||
|
||||
box[i][j]->topLeft->setType(QCPItemPosition::ptAxisRectRatio);
|
||||
box[i][j]->topLeft->setCoords(xPosStart + xPosStep*i, yPosStart + yPosStep*j);
|
||||
box[i][j]->bottomRight->setType(QCPItemPosition::ptAxisRectRatio);
|
||||
box[i][j]->bottomRight->setCoords(xPosStart + xPosStep*(i+1), yPosStart + yPosStep*(j+1));
|
||||
|
||||
txt[i][j] = new QCPItemText(this);
|
||||
txt[i][j]->setPositionAlignment(Qt::AlignLeft);
|
||||
txt[i][j]->position->setType(QCPItemPosition::ptAxisRectRatio);
|
||||
txt[i][j]->position->setCoords(xPosStart + xPosStep/2 + xPosStep*i, yPosStart + yPosStep*j);;
|
||||
txt[i][j]->setText("0");
|
||||
txt[i][j]->setFont(QFont("Helvetica", 9));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
cutList.clear();
|
||||
cutEntryList.clear();
|
||||
|
||||
rescaleAxes();
|
||||
|
||||
usingMenu = false;
|
||||
isDrawCut = false;
|
||||
tempCutID = -1;
|
||||
numCut = 0;
|
||||
lastPlottableID = -1;
|
||||
|
||||
line = new QCPItemLine(this);
|
||||
line->setPen(QPen(Qt::gray, 1, Qt::DashLine));
|
||||
line->setVisible(false);
|
||||
|
||||
isBusy = false;
|
||||
|
||||
connect(this, &QCustomPlot::mouseMove, this, [=](QMouseEvent *event){
|
||||
double x = xAxis->pixelToCoord(event->pos().x());
|
||||
double y = yAxis->pixelToCoord(event->pos().y());
|
||||
int xI, yI;
|
||||
colorMap->data()->coordToCell(x, y, &xI, &yI);
|
||||
double z = colorMap->data()->cell(xI, yI);
|
||||
|
||||
QString coordinates = QString("X: %1, Y: %2, Z: %3").arg(x).arg(y).arg(z);
|
||||
QToolTip::showText(event->globalPosition().toPoint(), coordinates, this);
|
||||
|
||||
//when drawing cut, show dashhed line
|
||||
if( isDrawCut && tempCut.size() > 0 ){
|
||||
line->end->setCoords(x,y);
|
||||
line->setVisible(true);
|
||||
replot();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
connect(this, &QCustomPlot::mousePress, this, [=](QMouseEvent * event){
|
||||
|
||||
if (event->button() == Qt::LeftButton && !usingMenu && !isDrawCut){
|
||||
setSelectionRectMode(QCP::SelectionRectMode::srmZoom);
|
||||
}
|
||||
|
||||
if (event->button() == Qt::LeftButton && isDrawCut){
|
||||
|
||||
oldMouseX = xAxis->pixelToCoord(event->pos().x());
|
||||
oldMouseY = yAxis->pixelToCoord(event->pos().y());
|
||||
|
||||
tempCut.push_back(QPointF(oldMouseX,oldMouseY));
|
||||
|
||||
line->start->setCoords(oldMouseX, oldMouseY);
|
||||
line->end->setCoords(oldMouseX, oldMouseY);
|
||||
line->setVisible(true);
|
||||
|
||||
DrawCut();
|
||||
}
|
||||
|
||||
//^================= right click
|
||||
if (event->button() == Qt::RightButton) rightMouseClickMenu(event);
|
||||
});
|
||||
|
||||
//connect( this, &QCustomPlot::mouseDoubleClick, this, [=](QMouseEvent *event){
|
||||
connect( this, &QCustomPlot::mouseDoubleClick, this, [=](){
|
||||
if( isDrawCut) {
|
||||
tempCut.push_back(tempCut[0]);
|
||||
DrawCut();
|
||||
isDrawCut = false;
|
||||
line->setVisible(false);
|
||||
|
||||
plottableIDList.push_back(plottableCount() -1 );
|
||||
|
||||
cutNameList.push_back("Cut-" + QString::number(cutList.count()));
|
||||
cutEntryList.push_back(0);
|
||||
|
||||
QCPItemText * text = new QCPItemText(this);
|
||||
text->setText(cutNameList.last());
|
||||
text->position->setCoords(tempCut[0].rx(), tempCut[0].ry());
|
||||
int colorID = tempCutID% colorCycle.count();
|
||||
text->setColor(colorCycle[colorID].first);
|
||||
cutTextIDList.push_back(itemCount() - 1);
|
||||
|
||||
replot();
|
||||
|
||||
cutList.push_back(tempCut);
|
||||
cutIDList.push_back(tempCutID);
|
||||
|
||||
// qDebug() << "----------- end of create cut";
|
||||
// qDebug() << " cutIDList " << cutIDList ;
|
||||
// qDebug() << "plottableIDList " << plottableIDList << ", " << plottableCount();
|
||||
// qDebug() << " cutTextIDList " << cutTextIDList << ", " << itemCount();
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
connect(this, &QCustomPlot::mouseRelease, this, [=](){
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
//^===================================
|
||||
|
||||
void SetXTitle(QString xTitle) { xAxis->setLabel(xTitle); }
|
||||
void SetYTitle(QString yTitle) { yAxis->setLabel(yTitle); }
|
||||
void SetXTitle(QString xTitle) { xAxis->setLabel(xTitle);}
|
||||
void SetYTitle(QString yTitle) { yAxis->setLabel(yTitle);}
|
||||
void Rebin(int xbin, double xmin, double xmax, int ybin, double ymin, double ymax);
|
||||
void RebinY(int ybin, double ymin, double ymax);
|
||||
|
||||
void SetChannelMap(bool onOff, int tickStep = 1) { isChannelMap = onOff; this->tickStep = tickStep;}
|
||||
|
||||
void UpdatePlot(){
|
||||
// QCPColorGradient color;
|
||||
// color.clearColorStops();
|
||||
// color.setNanColor(QColor("white"));
|
||||
// // color.setColorStopAt( 0.0, QColor("white" ));
|
||||
// // color.setColorStopAt( 1.0/entry[1][1], QColor("purple" ));
|
||||
// color.setColorStopAt( 0.0, QColor("purple" ));
|
||||
// color.setColorStopAt( 0.2, QColor("blue"));
|
||||
// color.setColorStopAt( 0.4, QColor("cyan"));
|
||||
// color.setColorStopAt( 0.6, QColor("green"));
|
||||
// color.setColorStopAt( 0.8, QColor("yellow"));
|
||||
// color.setColorStopAt( 1.0, QColor("red"));
|
||||
// colorMap->setGradient(color);
|
||||
|
||||
colorMap->rescaleDataRange();
|
||||
|
||||
replot();
|
||||
}
|
||||
|
||||
void UpdatePlot(){ colorMap->rescaleDataRange(); replot(); }
|
||||
void Clear(); // Clear Data and histrogram
|
||||
|
||||
void Fill(double x, double y);
|
||||
|
@ -232,6 +52,9 @@ public:
|
|||
double GetYMin() const {return yMin;}
|
||||
double GetYMax() const {return yMax;}
|
||||
|
||||
void SaveCuts(QString cutFileName);
|
||||
void LoadCuts(QString cutFileName);
|
||||
|
||||
private:
|
||||
double xMin, xMax, yMin, yMax;
|
||||
int xBin, yBin;
|
||||
|
@ -252,15 +75,15 @@ private:
|
|||
|
||||
QPolygonF tempCut;
|
||||
int tempCutID; // only incresing;
|
||||
QList<QPolygonF> cutList;
|
||||
QList<int> cutIDList;
|
||||
int numCut;
|
||||
QList<QPolygonF> cutList;
|
||||
QList<QString> cutNameList; // name of the cut
|
||||
QList<int> cutEntryList; // number of entry inside the cut.
|
||||
QList<int> cutIDList; // ID of the cut
|
||||
QList<int> cutTextIDList; //
|
||||
QList<int> plottableIDList;
|
||||
bool isDrawCut;
|
||||
int lastPlottableID;
|
||||
QList<int> cutTextIDList;
|
||||
QList<int> plottableIDList;
|
||||
QList<QString> cutNameList;
|
||||
QList<int> cutEntryList;
|
||||
|
||||
QCPItemLine * line;
|
||||
double oldMouseX = 0.0, oldMouseY = 0.0;
|
||||
|
@ -270,11 +93,183 @@ private:
|
|||
void rightMouseClickMenu(QMouseEvent * event);
|
||||
void rightMouseClickRebin();
|
||||
|
||||
QString settingPath;
|
||||
|
||||
};
|
||||
|
||||
//^###############################################
|
||||
//^###############################################
|
||||
|
||||
inline Histogram2D::Histogram2D(QString title, QString xLabel, QString yLabel, int xbin, double xmin, double xmax, int ybin, double ymin, double ymax, QWidget * parent, QString defaultPath) : QCustomPlot(parent){
|
||||
// DebugPrint("%s", "Histogram2D");
|
||||
|
||||
settingPath = defaultPath;
|
||||
for( int i = 0; i < 3; i ++ ){
|
||||
for( int j = 0; j < 3; j ++ ){
|
||||
box[i][j] = nullptr;
|
||||
txt[i][j] = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
isChannelMap = false;
|
||||
tickStep = 1; // only used when isChannelMap = true
|
||||
isLogZ = false;
|
||||
|
||||
axisRect()->setupFullAxesBox(true);
|
||||
xAxis->setLabel(xLabel);
|
||||
yAxis->setLabel(yLabel);
|
||||
|
||||
colorMap = new QCPColorMap(xAxis, yAxis);
|
||||
Rebin(xbin, xmin, xmax, ybin, ymin, ymax);
|
||||
colorMap->setInterpolate(false);
|
||||
|
||||
QCPTextElement *titleEle = new QCPTextElement(this, title, QFont("sans", 12));
|
||||
plotLayout()->insertRow(0);
|
||||
plotLayout()->addElement(0, 0, titleEle);
|
||||
|
||||
colorScale = new QCPColorScale(this);
|
||||
plotLayout()->addElement(1, 1, colorScale);
|
||||
colorScale->setType(QCPAxis::atRight);
|
||||
colorMap->setColorScale(colorScale);
|
||||
|
||||
|
||||
QCPColorGradient color;
|
||||
color.setNanHandling(QCPColorGradient::NanHandling::nhNanColor);
|
||||
color.setNanColor(QColor("white"));
|
||||
color.clearColorStops();
|
||||
// color.setColorStopAt( 0.0, QColor("white" ));
|
||||
color.setColorStopAt( 0.0, QColor("purple" ));
|
||||
color.setColorStopAt( 0.2, QColor("blue"));
|
||||
color.setColorStopAt( 0.4, QColor("cyan"));
|
||||
color.setColorStopAt( 0.6, QColor("green"));
|
||||
color.setColorStopAt( 0.8, QColor("yellow"));
|
||||
color.setColorStopAt( 1.0, QColor("red"));
|
||||
colorMap->setGradient(color);
|
||||
|
||||
double xPosStart = 0.02;
|
||||
double xPosStep = 0.07;
|
||||
double yPosStart = 0.02;
|
||||
double yPosStep = 0.05;
|
||||
|
||||
for( int i = 0; i < 3; i ++ ){
|
||||
for( int j = 0; j < 3; j ++ ){
|
||||
box[i][j] = new QCPItemRect(this);
|
||||
|
||||
box[i][j]->topLeft->setType(QCPItemPosition::ptAxisRectRatio);
|
||||
box[i][j]->topLeft->setCoords(xPosStart + xPosStep*i, yPosStart + yPosStep*j);
|
||||
box[i][j]->bottomRight->setType(QCPItemPosition::ptAxisRectRatio);
|
||||
box[i][j]->bottomRight->setCoords(xPosStart + xPosStep*(i+1), yPosStart + yPosStep*(j+1));
|
||||
|
||||
txt[i][j] = new QCPItemText(this);
|
||||
txt[i][j]->setPositionAlignment(Qt::AlignLeft);
|
||||
txt[i][j]->position->setType(QCPItemPosition::ptAxisRectRatio);
|
||||
txt[i][j]->position->setCoords(xPosStart + xPosStep/2 + xPosStep*i, yPosStart + yPosStep*j);;
|
||||
txt[i][j]->setText("0");
|
||||
txt[i][j]->setFont(QFont("Helvetica", 9));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
cutList.clear();
|
||||
cutEntryList.clear();
|
||||
|
||||
rescaleAxes();
|
||||
|
||||
usingMenu = false;
|
||||
isDrawCut = false;
|
||||
tempCutID = -1;
|
||||
numCut = 0;
|
||||
lastPlottableID = -1;
|
||||
|
||||
line = new QCPItemLine(this);
|
||||
line->setPen(QPen(Qt::gray, 1, Qt::DashLine));
|
||||
line->setVisible(false);
|
||||
|
||||
isBusy = false;
|
||||
|
||||
connect(this, &QCustomPlot::mouseMove, this, [=](QMouseEvent *event){
|
||||
double x = xAxis->pixelToCoord(event->pos().x());
|
||||
double y = yAxis->pixelToCoord(event->pos().y());
|
||||
int xI, yI;
|
||||
colorMap->data()->coordToCell(x, y, &xI, &yI);
|
||||
double z = colorMap->data()->cell(xI, yI);
|
||||
|
||||
QString coordinates = QString("X: %1, Y: %2, Z: %3").arg(x).arg(y).arg(z);
|
||||
QToolTip::showText(event->globalPosition().toPoint(), coordinates, this);
|
||||
|
||||
//when drawing cut, show dashhed line
|
||||
if( isDrawCut && tempCut.size() > 0 ){
|
||||
line->end->setCoords(x,y);
|
||||
line->setVisible(true);
|
||||
replot();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
connect(this, &QCustomPlot::mousePress, this, [=](QMouseEvent * event){
|
||||
|
||||
if (event->button() == Qt::LeftButton && !usingMenu && !isDrawCut){
|
||||
setSelectionRectMode(QCP::SelectionRectMode::srmZoom);
|
||||
}
|
||||
|
||||
if (event->button() == Qt::LeftButton && isDrawCut){
|
||||
|
||||
oldMouseX = xAxis->pixelToCoord(event->pos().x());
|
||||
oldMouseY = yAxis->pixelToCoord(event->pos().y());
|
||||
|
||||
tempCut.push_back(QPointF(oldMouseX,oldMouseY));
|
||||
|
||||
line->start->setCoords(oldMouseX, oldMouseY);
|
||||
line->end->setCoords(oldMouseX, oldMouseY);
|
||||
line->setVisible(true);
|
||||
|
||||
DrawCut();
|
||||
}
|
||||
|
||||
//^================= right click
|
||||
if (event->button() == Qt::RightButton) rightMouseClickMenu(event);
|
||||
});
|
||||
|
||||
//connect( this, &QCustomPlot::mouseDoubleClick, this, [=](QMouseEvent *event){
|
||||
connect( this, &QCustomPlot::mouseDoubleClick, this, [=](){
|
||||
if( isDrawCut) {
|
||||
tempCut.push_back(tempCut[0]);
|
||||
DrawCut();
|
||||
isDrawCut = false;
|
||||
line->setVisible(false);
|
||||
|
||||
plottableIDList.push_back(plottableCount() -1 );
|
||||
|
||||
cutNameList.push_back("Cut-" + QString::number(cutList.count()));
|
||||
cutEntryList.push_back(0);
|
||||
|
||||
QCPItemText * text = new QCPItemText(this);
|
||||
text->setText(cutNameList.last());
|
||||
text->position->setCoords(tempCut[0].rx(), tempCut[0].ry());
|
||||
int colorID = tempCutID% colorCycle.count();
|
||||
text->setColor(colorCycle[colorID].first);
|
||||
cutTextIDList.push_back(itemCount() - 1);
|
||||
|
||||
replot();
|
||||
|
||||
cutList.push_back(tempCut);
|
||||
cutIDList.push_back(tempCutID);
|
||||
|
||||
// qDebug() << "----------- end of create cut";
|
||||
// qDebug() << " cutIDList " << cutIDList ;
|
||||
// qDebug() << "plottableIDList " << plottableIDList << ", " << plottableCount();
|
||||
// qDebug() << " cutTextIDList " << cutTextIDList << ", " << itemCount();
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
connect(this, &QCustomPlot::mouseRelease, this, [=](){
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline void Histogram2D::Fill(double x, double y){
|
||||
// DebugPrint("%s", "Histogram2D");
|
||||
if( isBusy ) return;
|
||||
|
@ -338,6 +333,9 @@ inline void Histogram2D::Rebin(int xbin, double xmin, double xmax, int ybin, do
|
|||
}
|
||||
}
|
||||
|
||||
rescaleAxes();
|
||||
UpdatePlot();
|
||||
|
||||
}
|
||||
|
||||
inline void Histogram2D::RebinY(int ybin, double ymin, double ymax){
|
||||
|
@ -388,7 +386,7 @@ inline void Histogram2D::ClearAllCuts(){
|
|||
inline void Histogram2D::PrintCutEntry() const{
|
||||
DebugPrint("%s", "Histogram2D");
|
||||
if( numCut == 0 ) return;
|
||||
printf("=============== There are %d cuts.\n", numCut);
|
||||
printf("=============== There are %d cuts. (%lld, %lld)\n", numCut, cutList.count(), cutEntryList.count());
|
||||
for( int i = 0; i < cutList.count(); i++){
|
||||
if( cutList[i].isEmpty() ) continue;
|
||||
printf("%10s | %d \n", cutNameList[i].toStdString().c_str(), cutEntryList[i]);
|
||||
|
@ -420,7 +418,7 @@ inline void Histogram2D::DrawCut(){
|
|||
}
|
||||
replot();
|
||||
|
||||
//qDebug() << "Plottable count : " << plottableCount() << ", cutList.count :" << cutList.count() << ", cutID :" << lastPlottableID;
|
||||
// qDebug() << "Plottable count : " << plottableCount() << ", cutList.count :" << cutList.count() << ", cutID :" << lastPlottableID;
|
||||
}
|
||||
|
||||
inline void Histogram2D::rightMouseClickMenu(QMouseEvent * event){
|
||||
|
@ -436,8 +434,11 @@ inline void Histogram2D::rightMouseClickMenu(QMouseEvent * event){
|
|||
QAction * a2 = menu->addAction("Clear hist.");
|
||||
QAction * a3 = menu->addAction("Toggle Stat.");
|
||||
QAction * a4 = menu->addAction("Rebin (clear histogram)");
|
||||
QAction * a8 = menu->addAction("Load Cut(s)");
|
||||
QAction * a5 = menu->addAction("Create a Cut");
|
||||
QAction * a7 = nullptr;
|
||||
if( numCut > 0 ) {
|
||||
a7 = menu->addAction("Save Cut(s)");
|
||||
menu->addSeparator();
|
||||
menu->addAction("Add/Edit names to Cuts");
|
||||
menu->addAction("Clear all Cuts");
|
||||
|
@ -572,6 +573,27 @@ inline void Histogram2D::rightMouseClickMenu(QMouseEvent * event){
|
|||
return;
|
||||
}
|
||||
|
||||
if( selectedAction == a8 ){ // load Cuts
|
||||
QString filePath = QFileDialog::getOpenFileName(this,
|
||||
"Load Cuts from File",
|
||||
settingPath,
|
||||
"Text file (*.txt)");
|
||||
|
||||
if (!filePath.isEmpty()) LoadCuts(filePath);
|
||||
|
||||
}
|
||||
|
||||
if( selectedAction == a7 ){ // Save Cuts
|
||||
|
||||
QString filePath = QFileDialog::getSaveFileName(this,
|
||||
"Save Cuts to File",
|
||||
settingPath,
|
||||
"Text file (*.txt)");
|
||||
|
||||
if (!filePath.isEmpty()) SaveCuts(filePath);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
@ -593,7 +615,7 @@ inline void Histogram2D::rightMouseClickRebin(){
|
|||
lineEditX[i] = new QLineEdit(&dialog);
|
||||
layout.addRow(nameListX[i] + " : ", lineEditX[i]);
|
||||
}
|
||||
lineEditX[0]->setText(QString::number(xBin));
|
||||
lineEditX[0]->setText(QString::number(xBin-2));
|
||||
lineEditX[1]->setText(QString::number(xMin));
|
||||
lineEditX[2]->setText(QString::number(xMax));
|
||||
|
||||
|
@ -603,7 +625,7 @@ inline void Histogram2D::rightMouseClickRebin(){
|
|||
lineEditY[i] = new QLineEdit(&dialog);
|
||||
layout.addRow(nameListY[i] + " : ", lineEditY[i]);
|
||||
}
|
||||
lineEditY[0]->setText(QString::number(yBin));
|
||||
lineEditY[0]->setText(QString::number(yBin-2));
|
||||
lineEditY[1]->setText(QString::number(yMin));
|
||||
lineEditY[2]->setText(QString::number(yMax));
|
||||
|
||||
|
@ -666,12 +688,120 @@ inline void Histogram2D::rightMouseClickRebin(){
|
|||
if( dialog.exec() == QDialog::Accepted ){
|
||||
isBusy = true;
|
||||
Rebin((int)number[0][0], number[1][0], number[2][0], (int)number[0][1], number[1][1], number[2][1]);
|
||||
rescaleAxes();
|
||||
UpdatePlot();
|
||||
isBusy = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
inline void Histogram2D::SaveCuts(QString cutFileName){
|
||||
|
||||
QFile file(cutFileName);
|
||||
if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
||||
QTextStream out(&file);
|
||||
|
||||
// Define the text to write
|
||||
QStringList lines;
|
||||
|
||||
for( int i = 0; i < cutList.size(); i++){
|
||||
lines << "====== "+ cutNameList[i];
|
||||
for( int pt = 0 ; pt < cutList[i].size(); pt ++){
|
||||
lines << QString::number(cutList[i][pt].rx(), 'g', 5) + "," + QString::number(cutList[i][pt].ry(), 'g', 5);
|
||||
}
|
||||
}
|
||||
|
||||
lines << "#===== End of File";
|
||||
|
||||
// Write each line to the file
|
||||
for (const QString &line : lines) out << line << "\n";
|
||||
|
||||
// Close the file
|
||||
file.close();
|
||||
qDebug() << "File written successfully to" << cutFileName;
|
||||
}else{
|
||||
qWarning() << "Unable to open file" << cutFileName;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
inline void Histogram2D::LoadCuts(QString cutFileName){
|
||||
|
||||
QFile file(cutFileName);
|
||||
QString cutNameTemp;
|
||||
|
||||
// Open the file in read mode
|
||||
if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
QTextStream in(&file);
|
||||
|
||||
ClearAllCuts();
|
||||
tempCut.clear();
|
||||
|
||||
// Read each line and append to the QStringList
|
||||
|
||||
while (!in.atEnd()) {
|
||||
QString line = in.readLine();
|
||||
|
||||
if( line.contains("======") ){
|
||||
if( !tempCut.isEmpty() ) {
|
||||
DrawCut();
|
||||
plottableIDList.push_back(plottableCount() -1 );
|
||||
cutNameList.push_back(cutNameTemp);
|
||||
cutEntryList.push_back(0);
|
||||
QCPItemText * text = new QCPItemText(this);
|
||||
text->setText(cutNameList.last());
|
||||
text->position->setCoords(tempCut[0].rx(), tempCut[0].ry());
|
||||
int colorID = tempCutID% colorCycle.count();
|
||||
text->setColor(colorCycle[colorID].first);
|
||||
cutTextIDList.push_back(itemCount() - 1);
|
||||
// cutList.push_back(tempCut);
|
||||
cutIDList.push_back(tempCutID);
|
||||
}
|
||||
tempCut.clear();
|
||||
tempCutID ++;
|
||||
numCut ++;
|
||||
|
||||
int spacePos = line.indexOf(' ');
|
||||
cutNameTemp = line.mid(spacePos + 1);
|
||||
continue;
|
||||
}
|
||||
|
||||
if( line.contains("#==") ) {
|
||||
DrawCut();
|
||||
plottableIDList.push_back(plottableCount() -1 );
|
||||
cutNameList.push_back(cutNameTemp);
|
||||
cutEntryList.push_back(0);
|
||||
QCPItemText * text = new QCPItemText(this);
|
||||
text->setText(cutNameList.last());
|
||||
text->position->setCoords(tempCut[0].rx(), tempCut[0].ry());
|
||||
int colorID = tempCutID% colorCycle.count();
|
||||
text->setColor(colorCycle[colorID].first);
|
||||
cutTextIDList.push_back(itemCount() - 1);
|
||||
cutList.push_back(tempCut);
|
||||
cutIDList.push_back(tempCutID);
|
||||
break;
|
||||
}else{
|
||||
QStringList haha = line.split(",");
|
||||
// qDebug() << haha;
|
||||
if( haha.size() == 2 ){
|
||||
tempCut.push_back(QPointF(haha[0].toFloat(), haha[1].toFloat()));
|
||||
DrawCut();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Close the file
|
||||
file.close();
|
||||
qDebug() << "File read successfully from" << cutFileName;
|
||||
|
||||
// PrintCutEntry();
|
||||
// DrawCut();
|
||||
replot();
|
||||
|
||||
} else {
|
||||
qWarning() << "Unable to open file" << cutFileName;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
122
MultiBuilder.cpp
122
MultiBuilder.cpp
|
@ -7,15 +7,18 @@ MultiBuilder::MultiBuilder(Data ** multiData, std::vector<int> type, std::vector
|
|||
data = multiData;
|
||||
typeList = type;
|
||||
snList = sn;
|
||||
numTotCh = 0;
|
||||
for( uShort i = 0; i < nData; i++) {
|
||||
idList.push_back(i);
|
||||
dataSize.push_back(data[i]->GetDataSize());
|
||||
numTotCh += data[i]->GetNChannel();
|
||||
}
|
||||
timeWindow = 100;
|
||||
leftOverTime = 100;
|
||||
breakTime = -1;
|
||||
timeJump = 1e8;
|
||||
lastEventTime = 0;
|
||||
forceStop = false;
|
||||
ClearEvents();
|
||||
|
||||
|
||||
|
@ -29,6 +32,7 @@ MultiBuilder::MultiBuilder(Data * singleData, int type, int sn): nData(1){
|
|||
DebugPrint("%s", "MultiBuilder");
|
||||
data = new Data *[1];
|
||||
data[0] = singleData;
|
||||
numTotCh = data[0]->GetNChannel();
|
||||
typeList.push_back(type);
|
||||
snList.push_back(sn);
|
||||
idList.push_back(0);
|
||||
|
@ -37,7 +41,7 @@ MultiBuilder::MultiBuilder(Data * singleData, int type, int sn): nData(1){
|
|||
breakTime = -1;
|
||||
timeJump = 1e8;
|
||||
lastEventTime = 0;
|
||||
|
||||
forceStop = false;
|
||||
ClearEvents();
|
||||
}
|
||||
|
||||
|
@ -57,6 +61,7 @@ void MultiBuilder::ClearEvents(){
|
|||
loopIndex[i][j] = 0;
|
||||
nextIndex[i][j] = -1;
|
||||
chExhaused[i][j] = false;
|
||||
lastBackWardIndex[i][j] = 0;
|
||||
}
|
||||
|
||||
earlistDigi = -1;
|
||||
|
@ -77,7 +82,6 @@ void MultiBuilder::PrintStat(){
|
|||
if( nextIndex[i][ch] >= 0 ) printf("%d %3d %2d | %7d (%d)\n", i, snList[i], ch, nextIndex[i][ch], loopIndex[i][ch]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void MultiBuilder::PrintAllEvent(){
|
||||
|
@ -89,7 +93,6 @@ void MultiBuilder::PrintAllEvent(){
|
|||
events[i][j].Print();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void MultiBuilder::FindEarlistTimeAndCh(bool verbose){
|
||||
|
@ -100,22 +103,26 @@ void MultiBuilder::FindEarlistTimeAndCh(bool verbose){
|
|||
nExhaushedCh = 0;
|
||||
for( int i = 0; i < nData; i++){
|
||||
|
||||
for( int j = 0; j < data[i]->GetNChannel(); j++ ) chExhaused[i][j] = false;
|
||||
for( int j = 0; j < data[i]->GetNChannel(); j++ ) {
|
||||
chExhaused[i][j] = false;
|
||||
}
|
||||
|
||||
for(unsigned int ch = 0; ch < data[i]->GetNChannel(); ch ++){
|
||||
|
||||
int index = data[i]->GetDataIndex(ch);
|
||||
if( ch >= data[i]->GetNChannel() || index < 0 ) {
|
||||
nExhaushedCh ++;
|
||||
chExhaused[i][ch] = true;
|
||||
continue;
|
||||
}
|
||||
{// check is dataIndex is valid
|
||||
int index = data[i]->GetDataIndex(ch);
|
||||
if( index < 0 ) {
|
||||
nExhaushedCh ++;
|
||||
chExhaused[i][ch] = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if( data[i]->GetTimestamp(ch, index) == 0 ||
|
||||
loopIndex[i][ch] * dataSize[i] > data[i]->GetLoopIndex(ch) * dataSize[i] + data[i]->GetDataIndex(ch)) {
|
||||
nExhaushedCh ++;
|
||||
chExhaused[i][ch] = true;
|
||||
continue;
|
||||
if( data[i]->GetTimestamp(ch, index) == 0 ||
|
||||
loopIndex[i][ch] * dataSize[i] > data[i]->GetLoopIndex(ch) * dataSize[i] + data[i]->GetDataIndex(ch)) {
|
||||
nExhaushedCh ++;
|
||||
chExhaused[i][ch] = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if( nextIndex[i][ch] == -1 ) nextIndex[i][ch] = 0;
|
||||
|
@ -126,6 +133,7 @@ void MultiBuilder::FindEarlistTimeAndCh(bool verbose){
|
|||
earlistDigi = i;
|
||||
earlistCh = ch;
|
||||
}
|
||||
// printf(" ch : %d | time %llu | %llu\n", ch, time, earlistTime);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -145,9 +153,9 @@ void MultiBuilder::FindLatestTimeAndCh(bool verbose){
|
|||
|
||||
for( int j = 0; j < data[i]->GetNChannel(); j++ ) chExhaused[i][j] = false;
|
||||
|
||||
for(unsigned int ch = 0; ch < MaxNChannels; ch ++){
|
||||
for(unsigned int ch = 0; ch < data[i]->GetNChannel(); ch ++){
|
||||
|
||||
if( nextIndex[i][ch] < 0 || ch >= data[i]->GetNChannel() || data[i]->GetDataIndex(ch) < 0 ) {
|
||||
if( nextIndex[i][ch] < 0 || data[i]->GetDataIndex(ch) < 0 || nextIndex[i][ch] <= lastBackWardIndex[i][ch] ) {
|
||||
nExhaushedCh ++;
|
||||
chExhaused[i][ch] = true;
|
||||
// printf(", exhanshed. %d \n", nExhaushedCh);
|
||||
|
@ -211,7 +219,8 @@ void MultiBuilder::FindLatestTimeOfData(bool verbose){
|
|||
|
||||
void MultiBuilder::BuildEvents(bool isFinal, bool skipTrace, bool verbose){
|
||||
DebugPrint("%s", "MultiBuilder");
|
||||
FindEarlistTimeAmongLastData(verbose); // give lastest Time, Ch, and Digi
|
||||
|
||||
FindEarlistTimeAmongLastData(verbose); // give lastest Time, Ch, and Digi for event building
|
||||
|
||||
FindEarlistTimeAndCh(verbose); //Give the earliest time, ch, digi
|
||||
if( earlistCh == -1 || nExhaushedCh == nData * MaxNChannels) return; /// no data
|
||||
|
@ -221,13 +230,12 @@ void MultiBuilder::BuildEvents(bool isFinal, bool skipTrace, bool verbose){
|
|||
Hit em;
|
||||
do{
|
||||
|
||||
if( forceStop ) break;
|
||||
|
||||
eventIndex ++;
|
||||
if( eventIndex >= MaxNEvent ) eventIndex = 0;
|
||||
events[eventIndex].clear();
|
||||
|
||||
eventBuilt ++;
|
||||
totalEventBuilt ++;
|
||||
|
||||
em.Clear();
|
||||
|
||||
for( int k = 0; k < nData; k++){
|
||||
|
@ -279,6 +287,8 @@ void MultiBuilder::BuildEvents(bool isFinal, bool skipTrace, bool verbose){
|
|||
if( timeWindow <= 0 ) break;
|
||||
}
|
||||
|
||||
if( events[eventIndex].size() == 0 ) continue;
|
||||
|
||||
if( events[eventIndex].size() > 1) {
|
||||
std::sort(events[eventIndex].begin(), events[eventIndex].end(), [](const Hit& a, const Hit& b) {
|
||||
return a.timestamp < b.timestamp;
|
||||
|
@ -293,14 +303,17 @@ void MultiBuilder::BuildEvents(bool isFinal, bool skipTrace, bool verbose){
|
|||
// //if there is a time jump, say, bigger than TimeJump. break
|
||||
if( earlistTime - lastEventTime > timeJump ) {
|
||||
if( verbose ){
|
||||
printf("%6lu, %16llu\n", eventIndex, earlistTime);
|
||||
printf("%5s - %16llu \n", "", lastEventTime);
|
||||
printf("%5s > %16llu \n", "", timeJump);
|
||||
printf("!!!!!!!! Time Jump detected stop event building. stop event buinding and get more data.\n");
|
||||
printf("!!!!!!!! Time Jump detected stop event building and get more data.\n");
|
||||
printf("event index : %6lu, earlist time : %16llu\n", eventIndex, earlistTime);
|
||||
printf(" %6s last event time : %16llu \n", "", lastEventTime);
|
||||
printf(" %6s time jump > %16llu \n", "", timeJump);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
eventBuilt ++;
|
||||
totalEventBuilt ++;
|
||||
|
||||
if( verbose ){
|
||||
printf(">>>>>>>>>>>>>>>>> Event ID : %ld, total built: %ld, multiplicity : %ld\n", eventIndex, totalEventBuilt, events[eventIndex].size());
|
||||
for( int i = 0; i <(int) events[eventIndex].size(); i++){
|
||||
|
@ -337,13 +350,16 @@ void MultiBuilder::BuildEvents(bool isFinal, bool skipTrace, bool verbose){
|
|||
}
|
||||
}while(nExhaushedCh < nData * MaxNChannels);
|
||||
|
||||
forceStop = false;
|
||||
|
||||
}
|
||||
|
||||
void MultiBuilder::BuildEventsBackWard(int maxNumEvent, bool verbose){
|
||||
DebugPrint("%s", "MultiBuilder");
|
||||
//skip trace, and only build for maxNumEvent events max
|
||||
|
||||
// remember the end of DataIndex, prevent over build
|
||||
// Get the last data index and loop index
|
||||
|
||||
for( int k = 0; k < nData; k++){
|
||||
for( int i = 0; i < data[k]->GetNChannel(); i++){
|
||||
nextIndex[k][i] = data[k]->GetDataIndex(i);
|
||||
|
@ -357,12 +373,11 @@ void MultiBuilder::BuildEventsBackWard(int maxNumEvent, bool verbose){
|
|||
eventBuilt = 0;
|
||||
Hit em;
|
||||
do{
|
||||
if( forceStop ) break;
|
||||
eventIndex ++;
|
||||
if( eventIndex >= MaxNEvent ) eventIndex = 0;
|
||||
events[eventIndex].clear();
|
||||
|
||||
eventBuilt ++;
|
||||
totalEventBuilt ++;
|
||||
em.Clear();
|
||||
|
||||
for( int k = 0; k < nData; k++){
|
||||
|
@ -373,10 +388,9 @@ void MultiBuilder::BuildEventsBackWard(int maxNumEvent, bool verbose){
|
|||
for( int i = 0; i < numCh; i++){
|
||||
int ch = (i + latestCh) % numCh;
|
||||
if( chExhaused[bd][ch] ) continue;
|
||||
//if( nextIndex[bd][ch] <= lastBackWardIndex[bd][ch] || nextIndex[bd][ch] < 0){
|
||||
if( nextIndex[bd][ch] < 0){
|
||||
chExhaused[bd][ch] = true;
|
||||
if( nextIndex[bd][ch] <= lastBackWardIndex[bd][ch] || nextIndex[bd][ch] <= 0){
|
||||
nExhaushedCh ++;
|
||||
chExhaused[bd][ch] = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -404,12 +418,27 @@ void MultiBuilder::BuildEventsBackWard(int maxNumEvent, bool verbose){
|
|||
if( timeWindow == 0 ) break;
|
||||
}
|
||||
|
||||
std::sort(events[eventIndex].begin(), events[eventIndex].end(), [](const Hit& a, const Hit& b) {
|
||||
return a.timestamp < b.timestamp;
|
||||
});
|
||||
|
||||
FindLatestTimeAndCh(verbose);
|
||||
|
||||
if( verbose ) printf(" nExhaushedCh %d | numToCh %d \n", nExhaushedCh, numTotCh);
|
||||
if( nExhaushedCh == numTotCh ) {
|
||||
if( verbose ) printf("######################### no more event to be built\n");
|
||||
break;
|
||||
}
|
||||
if( verbose ) printf("----- next bd: %d, ch : %d, next latest Time : %llu.\n", latestDigi, latestCh, latestTime);
|
||||
|
||||
if( events[eventIndex].size() > 0 ) {
|
||||
eventBuilt ++;
|
||||
totalEventBuilt ++;
|
||||
|
||||
std::sort(events[eventIndex].begin(), events[eventIndex].end(), [](const Hit& a, const Hit& b) {
|
||||
return a.timestamp < b.timestamp;
|
||||
});
|
||||
}else{
|
||||
continue;
|
||||
}
|
||||
|
||||
if( verbose ){
|
||||
printf(">>>>>>>>>>>>>>>>> Event ID : %ld, total built: %ld, multiplicity : %ld\n", eventIndex, totalEventBuilt, events[eventIndex].size());
|
||||
for( int i = 0; i <(int) events[eventIndex].size(); i++){
|
||||
|
@ -422,24 +451,19 @@ void MultiBuilder::BuildEventsBackWard(int maxNumEvent, bool verbose){
|
|||
break;
|
||||
}
|
||||
}
|
||||
printf("%05d, %02d | %5d | %5d %llu \n", sn, chxxx, nextIndex[bd][chxxx], events[eventIndex][i].energy, events[eventIndex][i].timestamp);
|
||||
printf("%5d, %02d | %5d | %5d %llu \n", sn, chxxx, nextIndex[bd][chxxx], events[eventIndex][i].energy, events[eventIndex][i].timestamp);
|
||||
}
|
||||
|
||||
if( nExhaushedCh == nData * MaxNChannels ) {
|
||||
printf("######################### no more event to be built\n");
|
||||
break;
|
||||
}
|
||||
printf("----- next bd: %d, ch : %d, next latest Time : %llu.\n", latestDigi, latestCh, latestTime);
|
||||
|
||||
}
|
||||
|
||||
}while(nExhaushedCh < nData * MaxNChannels && eventBuilt < maxNumEvent);
|
||||
}while(nExhaushedCh < numTotCh && eventBuilt < maxNumEvent);
|
||||
|
||||
// // remember the end of DataIndex, prevent over build
|
||||
// for( int k = 0; k < nData; k++){
|
||||
// for( int i = 0; i < MaxRegChannel; i++){
|
||||
// lastBackWardIndex[k][i] = data[k]->DataIndex[i];
|
||||
// }
|
||||
// }
|
||||
forceStop = false;
|
||||
|
||||
// remember the end of DataIndex, prevent over build
|
||||
for( int k = 0; k < nData; k++){
|
||||
for( int i = 0; i < data[k]->GetNChannel(); i++){
|
||||
lastBackWardIndex[k][i] = data[k]->GetDataIndex(i);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -14,16 +14,18 @@ public:
|
|||
MultiBuilder(Data * singleData, int type, int sn);
|
||||
~MultiBuilder();
|
||||
|
||||
void SetTimeWindow(unsigned short ticks) {timeWindow = ticks; leftOverTime = ticks;}
|
||||
void ForceStop(bool onOff) { forceStop = onOff;}
|
||||
|
||||
void SetTimeWindow(unsigned short nanosec) {timeWindow = nanosec; leftOverTime = nanosec;}
|
||||
unsigned short GetTimeWindow() const{return timeWindow;}
|
||||
|
||||
void SetTimeJump(unsigned long long TimeJumpInNanoSec) {timeJump = TimeJumpInNanoSec;}
|
||||
unsigned long long GetTimeJump() const {return timeJump;}
|
||||
|
||||
void SetLeftOverTime(unsigned long long ticks) {leftOverTime = ticks;}
|
||||
void SetLeftOverTime(unsigned long long nanosec) {leftOverTime = nanosec;}
|
||||
unsigned long long GetLeftOverTime() const{return leftOverTime;}
|
||||
|
||||
void SetBreakTime(unsigned long long ticks) {breakTime = ticks;}
|
||||
void SetBreakTime(unsigned long long nanosec) {breakTime = nanosec;}
|
||||
unsigned long long GetBreakTime() const{return breakTime;}
|
||||
|
||||
unsigned int GetNumOfDigitizer() const {return nData;}
|
||||
|
@ -48,6 +50,7 @@ private:
|
|||
std::vector<int> tick2ns;
|
||||
const unsigned short nData;
|
||||
Data ** data; // assume all data has MaxNChannel (16)
|
||||
int numTotCh; // number of total channel = sum digi[i]->GetNChannel()
|
||||
|
||||
std::vector<uShort> dataSize;
|
||||
|
||||
|
@ -78,6 +81,8 @@ private:
|
|||
|
||||
int lastBackWardIndex[MaxNDigitizer][MaxNChannels];
|
||||
|
||||
bool forceStop;
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
54
README.md
54
README.md
|
@ -6,19 +6,19 @@ https://discord.gg/xVsRhNZF8G
|
|||
|
||||
This is a DAQ for 1st gen CAEN digitizer for
|
||||
|
||||
- V1725, V17255S, V1230 with PHA and PSD firmware.
|
||||
- x725, x725S, x730 with PHA and PSD firmware.
|
||||
- V1740 with QDC firmware
|
||||
|
||||
It has scope (updated every half-sec), allow full control of the digitizer (except LVDS), and allow saving waveform.
|
||||
|
||||
It can be connected to InfluxDB v1.8+ and Elog.
|
||||
|
||||
Each channel has it own 1D histogram. It will not be filled by default, but can enable it in the "Online 1D histgram" panel. The binning of each histogram will be saved under the raw data path as singleSpectaSetting.txt
|
||||
Each channel has it own 1D histogram. It will not be filled by default, but can enable it in the "Online Histgrams" panel. The binning of each histogram will be saved under the raw data path as singleSpectaSetting.txt
|
||||
|
||||
## Wiki
|
||||
https://fsunuc.physics.fsu.edu/wiki/index.php/CAEN_digitizer
|
||||
|
||||
## Online analyzer
|
||||
# Online analyzer
|
||||
A Multi-builder (event builder that can build event across multiple digitizer) is made. It has normal event building code and also a backward event building code that build events from the latest data up to certain amont of event.
|
||||
|
||||
A 1-D and 2-D histogram is avalible. In the 2-D histogram, graphical cuts can be created and rename.
|
||||
|
@ -27,6 +27,25 @@ An online analyzer class is created as a template for online analysis. An exampl
|
|||
|
||||
<span style="color:red;">Notice that, when the FSUDAQ is started, the online analyzer is not created, no event will be built. Once the online anlyzer is created and opened, event will be built, even the window is closed. </span>
|
||||
|
||||
## Create a custom online analyzer
|
||||
|
||||
Under the analyzer folder, there are few examples can be followed. Teh idea is create a derivative class based on the Analyzer.h. To implement the new online analyzer, user need to modify a few things:
|
||||
- add the code file into FSUDAQ_At.pro
|
||||
- add the header to the top of FSUDAQ.cpp
|
||||
- edit the vector onlienAnalyzerList at th etop of FSUDAQ.cpp
|
||||
- edit the FSUDAQ::OpenAnalyzer()
|
||||
|
||||
after that, we need to update the makefile by
|
||||
|
||||
```sh
|
||||
>qmake6 FSUDAQ_Qt6.pro
|
||||
```
|
||||
|
||||
and then recompile by
|
||||
```sh
|
||||
>make
|
||||
```
|
||||
|
||||
# Operation
|
||||
|
||||
When programSettings.txt is presented in the same folder as the FSUDAQ_Qt, the program will load it can config the following
|
||||
|
@ -65,8 +84,7 @@ User must setup the data path for data take. Without the data path, user still c
|
|||
|
||||
# ToDo
|
||||
|
||||
- Gaussians fitting for 1D Histogram
|
||||
- Improve the color scheme for 2D histogram
|
||||
- Gaussians fitting for 1D Histogra
|
||||
- Save Histogram?
|
||||
|
||||
# Required / Development enviroment
|
||||
|
@ -77,6 +95,7 @@ Ubuntu 22.04
|
|||
- CAENCOmm v1.5.3 +
|
||||
- CAENDigitizer v2.17.1 +
|
||||
- CAEN A3818 Driver v1.6.8 +
|
||||
- CAENUSBdrv v1.5.5 + (for V57XX digitizer with USB connection)
|
||||
|
||||
- qt6-base-dev
|
||||
- libqt6charts6-dec
|
||||
|
@ -135,13 +154,28 @@ if you want to use GDB debugger, in the *.pro file add
|
|||
|
||||
` QMAKE_CXXFLAGS += -g`
|
||||
|
||||
|
||||
# Auxillary programs (e.g. Event Builder)
|
||||
|
||||
There is a folder Aux, this folder contains many auxillary programs, such as EventBuilder. User can `make` under the folder to compile the programs.
|
||||
|
||||
# Tested Trigger Rate
|
||||
# Enable Core dump
|
||||
|
||||
The program has abort handler to save core dump.
|
||||
|
||||
first, enable the gdb in compilation by edit the FSUDAQ_Qt6.pro by commen out the following lines:
|
||||
```sh
|
||||
QMAKE_CXXFLAGS += -g
|
||||
QMAKE_CXXFLAGS_RELEASE = -O0
|
||||
QMAKE_CFLAGS_RELEASE = -O0
|
||||
```
|
||||
|
||||
second, ensure the core dump file has unlimited size and set the core dump file name
|
||||
```sh
|
||||
>ulimit -c unlimited
|
||||
>echo "core.%e.%p" | sudo tee /proc/sys/kernel/core_pattern
|
||||
```
|
||||
|
||||
* V1725, 1 MHz to 3 ch (decay = 500 ns), no trace. need to set Agg/Read = 100 and Evt/Agg = 511.
|
||||
|
||||
# Known Issues
|
||||
|
||||
|
@ -150,10 +184,10 @@ There is a folder Aux, this folder contains many auxillary programs, such as Eve
|
|||
* When using the scope, the Agg/Read must be smaller than 512.
|
||||
* Although the Events/Agg used the CAEN API to recalculate before ACQ start, for PHA firmware, when the trigger rate changed, the Events per Agg need to be changed.
|
||||
* The Agg Organization, Event per Agg, Record Length are strongly correlated. Some settings are invalid and will cause the digitizer goes crazy.
|
||||
* load digitizer setting would not load everything, only load the channel settings and some board settings.
|
||||
* Load digitizer setting would not load everything, only load the channel settings and some board settings.
|
||||
* Sometimes, the buffer is not in time order, and make the trigger/Accept rate to be nagative. This is nothing to do with the program but the digitizer settings. Recommand reporgram the digitizer.
|
||||
* for 1740 QDC, RecordLenght is board setting, but readout is indivuial group.
|
||||
* FOr PHA, the trapezoid scaling and fine-gain register are calculated before ACQ start.
|
||||
* For 1740 QDC, RecordLenght is board setting, but readout is indivuial group.
|
||||
* For PHA, the trapezoid scaling and fine-gain register are calculated before ACQ start.
|
||||
|
||||
# Known Bugs
|
||||
|
||||
|
|
83
Scope.cpp
83
Scope.cpp
|
@ -6,6 +6,7 @@
|
|||
#include <QGroupBox>
|
||||
#include <QStandardItemModel>
|
||||
#include <QLabel>
|
||||
#include <QScreen>
|
||||
|
||||
QVector<QPointF> Scope::TrapezoidFilter(QVector<QPointF> data, int baseLineEndS, int riseTimeS, int flatTopS, float decayTime_ns){
|
||||
DebugPrint("%s", "Scope");
|
||||
|
@ -40,12 +41,12 @@ QVector<QPointF> Scope::TrapezoidFilter(QVector<QPointF> data, int baseLineEndS,
|
|||
|
||||
trapezoid.append(QPointF(data[i].x(), sn / decayTime_ns / riseTimeS));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
return trapezoid;
|
||||
}
|
||||
|
||||
|
||||
//^========================================================
|
||||
//^========================================================
|
||||
Scope::Scope(Digitizer ** digi, unsigned int nDigi, ReadDataThread ** readDataThread, QMainWindow * parent) : QMainWindow(parent){
|
||||
DebugPrint("%s", "Scope");
|
||||
this->digi = digi;
|
||||
|
@ -53,9 +54,17 @@ Scope::Scope(Digitizer ** digi, unsigned int nDigi, ReadDataThread ** readDataTh
|
|||
this->readDataThread = readDataThread;
|
||||
|
||||
setWindowTitle("Scope");
|
||||
setGeometry(0, 0, 1000, 800);
|
||||
setWindowFlags( this->windowFlags() & ~Qt::WindowCloseButtonHint );
|
||||
|
||||
//====== resize window if screen too small
|
||||
QScreen * screen = QGuiApplication::primaryScreen();
|
||||
QRect screenGeo = screen->geometry();
|
||||
if( screenGeo.width() < 1000 || screenGeo.height() < 800) {
|
||||
setGeometry(0, 0, screenGeo.width() - 100, screenGeo.height() - 100);
|
||||
}else{
|
||||
setGeometry(0, 0, 1000, 800);
|
||||
}
|
||||
|
||||
enableSignalSlot = false;
|
||||
|
||||
isACQStarted = false;
|
||||
|
@ -90,16 +99,6 @@ Scope::Scope(Digitizer ** digi, unsigned int nDigi, ReadDataThread ** readDataTh
|
|||
xaxis->setLabelFormat("%.0f");
|
||||
xaxis->setTitleText("Time [ns]");
|
||||
|
||||
updateTraceThread = new TimingThread();
|
||||
updateTraceThread->SetWaitTimeinSec(ScopeUpdateMiliSec / 1000.);
|
||||
connect(updateTraceThread, &TimingThread::timeUp, this, &Scope::UpdateScope);
|
||||
|
||||
updateScalarThread = new TimingThread();
|
||||
updateScalarThread->SetWaitTimeinSec(2);
|
||||
connect(updateScalarThread, &TimingThread::timeUp, this, [=](){
|
||||
emit UpdateScaler();
|
||||
});
|
||||
|
||||
NullThePointers();
|
||||
|
||||
//*================================== UI
|
||||
|
@ -216,7 +215,7 @@ Scope::Scope(Digitizer ** digi, unsigned int nDigi, ReadDataThread ** readDataTh
|
|||
QLabel * lbhints = new QLabel("Type 'r' to restore view, '+/-' Zoom in/out, arrow key to pan.", this);
|
||||
layout->addWidget(lbhints, rowID, 0, 1, 4);
|
||||
|
||||
QLabel * lbinfo = new QLabel("Trace updates every " + QString::number(updateTraceThread->GetWaitTimeinSec()) + " sec.", this);
|
||||
QLabel * lbinfo = new QLabel("Trace updates every " + QString::number(ScopeUpdateMiliSec / 1000.) + " sec.", this);
|
||||
lbinfo->setAlignment(Qt::AlignRight);
|
||||
layout->addWidget(lbinfo, rowID, 6);
|
||||
|
||||
|
@ -278,22 +277,32 @@ Scope::Scope(Digitizer ** digi, unsigned int nDigi, ReadDataThread ** readDataTh
|
|||
yaxis->setRange(0, 0xFFF);
|
||||
}
|
||||
|
||||
workerThread = new QThread(this);
|
||||
scopeWorker = new ScopeWorker(this);
|
||||
scopeTimer = new QTimer(this);
|
||||
|
||||
scopeWorker->moveToThread(workerThread);
|
||||
|
||||
// Setup the timer to trigger every second
|
||||
connect(scopeTimer, &QTimer::timeout, scopeWorker, [=](){
|
||||
scopeWorker->UpdateScope();
|
||||
});
|
||||
workerThread->start();
|
||||
|
||||
enableSignalSlot = true;
|
||||
|
||||
}
|
||||
|
||||
|
||||
Scope::~Scope(){
|
||||
DebugPrint("%s", "Scope");
|
||||
updateTraceThread->Stop();
|
||||
updateTraceThread->quit();
|
||||
updateTraceThread->wait();
|
||||
delete updateTraceThread;
|
||||
|
||||
updateScalarThread->Stop();
|
||||
updateScalarThread->quit();
|
||||
updateScalarThread->wait();
|
||||
delete updateScalarThread;
|
||||
scopeTimer->stop();
|
||||
// scalarTimer->stop();
|
||||
|
||||
if( workerThread->isRunning() ){
|
||||
workerThread->quit();
|
||||
workerThread->wait();
|
||||
}
|
||||
|
||||
for( int i = 0; i < MaxNumberOfTrace; i++) delete dataTrace[i];
|
||||
delete plot;
|
||||
|
@ -422,8 +431,7 @@ void Scope::StartScope(){
|
|||
|
||||
}
|
||||
|
||||
updateTraceThread->start();
|
||||
updateScalarThread->start();
|
||||
scopeTimer->start(ScopeUpdateMiliSec);
|
||||
|
||||
bnScopeStart->setEnabled(false);
|
||||
bnScopeStart->setStyleSheet("");
|
||||
|
@ -434,7 +442,7 @@ void Scope::StartScope(){
|
|||
|
||||
EnableControl(false);
|
||||
|
||||
TellACQOnOff(true);
|
||||
emit TellACQOnOff(true);
|
||||
|
||||
isACQStarted = true;
|
||||
|
||||
|
@ -445,13 +453,8 @@ void Scope::StopScope(){
|
|||
if( !digi ) return;
|
||||
|
||||
// printf("------ Scope::%s \n", __func__);
|
||||
updateTraceThread->Stop();
|
||||
updateTraceThread->quit();
|
||||
updateTraceThread->exit();
|
||||
|
||||
updateScalarThread->Stop();
|
||||
updateScalarThread->quit();
|
||||
updateScalarThread->exit();
|
||||
scopeTimer->stop();
|
||||
// scalarTimer->stop();
|
||||
|
||||
if( chkSoleRun->isChecked() ){
|
||||
|
||||
|
@ -467,7 +470,6 @@ void Scope::StopScope(){
|
|||
|
||||
digiMTX[ID].lock();
|
||||
digi[ID]->StopACQ();
|
||||
digi[ID]->ReadACQStatus();
|
||||
digiMTX[ID].unlock();
|
||||
|
||||
//restore setting
|
||||
|
@ -498,9 +500,9 @@ void Scope::StopScope(){
|
|||
readDataThread[iDigi]->wait();
|
||||
readDataThread[iDigi]->SetScopeMode(false);
|
||||
}
|
||||
|
||||
digiMTX[iDigi].lock();
|
||||
digi[iDigi]->StopACQ();
|
||||
digi[iDigi]->ReadACQStatus();
|
||||
//digi[iDigi]->GetData()->PrintAllData();
|
||||
digiMTX[iDigi].unlock();
|
||||
|
||||
|
@ -511,6 +513,8 @@ void Scope::StopScope(){
|
|||
|
||||
}
|
||||
|
||||
runStatus->setStyleSheet(""); // cheated, don;t know why digi[iDigi]->GetACQStatusFromMemory(), sometimes return ACQ one.
|
||||
|
||||
emit UpdateOtherPanels();
|
||||
|
||||
bnScopeStart->setEnabled(true);
|
||||
|
@ -523,7 +527,7 @@ void Scope::StopScope(){
|
|||
|
||||
EnableControl(true);
|
||||
|
||||
TellACQOnOff(false);
|
||||
emit TellACQOnOff(false);
|
||||
|
||||
isACQStarted = false;
|
||||
|
||||
|
@ -736,7 +740,7 @@ void Scope::SetUpSpinBox(RSpinBox * &sb, QString str, int row, int col, const Re
|
|||
value = uint16_t((1.0 - sb->value()/100.) * 0xFFFF);
|
||||
}
|
||||
|
||||
if( para == DPP::PHA::TriggerThreshold ){
|
||||
if( para == DPP::PHA::TriggerThreshold || para == DPP::PSD::TriggerThreshold){
|
||||
value = sb->value();
|
||||
}
|
||||
|
||||
|
@ -745,7 +749,7 @@ void Scope::SetUpSpinBox(RSpinBox * &sb, QString str, int row, int col, const Re
|
|||
if( digi[ID]->GetDPPType() == DPPTypeCode::DPP_QDC_CODE ){
|
||||
int grp = ch/8; // convert ch to grp
|
||||
digiMTX[ID].lock();
|
||||
digi[ID]->WriteRegister(para, value, grp);
|
||||
digi[ID]->WriteRegister(para, value, grp);
|
||||
digiMTX[ID].unlock();
|
||||
}else{
|
||||
digiMTX[ID].lock();
|
||||
|
@ -1254,6 +1258,7 @@ void Scope::UpdatePanel_PSD(){
|
|||
UpdateSpinBox(sbShortGate, DPP::PSD::ShortGateWidth);
|
||||
UpdateSpinBox(sbLongGate, DPP::PSD::LongGateWidth);
|
||||
UpdateSpinBox(sbGateOffset, DPP::PSD::GateOffset);
|
||||
UpdateSpinBox(sbThreshold, DPP::PSD::TriggerThreshold);
|
||||
|
||||
uint32_t BdCfg = digi[ID]->GetSettingFromMemory(DPP::BoardConfiguration, ch);
|
||||
|
||||
|
|
27
Scope.h
27
Scope.h
|
@ -12,6 +12,7 @@
|
|||
#include <QComboBox>
|
||||
#include <QGridLayout>
|
||||
#include <QGroupBox>
|
||||
#include <QTimer>
|
||||
#include <QLineSeries>
|
||||
#include <QRubberBand>
|
||||
#include <QMouseEvent>
|
||||
|
@ -22,6 +23,8 @@
|
|||
#include "CustomThreads.h"
|
||||
#include "CustomWidgets.h"
|
||||
|
||||
class ScopeWorker; //Forward declaration
|
||||
|
||||
//^====================================================
|
||||
//^====================================================
|
||||
class Scope : public QMainWindow{
|
||||
|
@ -51,7 +54,6 @@ signals:
|
|||
void CloseWindow();
|
||||
void SendLogMsg(const QString &msg);
|
||||
void TellACQOnOff(const bool onOff);
|
||||
void UpdateScaler();
|
||||
void UpdateOtherPanels();
|
||||
|
||||
private:
|
||||
|
@ -87,8 +89,6 @@ private:
|
|||
unsigned short oldCh, oldDigi;
|
||||
|
||||
ReadDataThread ** readDataThread;
|
||||
TimingThread * updateTraceThread;
|
||||
TimingThread * updateScalarThread;
|
||||
|
||||
bool enableSignalSlot;
|
||||
|
||||
|
@ -147,8 +147,29 @@ private:
|
|||
//sbGateOffset -> GateOffset
|
||||
//sbTriggerHoldOff ->Trigger Hold Off
|
||||
|
||||
QThread * workerThread;
|
||||
ScopeWorker * scopeWorker;
|
||||
QTimer * scopeTimer;
|
||||
|
||||
};
|
||||
|
||||
//^#======================================================== ScopeWorker
|
||||
class ScopeWorker : public QObject{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ScopeWorker(Scope * parent): SS(parent){}
|
||||
|
||||
public slots:
|
||||
void UpdateScope(){
|
||||
SS->UpdateScope();
|
||||
emit workDone();
|
||||
}
|
||||
|
||||
signals:
|
||||
void workDone();
|
||||
|
||||
private:
|
||||
Scope * SS;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -4,12 +4,13 @@
|
|||
#include <QGroupBox>
|
||||
#include <QStandardItemModel>
|
||||
#include <QLabel>
|
||||
// #include <QScreen>
|
||||
|
||||
SingleSpectra::SingleSpectra(Digitizer ** digi, unsigned int nDigi, QString rawDataPath, QMainWindow * parent) : QMainWindow(parent){
|
||||
DebugPrint("%s", "SingleSpectra");
|
||||
this->digi = digi;
|
||||
this->nDigi = nDigi;
|
||||
this->rawDataPath = rawDataPath;
|
||||
this->settingPath = rawDataPath + "/HistogramSettings.txt";
|
||||
|
||||
maxFillTimeinMilliSec = 1000;
|
||||
maxFillTimePerDigi = maxFillTimeinMilliSec/nDigi;
|
||||
|
@ -17,8 +18,15 @@ SingleSpectra::SingleSpectra(Digitizer ** digi, unsigned int nDigi, QString rawD
|
|||
isSignalSlotActive = true;
|
||||
|
||||
setWindowTitle("Single Histograms");
|
||||
setGeometry(0, 0, 1000, 800);
|
||||
//setWindowFlags( this->windowFlags() & ~Qt::WindowCloseButtonHint );
|
||||
|
||||
//====== resize window if screen too small
|
||||
QScreen * screen = QGuiApplication::primaryScreen();
|
||||
QRect screenGeo = screen->geometry();
|
||||
if( screenGeo.width() < 1000 || screenGeo.height() < 800) {
|
||||
setGeometry(0, 0, screenGeo.width() - 100, screenGeo.height() - 100);
|
||||
}else{
|
||||
setGeometry(0, 0, 1000, 800);
|
||||
}
|
||||
|
||||
QWidget * layoutWidget = new QWidget(this);
|
||||
setCentralWidget(layoutWidget);
|
||||
|
@ -73,101 +81,17 @@ SingleSpectra::SingleSpectra(Digitizer ** digi, unsigned int nDigi, QString rawD
|
|||
}
|
||||
});
|
||||
|
||||
QPushButton * bnRebinDigi = new QPushButton("Rebin Energy", this);
|
||||
ctrlLayout->addWidget(bnRebinDigi, 0, 6, 1, 2);
|
||||
connect(bnRebinDigi, &QPushButton::clicked, this, [=](){
|
||||
int ID = cbDigi->currentIndex();
|
||||
int ch = cbCh->currentIndex();
|
||||
|
||||
int a_Bin;
|
||||
float a_Min, a_Max;
|
||||
|
||||
if( ch >= 0 ){
|
||||
a_Bin = hist[ID][ch]->GetNBin();
|
||||
a_Min = hist[ID][ch]->GetXMin();
|
||||
a_Max = hist[ID][ch]->GetXMax();
|
||||
}else{
|
||||
a_Bin = hist2D[ID]->GetYNBin();
|
||||
a_Min = hist2D[ID]->GetYMin();
|
||||
a_Max = hist2D[ID]->GetYMax();
|
||||
}
|
||||
|
||||
//pop up a dialog for nBin and ranhe
|
||||
|
||||
QDialog dialog(this);
|
||||
dialog.setWindowTitle("Rebin histograms");
|
||||
|
||||
QFormLayout layout(&dialog);
|
||||
|
||||
QLabel * info = new QLabel(&dialog);
|
||||
info->setStyleSheet("color:red;");
|
||||
info->setText("This will also clear histogram!!");
|
||||
layout.addRow(info);
|
||||
|
||||
QStringList nameList = {"Num. Bin", "x-Min", "x-Max"};
|
||||
QLineEdit* lineEdit[3];
|
||||
|
||||
for (int i = 0; i < 3; ++i) {
|
||||
lineEdit[i] = new QLineEdit(&dialog);
|
||||
layout.addRow(nameList[i] + " : ", lineEdit[i]);
|
||||
}
|
||||
lineEdit[0]->setText(QString::number(a_Bin));
|
||||
lineEdit[1]->setText(QString::number(a_Min));
|
||||
lineEdit[2]->setText(QString::number(a_Max));
|
||||
|
||||
QLabel * msg = new QLabel(&dialog);
|
||||
msg->setStyleSheet("color:red;");
|
||||
layout.addRow(msg);
|
||||
|
||||
QDialogButtonBox buttonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, &dialog);
|
||||
layout.addRow(&buttonBox);
|
||||
|
||||
double number[3];
|
||||
|
||||
QObject::connect(&buttonBox, &QDialogButtonBox::accepted, [&]() {
|
||||
int OKcount = 0;
|
||||
bool conversionOk = true;
|
||||
for( int i = 0; i < 3; i++ ){
|
||||
number[i] = lineEdit[i]->text().toDouble(&conversionOk);
|
||||
if( conversionOk ){
|
||||
OKcount++;
|
||||
}else{
|
||||
msg->setText(nameList[i] + " is invalid.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if( OKcount == 3 ) {
|
||||
if( number[2] > number[1] ) {
|
||||
dialog.accept();
|
||||
}else{
|
||||
msg->setText(nameList[2] + " is smaller than " + nameList[1]);
|
||||
}
|
||||
}
|
||||
});
|
||||
QObject::connect(&buttonBox, &QDialogButtonBox::rejected, [&]() { dialog.reject();});
|
||||
|
||||
if( dialog.exec() == QDialog::Accepted ){
|
||||
if( hist2D[ID] ) {
|
||||
hist2D[ID]->RebinY((int)number[0], number[1], number[2]);
|
||||
hist2D[ID]->rescaleAxes();
|
||||
hist2D[ID]->UpdatePlot();
|
||||
}
|
||||
for( int j = 0; j < digi[ID]->GetNumInputCh(); j++){
|
||||
if( hist[ID][j] ) {
|
||||
hist[ID][j]->Rebin((int)number[0], number[1], number[2]);
|
||||
hist[ID][j]->UpdatePlot();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
QCheckBox * chkIsFillHistogram = new QCheckBox("Fill Histograms", this);
|
||||
ctrlLayout->addWidget(chkIsFillHistogram, 0, 8);
|
||||
connect(chkIsFillHistogram, &QCheckBox::stateChanged, this, [=](int state){ fillHistograms = state;});
|
||||
chkIsFillHistogram = new QCheckBox("Fill Histograms", this);
|
||||
ctrlLayout->addWidget(chkIsFillHistogram, 0, 6, 1, 2);
|
||||
chkIsFillHistogram->setChecked(false);
|
||||
fillHistograms = false;
|
||||
isFillingHistograms = false;
|
||||
|
||||
QLabel * lbSettingPath = new QLabel( settingPath , this);
|
||||
ctrlLayout->addWidget(lbSettingPath, 1, 0, 1, 6);
|
||||
|
||||
QPushButton * bnSaveButton = new QPushButton("Save Hist. Settings", this);
|
||||
ctrlLayout->addWidget(bnSaveButton, 1, 6, 1, 2);
|
||||
connect(bnSaveButton, &QPushButton::clicked, this, &SingleSpectra::SaveSetting);
|
||||
|
||||
}
|
||||
|
||||
|
@ -193,6 +117,9 @@ SingleSpectra::SingleSpectra(Digitizer ** digi, unsigned int nDigi, QString rawD
|
|||
for( int j = 0; j < digi[i]->GetNumInputCh(); j++){
|
||||
if( i < nDigi ) {
|
||||
hist[i][j] = new Histogram1D("Digi-" + QString::number(digi[i]->GetSerialNumber()) +", Ch-" + QString::number(j), "Raw Energy [ch]", nBin, eMin, eMax);
|
||||
if( digi[i]->GetDPPType() == DPPTypeCode::DPP_PSD_CODE ){
|
||||
hist[i][j]->AddDataList("Short Energy", Qt::green);
|
||||
}
|
||||
}else{
|
||||
hist[i][j] = nullptr;
|
||||
}
|
||||
|
@ -216,10 +143,28 @@ SingleSpectra::SingleSpectra(Digitizer ** digi, unsigned int nDigi, QString rawD
|
|||
ClearInternalDataCount();
|
||||
|
||||
|
||||
workerThread = new QThread(this);
|
||||
histWorker = new HistWorker(this);
|
||||
timer = new QTimer(this);
|
||||
|
||||
histWorker->moveToThread(workerThread);
|
||||
|
||||
// Setup the timer to trigger every second
|
||||
connect(timer, &QTimer::timeout, histWorker, &HistWorker::FillHistograms);
|
||||
workerThread->start();
|
||||
|
||||
}
|
||||
|
||||
SingleSpectra::~SingleSpectra(){
|
||||
DebugPrint("%s", "SingleSpectra");
|
||||
|
||||
timer->stop();
|
||||
|
||||
if( workerThread->isRunning() ){
|
||||
workerThread->quit();
|
||||
workerThread->wait();
|
||||
}
|
||||
|
||||
SaveSetting();
|
||||
|
||||
for( unsigned int i = 0; i < nDigi; i++ ){
|
||||
|
@ -289,9 +234,13 @@ void SingleSpectra::ChangeHistView(){
|
|||
}
|
||||
|
||||
void SingleSpectra::FillHistograms(){
|
||||
// DebugPrint("%s", "SingleSpectra");
|
||||
if( !fillHistograms ) return;
|
||||
|
||||
// printf("%s | %d %d \n", __func__, chkIsFillHistogram->checkState(), isFillingHistograms);
|
||||
if( this->isVisible() == false ) return;
|
||||
if( chkIsFillHistogram->checkState() == Qt::Unchecked ) return;
|
||||
if( isFillingHistograms) return;
|
||||
|
||||
isFillingHistograms = true;
|
||||
timespec t0, t1;
|
||||
|
||||
QVector<int> randomDigiList = generateNonRepeatedCombination(nDigi);
|
||||
|
@ -304,17 +253,15 @@ void SingleSpectra::FillHistograms(){
|
|||
QVector<int> randomChList = generateNonRepeatedCombination(digi[ID]->GetNumInputCh());
|
||||
|
||||
// qDebug() << randomChList;
|
||||
|
||||
digiMTX[ID].lock();
|
||||
|
||||
// digiMTX[ID].lock();
|
||||
// digi[ID]->GetData()->PrintAllData();
|
||||
|
||||
clock_gettime(CLOCK_REALTIME, &t0);
|
||||
for( int k = 0; k < digi[ID]->GetNumInputCh(); k ++ ){
|
||||
int ch = randomChList[k];
|
||||
int lastIndex = digi[ID]->GetData()->GetDataIndex(ch);
|
||||
// printf("--- ch %2d | last index %d \n", ch, lastIndex);
|
||||
if( lastIndex < 0 ) continue;
|
||||
// printf("--- ch %2d | last index %d \n", ch, lastIndex);
|
||||
|
||||
int loopIndex = digi[ID]->GetData()->GetLoopIndex(ch);
|
||||
|
||||
|
@ -345,6 +292,11 @@ void SingleSpectra::FillHistograms(){
|
|||
// printf(" ch: %d, last fill idx : %d | %d \n", ch, lastFilledIndex[ID][ch], data);
|
||||
|
||||
hist[ID][ch]->Fill( data );
|
||||
if( digi[i]->GetDPPType() == DPPTypeCode::DPP_PSD_CODE ){
|
||||
uShort e2 = digi[ID]->GetData()->GetEnergy2(ch, lastFilledIndex[ID][ch]);
|
||||
// printf("%u \n", e2);
|
||||
hist[ID][ch]->Fill( e2, 1);
|
||||
}
|
||||
hist2D[ID]->Fill(ch, data);
|
||||
}
|
||||
if( histVisibility[ID][ch] ) hist[ID][ch]->UpdatePlot();
|
||||
|
@ -354,44 +306,65 @@ void SingleSpectra::FillHistograms(){
|
|||
}
|
||||
|
||||
if( hist2DVisibility[ID] ) hist2D[ID]->UpdatePlot();
|
||||
digiMTX[ID].unlock();
|
||||
// digiMTX[ID].unlock();
|
||||
|
||||
}
|
||||
|
||||
isFillingHistograms = false;
|
||||
|
||||
}
|
||||
|
||||
void SingleSpectra::SaveSetting(){
|
||||
DebugPrint("%s", "SingleSpectra");
|
||||
QFile file(rawDataPath + "/singleSpectraSetting.txt");
|
||||
|
||||
file.open(QIODevice::Text | QIODevice::WriteOnly);
|
||||
QFile file(settingPath );
|
||||
|
||||
for( unsigned int i = 0; i < nDigi; i++){
|
||||
file.write(("======= " + QString::number(digi[i]->GetSerialNumber()) + "\n").toStdString().c_str());
|
||||
for( int ch = 0; ch < digi[i]->GetNumInputCh() ; ch++){
|
||||
QString a = QString::number(ch).rightJustified(2, ' ');
|
||||
QString b = QString::number(hist[i][ch]->GetNBin()).rightJustified(6, ' ');
|
||||
QString c = QString::number(hist[i][ch]->GetXMin()).rightJustified(6, ' ');
|
||||
QString d = QString::number(hist[i][ch]->GetXMax()).rightJustified(6, ' ');
|
||||
file.write( QString("%1 %2 %3 %4\n").arg(a).arg(b).arg(c).arg(d).toStdString().c_str() );
|
||||
if (!file.exists()) {
|
||||
// If the file does not exist, create it
|
||||
if (!file.open(QIODevice::WriteOnly)) {
|
||||
qWarning() << "Could not create file" << settingPath;
|
||||
} else {
|
||||
qDebug() << "File" << settingPath << "created successfully";
|
||||
file.close();
|
||||
}
|
||||
|
||||
QString a = QString::number(digi[i]->GetNumInputCh()).rightJustified(2, ' ');
|
||||
QString b = QString::number(hist2D[i]->GetXNBin()).rightJustified(6, ' ');
|
||||
QString c = QString::number(hist2D[i]->GetXMin()).rightJustified(6, ' ');
|
||||
QString d = QString::number(hist2D[i]->GetXMax()).rightJustified(6, ' ');
|
||||
QString e = QString::number(hist2D[i]->GetYNBin()).rightJustified(6, ' ');
|
||||
QString f = QString::number(hist2D[i]->GetYMin()).rightJustified(6, ' ');
|
||||
QString g = QString::number(hist2D[i]->GetYMax()).rightJustified(6, ' ');
|
||||
file.write( QString("%1 %2 %3 %4 %5 %6 %7\n").arg(a).arg(b).arg(c).arg(d).arg(e).arg(f).arg(g).toStdString().c_str() );
|
||||
}
|
||||
|
||||
file.write("//========== End of file\n");
|
||||
file.close();
|
||||
if( file.open(QIODevice::Text | QIODevice::WriteOnly) ){
|
||||
|
||||
for( unsigned int i = 0; i < nDigi; i++){
|
||||
file.write(("======= " + QString::number(digi[i]->GetSerialNumber()) + "\n").toStdString().c_str());
|
||||
for( int ch = 0; ch < digi[i]->GetNumInputCh() ; ch++){
|
||||
QString a = QString::number(ch).rightJustified(2, ' ');
|
||||
QString b = QString::number(hist[i][ch]->GetNBin()).rightJustified(6, ' ');
|
||||
QString c = QString::number(hist[i][ch]->GetXMin()).rightJustified(6, ' ');
|
||||
QString d = QString::number(hist[i][ch]->GetXMax()).rightJustified(6, ' ');
|
||||
file.write( QString("%1 %2 %3 %4\n").arg(a).arg(b).arg(c).arg(d).toStdString().c_str() );
|
||||
}
|
||||
|
||||
QString a = QString::number(digi[i]->GetNumInputCh()).rightJustified(2, ' ');
|
||||
QString b = QString::number(hist2D[i]->GetXNBin()-2).rightJustified(6, ' ');
|
||||
QString c = QString::number(hist2D[i]->GetXMin()).rightJustified(6, ' ');
|
||||
QString d = QString::number(hist2D[i]->GetXMax()).rightJustified(6, ' ');
|
||||
QString e = QString::number(hist2D[i]->GetYNBin()-2).rightJustified(6, ' ');
|
||||
QString f = QString::number(hist2D[i]->GetYMin()).rightJustified(6, ' ');
|
||||
QString g = QString::number(hist2D[i]->GetYMax()).rightJustified(6, ' ');
|
||||
file.write( QString("%1 %2 %3 %4 %5 %6 %7\n").arg(a).arg(b).arg(c).arg(d).arg(e).arg(f).arg(g).toStdString().c_str() );
|
||||
}
|
||||
|
||||
file.write("##========== End of file\n");
|
||||
file.close();
|
||||
|
||||
printf("Saved Histogram Settings to %s\n", settingPath.toStdString().c_str());
|
||||
}else{
|
||||
printf("%s|cannot open HistogramSettings.txt\n", __func__);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void SingleSpectra::LoadSetting(){
|
||||
DebugPrint("%s", "SingleSpectra");
|
||||
QFile file(rawDataPath + "/singleSpectraSetting.txt");
|
||||
|
||||
QFile file(settingPath);
|
||||
|
||||
if( file.open(QIODevice::Text | QIODevice::ReadOnly) ){
|
||||
|
||||
|
@ -402,7 +375,7 @@ void SingleSpectra::LoadSetting(){
|
|||
int digiID = -1;
|
||||
|
||||
while ( !line.isNull() ){
|
||||
if( line.contains("//========== ") ) break;
|
||||
if( line.contains("##========== ") ) break;
|
||||
if( line.contains("//") ) continue;
|
||||
if( line.contains("======= ") ){
|
||||
digiSN = line.mid(7).toInt();
|
||||
|
@ -422,21 +395,21 @@ void SingleSpectra::LoadSetting(){
|
|||
|
||||
QStringList list = line.split(QRegularExpression("\\s+"));
|
||||
list.removeAll("");
|
||||
if( list.count() != 4 ) {
|
||||
line = in.readLine();
|
||||
continue;
|
||||
}
|
||||
QVector<int> data;
|
||||
// if( list.count() != 4 ) {
|
||||
// line = in.readLine();
|
||||
// continue;
|
||||
// }
|
||||
QVector<float> data;
|
||||
for( int i = 0; i < list.count(); i++){
|
||||
data.push_back(list[i].toInt());
|
||||
data.push_back(list[i].toFloat());
|
||||
}
|
||||
|
||||
if( 0 <= data[0] && data[0] < digi[digiID]->GetNumInputCh() ){
|
||||
hist[digiID][data[0]]->Rebin(data[1], data[2], data[3]);
|
||||
hist[digiID][int(data[0])]->Rebin(data[1], data[2], data[3]);
|
||||
}
|
||||
|
||||
if( data[0] == digi[digiID]->GetNumInputCh() && data.size() == 7 ){
|
||||
hist2D[digiID]->Rebin(data[1], data[2], data[3], data[4], data[5], data[6]);
|
||||
if( int(data[0]) == digi[digiID]->GetNumInputCh() && data.size() == 7 ){
|
||||
hist2D[digiID]->Rebin(int(data[1]), data[2], data[3], int(data[4]), data[5], data[6]);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -446,6 +419,8 @@ void SingleSpectra::LoadSetting(){
|
|||
|
||||
}else{
|
||||
|
||||
printf("%s|cannot open HistogramSettings.txt\n", __func__);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "Histogram1D.h"
|
||||
#include "Histogram2D.h"
|
||||
|
||||
class HistWorker; //Forward decalration
|
||||
|
||||
//^====================================================
|
||||
//^====================================================
|
||||
|
@ -31,8 +32,8 @@ public:
|
|||
~SingleSpectra();
|
||||
|
||||
void ClearInternalDataCount();
|
||||
void SetFillHistograms(bool onOff) { fillHistograms = onOff;}
|
||||
bool IsFillHistograms() const {return fillHistograms;}
|
||||
// void SetFillHistograms(bool onOff) { fillHistograms = onOff;}
|
||||
// bool IsFillHistograms() const {return fillHistograms;}
|
||||
|
||||
void LoadSetting();
|
||||
void SaveSetting();
|
||||
|
@ -45,17 +46,33 @@ public:
|
|||
public slots:
|
||||
void FillHistograms();
|
||||
void ChangeHistView();
|
||||
void startTimer(){
|
||||
// printf("timer start\n");
|
||||
timer->start(maxFillTimeinMilliSec);
|
||||
}
|
||||
void stopTimer(){
|
||||
// printf("timer stop\n");
|
||||
timer->stop();
|
||||
ClearInternalDataCount();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
Digitizer ** digi;
|
||||
unsigned short nDigi;
|
||||
|
||||
int lastFilledIndex[MaxNDigitizer][MaxNChannels];
|
||||
int loopFilledIndex[MaxNDigitizer][MaxNChannels];
|
||||
bool histVisibility[MaxNDigitizer][MaxNChannels];
|
||||
bool hist2DVisibility[MaxNDigitizer];
|
||||
unsigned short maxFillTimePerDigi;
|
||||
|
||||
bool isFillingHistograms;
|
||||
Histogram1D * hist[MaxNDigitizer][MaxNChannels];
|
||||
Histogram2D * hist2D[MaxNDigitizer];
|
||||
|
||||
bool histVisibility[MaxNDigitizer][MaxNChannels];
|
||||
bool hist2DVisibility[MaxNDigitizer];
|
||||
|
||||
QCheckBox * chkIsFillHistogram;
|
||||
|
||||
RComboBox * cbDivision;
|
||||
|
||||
|
@ -66,17 +83,35 @@ private:
|
|||
QGridLayout * histLayout;
|
||||
int oldBd, oldCh;
|
||||
|
||||
int lastFilledIndex[MaxNDigitizer][MaxNChannels];
|
||||
int loopFilledIndex[MaxNDigitizer][MaxNChannels];
|
||||
|
||||
bool fillHistograms;
|
||||
|
||||
QString rawDataPath;
|
||||
QString settingPath;
|
||||
|
||||
unsigned short maxFillTimeinMilliSec;
|
||||
unsigned short maxFillTimePerDigi;
|
||||
|
||||
bool isSignalSlotActive;
|
||||
|
||||
QThread * workerThread;
|
||||
HistWorker * histWorker;
|
||||
QTimer * timer;
|
||||
|
||||
};
|
||||
|
||||
//^#======================================================== HistWorker
|
||||
class HistWorker : public QObject{
|
||||
Q_OBJECT
|
||||
public:
|
||||
HistWorker(SingleSpectra * parent): SS(parent){}
|
||||
|
||||
public slots:
|
||||
void FillHistograms(){
|
||||
SS->FillHistograms();
|
||||
emit workDone();
|
||||
}
|
||||
|
||||
signals:
|
||||
void workDone();
|
||||
|
||||
private:
|
||||
SingleSpectra * SS;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -13,7 +13,9 @@ Analyzer::Analyzer(Digitizer ** digi, unsigned int nDigi, QMainWindow * parent )
|
|||
setGeometry(0, 0, 1000, 800);
|
||||
|
||||
influx = nullptr;
|
||||
dataBaseIP = "";
|
||||
dataBaseName = "";
|
||||
dataBaseToken = "";
|
||||
|
||||
dataList = new Data*[nDigi];
|
||||
typeList.clear();
|
||||
|
@ -28,9 +30,9 @@ Analyzer::Analyzer(Digitizer ** digi, unsigned int nDigi, QMainWindow * parent )
|
|||
isBuildBackward = false;
|
||||
mb = new MultiBuilder(dataList, typeList, snList);
|
||||
|
||||
buildTimerThread = new TimingThread(this);
|
||||
buildTimerThread->SetWaitTimeinSec(1.0); //^Set event build interval
|
||||
connect( buildTimerThread, &TimingThread::timeUp, this, &Analyzer::UpdateHistograms);
|
||||
// buildTimerThread = new TimingThread(this);
|
||||
// buildTimerThread->SetWaitTimeinSec(1.0); //^Set event build interval
|
||||
// connect( buildTimerThread, &TimingThread::timeUp, this, &Analyzer::UpdateHistograms);
|
||||
|
||||
QWidget * layoutWidget = new QWidget(this);
|
||||
setCentralWidget(layoutWidget);
|
||||
|
@ -40,9 +42,41 @@ Analyzer::Analyzer(Digitizer ** digi, unsigned int nDigi, QMainWindow * parent )
|
|||
// QPushButton * bnSetting = new QPushButton("Settings", this);
|
||||
// layout->addWidget(bnSetting);
|
||||
|
||||
anaThread = new QThread(this);
|
||||
anaWorker = new AnalyzerWorker(this);
|
||||
anaTimer = new QTimer();
|
||||
isWorking = false;
|
||||
|
||||
anaWorker->moveToThread(anaThread);
|
||||
|
||||
connect(anaTimer, &QTimer::timeout, anaWorker, [=](){
|
||||
if( isWorking ) return;
|
||||
isWorking = true;
|
||||
anaWorker->UpdateHistograms();
|
||||
isWorking = false;
|
||||
});
|
||||
|
||||
// connect(anaWorker, &AnalyzerWorker::workDone, this, [=](){
|
||||
// printf(" --------- work Done\n");
|
||||
// });
|
||||
|
||||
anaThread->start();
|
||||
|
||||
}
|
||||
|
||||
Analyzer::~Analyzer(){
|
||||
|
||||
printf("Analyzer::%s\n", __func__);
|
||||
anaTimer->stop();
|
||||
|
||||
printf(" is anaThread is running %d \n", anaThread->isRunning());
|
||||
if( anaThread->isRunning() ){
|
||||
anaThread->quit();
|
||||
anaThread->wait();
|
||||
}
|
||||
|
||||
printf("------ end of anaThread \n");
|
||||
|
||||
delete influx;
|
||||
delete mb;
|
||||
delete [] dataList;
|
||||
|
@ -60,6 +94,62 @@ double Analyzer::RandomGauss(double mean, double sigma){
|
|||
|
||||
}
|
||||
|
||||
void Analyzer::SetDatabase(QString IP, QString Name, QString Token){
|
||||
dataBaseIP = IP;
|
||||
dataBaseName = Name;
|
||||
dataBaseToken = Token;
|
||||
|
||||
if( influx ) {
|
||||
delete influx;
|
||||
influx = nullptr;
|
||||
}
|
||||
|
||||
influx = new InfluxDB(dataBaseIP.toStdString());
|
||||
|
||||
if( influx->TestingConnection() ){
|
||||
printf("InfluxDB URL (%s) is Valid. Version : %s\n", dataBaseIP.toStdString().c_str(), influx->GetVersionString().c_str());
|
||||
|
||||
if( influx->GetVersionNo() > 1 && dataBaseToken.isEmpty() ) {
|
||||
printf("A Token is required for accessing the database.\n");
|
||||
delete influx;
|
||||
influx = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
influx->SetToken(dataBaseToken.toStdString());
|
||||
|
||||
//==== chck database exist
|
||||
influx->CheckDatabases();
|
||||
std::vector<std::string> databaseList = influx->GetDatabaseList();
|
||||
bool foundDatabase = false;
|
||||
for( int i = 0; i < (int) databaseList.size(); i++){
|
||||
if( databaseList[i] == dataBaseName.toStdString() ) foundDatabase = true;
|
||||
// printf("%d | %s\n", i, databaseList[i].c_str());
|
||||
}
|
||||
if( foundDatabase ){
|
||||
influx->AddDataPoint("test value=1");
|
||||
influx->WriteData(dataBaseName.toStdString());
|
||||
influx->ClearDataPointsBuffer();
|
||||
if( influx->IsWriteOK() ){
|
||||
printf("test write database OK.\n");
|
||||
}else{
|
||||
printf("################# test write database FAIL.\n");
|
||||
delete influx;
|
||||
influx = nullptr;
|
||||
}
|
||||
}else{
|
||||
printf("Database name : %s NOT found.\n", dataBaseName.toStdString().c_str());
|
||||
delete influx;
|
||||
influx = nullptr;
|
||||
}
|
||||
}else{
|
||||
printf("InfluxDB URL (%s) is NOT Valid. \n", dataBaseIP.toStdString().c_str());
|
||||
delete influx;
|
||||
influx = nullptr;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Analyzer::RedefineEventBuilder(std::vector<int> idList){
|
||||
delete mb;
|
||||
delete [] dataList;
|
||||
|
@ -76,31 +166,70 @@ void Analyzer::RedefineEventBuilder(std::vector<int> idList){
|
|||
mb = new MultiBuilder(dataList, typeList, snList);
|
||||
}
|
||||
|
||||
void Analyzer::StartThread(){
|
||||
mb->ClearEvents();
|
||||
buildTimerThread->start();
|
||||
}
|
||||
|
||||
void Analyzer::StopThread(){
|
||||
// printf("%s\n", __func__);
|
||||
buildTimerThread->Stop();
|
||||
buildTimerThread->quit();
|
||||
buildTimerThread->wait();
|
||||
}
|
||||
|
||||
|
||||
|
||||
void Analyzer::BuildEvents(bool verbose){
|
||||
|
||||
unsigned int nData = mb->GetNumOfDigitizer();
|
||||
std::vector<int> idList = mb->GetDigiIDList();
|
||||
for( unsigned int i = 0; i < nData; i++ ) digiMTX[idList[i]].lock();
|
||||
// unsigned int nData = mb->GetNumOfDigitizer();
|
||||
// std::vector<int> idList = mb->GetDigiIDList();
|
||||
// for( unsigned int i = 0; i < nData; i++ ) digiMTX[idList[i]].lock();
|
||||
if( isBuildBackward ){
|
||||
mb->BuildEventsBackWard(maxNumEventBuilt, verbose);
|
||||
}else{
|
||||
mb->BuildEvents(0, 0, verbose);
|
||||
mb->BuildEvents(0, true, verbose);
|
||||
}
|
||||
// mb->PrintStat();
|
||||
// for( unsigned int i = 0; i < nData; i++ ) digiMTX[idList[i]].unlock();
|
||||
|
||||
}
|
||||
|
||||
void Analyzer::SetDatabaseButton(){
|
||||
|
||||
QDialog dialog;
|
||||
dialog.setWindowTitle("Influx Database");
|
||||
|
||||
QGridLayout layout(&dialog);
|
||||
|
||||
//------------------------------
|
||||
QLabel ipLabel("Database IP : ");
|
||||
layout.addWidget(&ipLabel, 0, 0);
|
||||
|
||||
QLineEdit ipLineEdit;
|
||||
ipLineEdit.setFixedSize(1000, 20);
|
||||
ipLineEdit.setText(dataBaseIP);
|
||||
layout.addWidget(&ipLineEdit, 0, 1);
|
||||
|
||||
//------------------------------
|
||||
QLabel nameLabel("Database Name : ");
|
||||
layout.addWidget(&nameLabel, 1, 0);
|
||||
|
||||
QLineEdit nameLineEdit;
|
||||
nameLineEdit.setFixedSize(1000, 20);
|
||||
nameLineEdit.setText(dataBaseName);
|
||||
layout.addWidget(&nameLineEdit, 1, 1);
|
||||
|
||||
//------------------------------
|
||||
QLabel tokenLabel("Database Token : ");
|
||||
layout.addWidget(&tokenLabel, 2, 0);
|
||||
|
||||
QLineEdit tokenLineEdit;
|
||||
tokenLineEdit.setFixedSize(1000, 20);
|
||||
tokenLineEdit.setText(dataBaseToken);
|
||||
layout.addWidget(&tokenLineEdit, 2, 1);
|
||||
|
||||
layout.addWidget(new QLabel("Only for version 2+, version 1+ can be skipped."), 3, 0, 1, 2);
|
||||
|
||||
// Buttons for OK and Cancel
|
||||
QDialogButtonBox buttonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
|
||||
layout.addWidget(&buttonBox);
|
||||
|
||||
QObject::connect(&buttonBox, &QDialogButtonBox::accepted, &dialog, &QDialog::accept);
|
||||
QObject::connect(&buttonBox, &QDialogButtonBox::rejected, &dialog, &QDialog::reject);
|
||||
|
||||
dialog.resize(400, dialog.sizeHint().height()); // Set the width to 400 pixels
|
||||
|
||||
// Show the dialog and get the result
|
||||
if (dialog.exec() == QDialog::Accepted) {
|
||||
SetDatabase(ipLineEdit.text().trimmed(), nameLineEdit.text().trimmed(),tokenLineEdit.text().trimmed());
|
||||
}
|
||||
for( unsigned int i = 0; i < nData; i++ ) digiMTX[idList[i]].unlock();
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -29,10 +29,17 @@ This is the mother of all other derivative analysis class.
|
|||
|
||||
derivative class should define the SetUpCanvas() and UpdateHistogram();
|
||||
|
||||
After creating a new class based on the Analyzer class,
|
||||
users need to add the class files to the FSUDAQ_Qt6.pro project file,
|
||||
include the header file in FSUDAQ.cpp,
|
||||
modify the MainWindow::OpenAnalyzer() method,
|
||||
and recompile FSUDAQ to incorporate the changes and activate the custom analyzer.
|
||||
|
||||
***************************************/
|
||||
#include "Histogram1D.h"
|
||||
#include "Histogram2D.h"
|
||||
|
||||
class AnalyzerWorker; //Forward decalration
|
||||
|
||||
//^==============================================
|
||||
//^==============================================
|
||||
|
@ -43,32 +50,47 @@ public:
|
|||
Analyzer(Digitizer ** digi, unsigned int nDigi, QMainWindow * parent = nullptr);
|
||||
virtual ~Analyzer();
|
||||
|
||||
virtual void SetUpCanvas();
|
||||
|
||||
MultiBuilder * GetEventBuilder() { return mb;}
|
||||
|
||||
void RedefineEventBuilder(std::vector<int> idList);
|
||||
void SetBackwardBuild(bool TF, int maxNumEvent = 100) { isBuildBackward = TF; maxNumEventBuilt = maxNumEvent;}
|
||||
void SetDatabase(QString IP, QString Name, QString Token);
|
||||
|
||||
double RandomGauss(double mean, double sigma);
|
||||
void SetDatabaseButton();
|
||||
|
||||
public slots:
|
||||
void StartThread();
|
||||
void StopThread();
|
||||
double GetUpdateTimeInSec() const {return waitTimeinSec;}
|
||||
|
||||
virtual void SetUpCanvas();
|
||||
virtual void UpdateHistograms(); // where event-building, analysis, and ploting
|
||||
|
||||
private slots:
|
||||
public slots:
|
||||
void startTimer(){
|
||||
// printf("start timer\n");
|
||||
mb->ForceStop(false);
|
||||
mb->ClearEvents();
|
||||
anaTimer->start(waitTimeinSec*1000);
|
||||
}
|
||||
void stopTimer(){
|
||||
// printf("stop worker\n");
|
||||
anaTimer->stop();
|
||||
mb->ForceStop(true);
|
||||
}
|
||||
|
||||
private slots:
|
||||
|
||||
protected:
|
||||
QGridLayout * layout;
|
||||
void BuildEvents(bool verbose = false);
|
||||
void SetUpdateTimeInSec(double sec = 1.0) {waitTimeinSec = sec; buildTimerThread->SetWaitTimeinSec(waitTimeinSec);}
|
||||
void SetUpdateTimeInSec(double sec = 1.0) { waitTimeinSec = sec; }
|
||||
|
||||
InfluxDB * influx;
|
||||
std::string dataBaseName;
|
||||
QString dataBaseIP;
|
||||
QString dataBaseName;
|
||||
QString dataBaseToken;
|
||||
|
||||
bool isWorking; // a flag to indicate the worker is working
|
||||
|
||||
private:
|
||||
Digitizer ** digi;
|
||||
unsigned short nDigi;
|
||||
|
||||
|
@ -81,8 +103,32 @@ private:
|
|||
MultiBuilder * mb;
|
||||
bool isBuildBackward;
|
||||
int maxNumEventBuilt;
|
||||
TimingThread * buildTimerThread;
|
||||
// TimingThread * buildTimerThread;
|
||||
|
||||
QThread * anaThread;
|
||||
AnalyzerWorker * anaWorker;
|
||||
QTimer * anaTimer;
|
||||
|
||||
};
|
||||
|
||||
//^================================================ AnalyzerWorker
|
||||
|
||||
class AnalyzerWorker : public QObject{
|
||||
Q_OBJECT
|
||||
public:
|
||||
AnalyzerWorker(Analyzer * parent): SS(parent){}
|
||||
|
||||
public slots:
|
||||
void UpdateHistograms(){
|
||||
SS->UpdateHistograms();
|
||||
emit workDone();
|
||||
}
|
||||
|
||||
signals:
|
||||
void workDone();
|
||||
|
||||
private:
|
||||
Analyzer * SS;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -33,7 +33,7 @@ public:
|
|||
evtbder->SetTimeWindow(500);
|
||||
|
||||
//========== use the influx from the Analyzer
|
||||
influx = new InfluxDB("https://fsunuc.physics.fsu.edu/influx/");
|
||||
influx = new InfluxDB("https://localhost:8086");
|
||||
dataBaseName = "testing";
|
||||
|
||||
SetUpCanvas(); // see below
|
||||
|
@ -85,7 +85,7 @@ inline void BeamTune::SetUpCanvas(){
|
|||
layout->addWidget(hFrame, 0, 0, 1, 2);
|
||||
|
||||
hFrame1 = new Histogram2D("X Map", "X-axis", "Y-axis", 100, -10, 110, 100, -0.8, 0.8, this);
|
||||
layout->addWidget(hFrame1, 1, 1, 1, 2);
|
||||
layout->addWidget(hFrame1, 1, 0, 1, 2);
|
||||
|
||||
|
||||
/*
|
||||
|
@ -137,38 +137,38 @@ inline void BeamTune::UpdateHistograms(){
|
|||
if( event.size() == 0 ) return;
|
||||
|
||||
|
||||
e0 = 0;
|
||||
e1 = 0;
|
||||
e2 = 0;
|
||||
e3 = 0;
|
||||
e0 = 0;
|
||||
e1 = 0;
|
||||
e2 = 0;
|
||||
e3 = 0;
|
||||
|
||||
t0 = 0;
|
||||
t1 = 0;
|
||||
t2 = 0;
|
||||
t3 = 0;
|
||||
|
||||
t0 = 0;
|
||||
t1 = 0;
|
||||
t2 = 0;
|
||||
t3 = 0;
|
||||
|
||||
s0 = 0;
|
||||
s1 = 0;
|
||||
s2 = 0;
|
||||
s3 = 0;
|
||||
s0 = 0;
|
||||
s1 = 0;
|
||||
s2 = 0;
|
||||
s3 = 0;
|
||||
|
||||
s_t0 = 0;
|
||||
s_t1 = 0;
|
||||
s_t2 = 0;
|
||||
s_t3 = 0;
|
||||
s_t0 = 0;
|
||||
s_t1 = 0;
|
||||
s_t2 = 0;
|
||||
s_t3 = 0;
|
||||
|
||||
|
||||
//std::vector<TLine*> lines; // Store lines to draw after the loop
|
||||
//std::vector<TMarker*> markers; // Store markers to draw after the loop
|
||||
//int lineCount = 0; // Counter to keep track of the number of lines
|
||||
//std::vector<TLine*> lines; // Store lines to draw after the loop
|
||||
//std::vector<TMarker*> markers; // Store markers to draw after the loop
|
||||
//int lineCount = 0; // Counter to keep track of the number of lines
|
||||
|
||||
for( int k = 0; k < (int) event.size(); k++ ){
|
||||
//event[k].Print();
|
||||
|
||||
if( event[k].ch == 2 ) {s0 = event[k].energy; s_t0 = event[k].timestamp;} //
|
||||
if( event[k].ch == 3 ) {s1= event[k].energy; s_t1 = event[k].timestamp;} // The 4 output signals from the
|
||||
if( event[k].ch == 3 ) {s1 = event[k].energy; s_t1 = event[k].timestamp;} // The 4 output signals from the
|
||||
if( event[k].ch == 4 ) {s2 = event[k].energy; s_t2 = event[k].timestamp;} // MCP detector
|
||||
if( event[k].ch == 5 ) {s3= event[k].energy; s_t3 = event[k].timestamp;} //
|
||||
if( event[k].ch == 5 ) {s3 = event[k].energy; s_t3 = event[k].timestamp;} //
|
||||
|
||||
if( event[k].ch == 10 ) {e0 = event[k].energy; t0 = event[k].timestamp;} //
|
||||
if( event[k].ch == 11 ) {e1= event[k].energy; t1 = event[k].timestamp;} // The 4 output signals from the
|
||||
|
@ -178,8 +178,8 @@ inline void BeamTune::UpdateHistograms(){
|
|||
}
|
||||
|
||||
if (s0>10 && s1>10 && s2>10 && s3>10 && e0>10 && e1>10 && e2>10 && e3>10) {
|
||||
float_t rotation_angle = 31.;
|
||||
double_t Xr = (((s1+s2)/(s0+s1+s2+s3))-0.51)*cos(-rotation_angle*M_PI/180)-(((s2+s3)/(s0+s1+s2+s3))-0.51)*sin(-rotation_angle*M_PI/180);
|
||||
float_t rotation_angle = 31.;
|
||||
double_t Xr = (((s1+s2)/(s0+s1+s2+s3))-0.51)*cos(-rotation_angle*M_PI/180)-(((s2+s3)/(s0+s1+s2+s3))-0.51)*sin(-rotation_angle*M_PI/180);
|
||||
double_t Yr = (((s1+s2)/(s0+s1+s2+s3))-0.51)*sin(-rotation_angle*M_PI/180)+(((s2+s3)/(s0+s1+s2+s3))-0.51)*cos(-rotation_angle*M_PI/180);
|
||||
|
||||
double_t X2 = ((e0-e1)/(e0+e1)); // PSD X position
|
||||
|
|
|
@ -2,37 +2,29 @@
|
|||
#define COINCIDENTANLAYZER_H
|
||||
|
||||
#include "Analyser.h"
|
||||
#include "FSUDAQ.h"
|
||||
|
||||
//^===========================================
|
||||
class CoincidentAnalyzer : public Analyzer{
|
||||
Q_OBJECT
|
||||
public:
|
||||
CoincidentAnalyzer(Digitizer ** digi, unsigned int nDigi, QMainWindow * parent = nullptr): Analyzer(digi, nDigi, parent){
|
||||
CoincidentAnalyzer(Digitizer ** digi, unsigned int nDigi, QString rawDataPath, QMainWindow * parent = nullptr): Analyzer(digi, nDigi, parent){
|
||||
|
||||
this->digi = digi;
|
||||
this->nDigi = nDigi;
|
||||
this->rawDataPath = rawDataPath;
|
||||
|
||||
SetUpdateTimeInSec(1.0);
|
||||
|
||||
//RedefineEventBuilder({0}); // only build for the 0-th digitizer, otherwise, it will build event accross all digitizers
|
||||
SetBackwardBuild(false, 100); // using normal building (acceding in time) or backward building, int the case of backward building, default events to be build is 100.
|
||||
|
||||
evtbder = GetEventBuilder();
|
||||
evtbder->SetTimeWindow(500);
|
||||
|
||||
//========== use the influx from the Analyzer
|
||||
influx = new InfluxDB("https://fsunuc.physics.fsu.edu/influx/");
|
||||
dataBaseName = "testing";
|
||||
mb->SetTimeWindow(500);
|
||||
|
||||
allowSignalSlot = false;
|
||||
SetUpCanvas();
|
||||
|
||||
LoadHistRange();
|
||||
|
||||
}
|
||||
|
||||
~CoincidentAnalyzer(){
|
||||
SaveHistRange();
|
||||
}
|
||||
|
||||
void SetUpCanvas();
|
||||
|
@ -42,13 +34,11 @@ public slots:
|
|||
|
||||
private:
|
||||
|
||||
Digitizer ** digi;
|
||||
unsigned int nDigi;
|
||||
|
||||
MultiBuilder *evtbder;
|
||||
|
||||
bool allowSignalSlot;
|
||||
|
||||
QLineEdit * leInfluxIP;
|
||||
QLineEdit * leDBName;
|
||||
|
||||
// declaie histograms
|
||||
Histogram2D * h2D;
|
||||
Histogram1D * h1;
|
||||
|
@ -73,35 +63,48 @@ private:
|
|||
RComboBox * aDigi;
|
||||
RComboBox * aCh;
|
||||
|
||||
void SaveHistRange();
|
||||
void LoadHistRange();
|
||||
QString rawDataPath;
|
||||
void SaveSettings();
|
||||
void LoadSettings();
|
||||
|
||||
};
|
||||
|
||||
|
||||
inline void CoincidentAnalyzer::SetUpCanvas(){
|
||||
|
||||
setWindowTitle("Online Coincident Analyzer");
|
||||
setGeometry(0, 0, 1600, 1000);
|
||||
|
||||
{//^====== magnet and reaction setting
|
||||
{//^====== channel settings
|
||||
QGroupBox * box = new QGroupBox("Configuration", this);
|
||||
layout->addWidget(box, 0, 0);
|
||||
QGridLayout * boxLayout = new QGridLayout(box);
|
||||
boxLayout->setAlignment(Qt::AlignTop | Qt::AlignLeft);
|
||||
box->setLayout(boxLayout);
|
||||
|
||||
int rowID = 0;
|
||||
|
||||
{
|
||||
chkRunAnalyzer = new QCheckBox("Run Analyzer", this);
|
||||
boxLayout->addWidget(chkRunAnalyzer, 0, 0);
|
||||
boxLayout->addWidget(chkRunAnalyzer, rowID, 0);
|
||||
|
||||
connect(chkRunAnalyzer, &QCheckBox::stateChanged, this, [=](int state){
|
||||
|
||||
sbBuildWindow->setEnabled(state != Qt::Checked);
|
||||
sbUpdateTime->setEnabled(state != Qt::Checked);
|
||||
chkBackWardBuilding->setEnabled(state != Qt::Checked);
|
||||
sbBackwardCount->setEnabled(state != Qt::Checked);
|
||||
|
||||
});
|
||||
|
||||
QLabel * lbUpdateTime = new QLabel("Update Period [s]", this);
|
||||
lbUpdateTime->setAlignment(Qt::AlignRight | Qt::AlignCenter);
|
||||
boxLayout->addWidget(lbUpdateTime, 0, 1);
|
||||
boxLayout->addWidget(lbUpdateTime, rowID, 1);
|
||||
sbUpdateTime = new RSpinBox(this, 1);
|
||||
sbUpdateTime->setMinimum(0.1);
|
||||
sbUpdateTime->setMaximum(5);
|
||||
sbUpdateTime->setValue(1);
|
||||
boxLayout->addWidget(sbUpdateTime, 0, 2);
|
||||
boxLayout->addWidget(sbUpdateTime, rowID, 2);
|
||||
|
||||
connect(sbUpdateTime, &RSpinBox::valueChanged, this, [=](){ sbUpdateTime->setStyleSheet("color : blue"); });
|
||||
|
||||
|
@ -110,17 +113,36 @@ inline void CoincidentAnalyzer::SetUpCanvas(){
|
|||
SetUpdateTimeInSec(sbUpdateTime->value());
|
||||
});
|
||||
|
||||
QLabel * lbBuildWindow = new QLabel("Event Window [ns]", this);
|
||||
lbBuildWindow->setAlignment(Qt::AlignRight | Qt::AlignCenter);
|
||||
boxLayout->addWidget(lbBuildWindow, rowID, 3);
|
||||
sbBuildWindow = new RSpinBox(this, 0);
|
||||
sbBuildWindow->setMinimum(1);
|
||||
sbBuildWindow->setMaximum(9999999999);
|
||||
sbBuildWindow->setValue(1000);
|
||||
boxLayout->addWidget(sbBuildWindow, rowID, 4);
|
||||
|
||||
connect(sbBuildWindow, &RSpinBox::valueChanged, this, [=](){
|
||||
sbBuildWindow->setStyleSheet("color : blue;");
|
||||
});
|
||||
|
||||
connect(sbBuildWindow, &RSpinBox::returnPressed, this, [=](){
|
||||
sbBuildWindow->setStyleSheet("");
|
||||
mb->SetTimeWindow((int)sbBuildWindow->value());
|
||||
});
|
||||
|
||||
rowID ++;
|
||||
chkBackWardBuilding = new QCheckBox("Use Backward builder", this);
|
||||
boxLayout->addWidget(chkBackWardBuilding, 1, 0);
|
||||
boxLayout->addWidget(chkBackWardBuilding, rowID, 0);
|
||||
|
||||
QLabel * lbBKWindow = new QLabel("Max No. Backward Event", this);
|
||||
lbBKWindow->setAlignment(Qt::AlignRight | Qt::AlignCenter);
|
||||
boxLayout->addWidget(lbBKWindow, 1, 1);
|
||||
boxLayout->addWidget(lbBKWindow, rowID, 1);
|
||||
sbBackwardCount = new RSpinBox(this, 0);
|
||||
sbBackwardCount->setMinimum(1);
|
||||
sbBackwardCount->setMaximum(9999);
|
||||
sbBackwardCount->setValue(100);
|
||||
boxLayout->addWidget(sbBackwardCount, 1, 2);
|
||||
boxLayout->addWidget(sbBackwardCount, rowID, 2);
|
||||
|
||||
chkBackWardBuilding->setChecked(false);
|
||||
sbBackwardCount->setEnabled(false);
|
||||
|
@ -140,61 +162,48 @@ inline void CoincidentAnalyzer::SetUpCanvas(){
|
|||
SetBackwardBuild(true, sbBackwardCount->value());
|
||||
});
|
||||
|
||||
QLabel * lbBuildWindow = new QLabel("Event Window [tick]", this);
|
||||
lbBuildWindow->setAlignment(Qt::AlignRight | Qt::AlignCenter);
|
||||
boxLayout->addWidget(lbBuildWindow, 2, 1);
|
||||
sbBuildWindow = new RSpinBox(this, 0);
|
||||
sbBuildWindow->setMinimum(1);
|
||||
sbBuildWindow->setMaximum(9999999999);
|
||||
boxLayout->addWidget(sbBuildWindow, 2, 2);
|
||||
|
||||
connect(sbBuildWindow, &RSpinBox::valueChanged, this, [=](){
|
||||
sbBuildWindow->setStyleSheet("color : blue;");
|
||||
});
|
||||
|
||||
connect(sbBuildWindow, &RSpinBox::returnPressed, this, [=](){
|
||||
sbBuildWindow->setStyleSheet("");
|
||||
evtbder->SetTimeWindow((int)sbBuildWindow->value());
|
||||
});
|
||||
}
|
||||
|
||||
{
|
||||
QFrame *separator = new QFrame(box);
|
||||
separator->setFrameShape(QFrame::HLine);
|
||||
separator->setFrameShadow(QFrame::Sunken);
|
||||
boxLayout->addWidget(separator, 3, 0, 1, 4);
|
||||
rowID ++;
|
||||
QFrame *separator0 = new QFrame(box);
|
||||
separator0->setFrameShape(QFrame::HLine);
|
||||
separator0->setFrameShadow(QFrame::Sunken);
|
||||
boxLayout->addWidget(separator0, rowID, 0, 1, 4);
|
||||
|
||||
rowID ++;
|
||||
QLabel * lbXDigi = new QLabel("X-Digi", this);
|
||||
lbXDigi->setAlignment(Qt::AlignRight | Qt::AlignCenter);
|
||||
boxLayout->addWidget(lbXDigi, 4, 0);
|
||||
boxLayout->addWidget(lbXDigi, rowID, 0);
|
||||
xDigi = new RComboBox(this);
|
||||
for(unsigned int i = 0; i < nDigi; i ++ ){
|
||||
xDigi->addItem("Digi-" + QString::number(digi[i]->GetSerialNumber()), i);
|
||||
}
|
||||
boxLayout->addWidget(xDigi, 4, 1);
|
||||
boxLayout->addWidget(xDigi, rowID, 1);
|
||||
|
||||
QLabel * lbXCh = new QLabel("X-Ch", this);
|
||||
lbXCh->setAlignment(Qt::AlignRight | Qt::AlignCenter);
|
||||
boxLayout->addWidget(lbXCh, 4, 2);
|
||||
boxLayout->addWidget(lbXCh, rowID, 2);
|
||||
xCh = new RComboBox(this);
|
||||
for( int i = 0; i < digi[0]->GetNumInputCh(); i++) xCh->addItem("Ch-" + QString::number(i), i);
|
||||
boxLayout->addWidget(xCh, 4, 3);
|
||||
boxLayout->addWidget(xCh, rowID, 3);
|
||||
|
||||
rowID ++;
|
||||
QLabel * lbYDigi = new QLabel("Y-Digi", this);
|
||||
lbYDigi->setAlignment(Qt::AlignRight | Qt::AlignCenter);
|
||||
boxLayout->addWidget(lbYDigi, 5, 0);
|
||||
boxLayout->addWidget(lbYDigi, rowID, 0);
|
||||
yDigi = new RComboBox(this);
|
||||
for(unsigned int i = 0; i < nDigi; i ++ ){
|
||||
yDigi->addItem("Digi-" + QString::number(digi[i]->GetSerialNumber()), i);
|
||||
}
|
||||
boxLayout->addWidget(yDigi, 5, 1);
|
||||
boxLayout->addWidget(yDigi, rowID, 1);
|
||||
|
||||
QLabel * lbYCh = new QLabel("Y-Ch", this);
|
||||
lbYCh->setAlignment(Qt::AlignRight | Qt::AlignCenter);
|
||||
boxLayout->addWidget(lbYCh, 5, 2);
|
||||
boxLayout->addWidget(lbYCh, rowID, 2);
|
||||
yCh = new RComboBox(this);
|
||||
for( int i = 0; i < digi[0]->GetNumInputCh(); i++) yCh->addItem("Ch-" + QString::number(i), i);
|
||||
boxLayout->addWidget(yCh, 5, 3);
|
||||
boxLayout->addWidget(yCh, rowID, 3);
|
||||
|
||||
connect(xDigi, &RComboBox::currentIndexChanged, this, [=](){
|
||||
allowSignalSlot = false;
|
||||
|
@ -241,26 +250,28 @@ inline void CoincidentAnalyzer::SetUpCanvas(){
|
|||
}
|
||||
|
||||
{
|
||||
rowID ++;
|
||||
QFrame *separator1 = new QFrame(box);
|
||||
separator1->setFrameShape(QFrame::HLine);
|
||||
separator1->setFrameShadow(QFrame::Sunken);
|
||||
boxLayout->addWidget(separator1, 6, 0, 1, 4);
|
||||
boxLayout->addWidget(separator1, rowID, 0, 1, 4);
|
||||
|
||||
rowID ++;
|
||||
QLabel * lbaDigi = new QLabel("ID-Digi", this);
|
||||
lbaDigi->setAlignment(Qt::AlignRight | Qt::AlignCenter);
|
||||
boxLayout->addWidget(lbaDigi, 7, 0);
|
||||
boxLayout->addWidget(lbaDigi, rowID, 0);
|
||||
aDigi = new RComboBox(this);
|
||||
for(unsigned int i = 0; i < nDigi; i ++ ){
|
||||
aDigi->addItem("Digi-" + QString::number(digi[i]->GetSerialNumber()), digi[i]->GetSerialNumber());
|
||||
aDigi->addItem("Digi-" + QString::number(digi[i]->GetSerialNumber()), i);
|
||||
}
|
||||
boxLayout->addWidget(aDigi, 7, 1);
|
||||
boxLayout->addWidget(aDigi, rowID, 1);
|
||||
|
||||
QLabel * lbaCh = new QLabel("1D-Ch", this);
|
||||
lbaCh->setAlignment(Qt::AlignRight | Qt::AlignCenter);
|
||||
boxLayout->addWidget(lbaCh, 7, 2);
|
||||
boxLayout->addWidget(lbaCh, rowID, 2);
|
||||
aCh = new RComboBox(this);
|
||||
for( int i = 0; i < digi[0]->GetNumInputCh(); i++) aCh->addItem("Ch-" + QString::number(i), i);
|
||||
boxLayout->addWidget(aCh, 7, 3);
|
||||
boxLayout->addWidget(aCh, rowID, 3);
|
||||
|
||||
connect(aDigi, &RComboBox::currentIndexChanged, this, [=](){
|
||||
allowSignalSlot = false;
|
||||
|
@ -290,13 +301,47 @@ inline void CoincidentAnalyzer::SetUpCanvas(){
|
|||
}
|
||||
|
||||
{
|
||||
QFrame *separator1 = new QFrame(box);
|
||||
separator1->setFrameShape(QFrame::HLine);
|
||||
separator1->setFrameShadow(QFrame::Sunken);
|
||||
boxLayout->addWidget(separator1, 8, 0, 1, 4);
|
||||
rowID ++;
|
||||
QFrame *separator2 = new QFrame(box);
|
||||
separator2->setFrameShape(QFrame::HLine);
|
||||
separator2->setFrameShadow(QFrame::Sunken);
|
||||
boxLayout->addWidget(separator2, rowID, 0, 1, 4);
|
||||
|
||||
QPushButton * bnClearHist = new QPushButton("Clear All Hist.");
|
||||
boxLayout->addWidget(bnClearHist, 9, 1);
|
||||
rowID ++;
|
||||
QLabel * lbIP = new QLabel("Database IP :", box);
|
||||
lbIP->setAlignment(Qt::AlignRight | Qt::AlignCenter);
|
||||
boxLayout->addWidget(lbIP, rowID, 0);
|
||||
leInfluxIP = new QLineEdit(box);
|
||||
leInfluxIP->setReadOnly(true);
|
||||
boxLayout->addWidget(leInfluxIP, rowID, 1, 1, 3);
|
||||
|
||||
QPushButton * bnInflux = new QPushButton("Set Influx", box);
|
||||
boxLayout->addWidget(bnInflux, rowID, 4);
|
||||
|
||||
rowID ++;
|
||||
QLabel * lbDBName = new QLabel("Database name :", box);
|
||||
lbDBName->setAlignment(Qt::AlignRight | Qt::AlignCenter);
|
||||
boxLayout->addWidget(lbDBName, rowID, 0);
|
||||
leDBName = new QLineEdit(box);
|
||||
leDBName->setReadOnly(true);
|
||||
boxLayout->addWidget(leDBName, rowID, 1);
|
||||
|
||||
connect(bnInflux, &QPushButton::clicked, this, [=](){
|
||||
SetDatabaseButton();
|
||||
if( influx ) {
|
||||
leDBName->setText(dataBaseName);
|
||||
leInfluxIP->setText(dataBaseIP);
|
||||
}
|
||||
});
|
||||
|
||||
// rowID ++;
|
||||
// QFrame *separator3 = new QFrame(box);
|
||||
// separator3->setFrameShape(QFrame::HLine);
|
||||
// separator3->setFrameShadow(QFrame::Sunken);
|
||||
// boxLayout->addWidget(separator3, rowID, 0, 1, 4);
|
||||
|
||||
QPushButton * bnClearHist = new QPushButton("Clear All Hist.", this);
|
||||
boxLayout->addWidget(bnClearHist, rowID, 2);
|
||||
|
||||
connect(bnClearHist, &QPushButton::clicked, this, [=](){
|
||||
h2D->Clear();
|
||||
|
@ -305,17 +350,26 @@ inline void CoincidentAnalyzer::SetUpCanvas(){
|
|||
hMulti->Clear();
|
||||
});
|
||||
|
||||
}
|
||||
QPushButton * bnSaveSettings = new QPushButton("Save Settings", this);
|
||||
boxLayout->addWidget(bnSaveSettings, rowID, 3);
|
||||
|
||||
connect(bnSaveSettings, &QPushButton::clicked, this, &CoincidentAnalyzer::SaveSettings);
|
||||
|
||||
QPushButton * bnLoadSettings = new QPushButton("Load Settings", this);
|
||||
boxLayout->addWidget(bnLoadSettings, rowID, 4);
|
||||
|
||||
connect(bnLoadSettings, &QPushButton::clicked, this, &CoincidentAnalyzer::LoadSettings);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//============ histograms
|
||||
hMulti = new Histogram1D("Multiplicity", "", 10, 0, 10, this);
|
||||
hMulti = new Histogram1D("Multiplicity", "", 16, 0, 16, this);
|
||||
layout->addWidget(hMulti, 0, 1);
|
||||
|
||||
// the "this" make the histogram a child of the SplitPole class. When SplitPole destory, all childs destory as well.
|
||||
h2D = new Histogram2D("Coincident Plot", "XXX", "YYY", 100, 0, 5000, 100, 0, 5000, this);
|
||||
h2D = new Histogram2D("Coincident Plot", "XXX", "YYY", 200, 0, 30000, 200, 0, 30000, this, rawDataPath);
|
||||
//layout is inheriatge from Analyzer
|
||||
layout->addWidget(h2D, 1, 0, 2, 1);
|
||||
|
||||
|
@ -327,17 +381,16 @@ inline void CoincidentAnalyzer::SetUpCanvas(){
|
|||
h2D->SetYTitle("Digi-" + QString::number(digi[bd]->GetSerialNumber()) + ", Ch-" + QString::number(ch));
|
||||
h2D->UpdatePlot();
|
||||
|
||||
|
||||
h1 = new Histogram1D("1D Plot", "XXX", 300, 0, 5000, this);
|
||||
h1 = new Histogram1D("1D Plot", "XXX", 300, 0, 30000, this);
|
||||
h1->SetColor(Qt::darkGreen);
|
||||
h1->AddDataList("Test", Qt::red); // add another histogram in h1, Max Data List is 10
|
||||
// h1->AddDataList("Test", Qt::red); // add another histogram in h1, Max Data List is 10
|
||||
bd = aDigi->currentData().toInt();
|
||||
ch = aCh->currentData().toInt();
|
||||
h1->SetXTitle("Digi-" + QString::number(digi[bd]->GetSerialNumber()) + ", Ch-" + QString::number(ch));
|
||||
h1->UpdatePlot();
|
||||
layout->addWidget(h1, 1, 1);
|
||||
|
||||
h1g = new Histogram1D("1D Plot (PID gated)", "XXX", 300, 0, 5000, this);
|
||||
h1g = new Histogram1D("1D Plot (PID gated)", "XXX", 300, 0, 30000, this);
|
||||
h1g->SetXTitle("Digi-" + QString::number(digi[bd]->GetSerialNumber()) + ", Ch-" + QString::number(ch));
|
||||
h1g->UpdatePlot();
|
||||
layout->addWidget(h1g, 2, 1);
|
||||
|
@ -345,17 +398,25 @@ inline void CoincidentAnalyzer::SetUpCanvas(){
|
|||
layout->setColumnStretch(0, 1);
|
||||
layout->setColumnStretch(1, 1);
|
||||
|
||||
allowSignalSlot = true;
|
||||
|
||||
}
|
||||
|
||||
inline void CoincidentAnalyzer::UpdateHistograms(){
|
||||
|
||||
// printf(">>>>>>>>>>>>> CoincidentAnalyzer::%s | %d %d %d \n", __func__, this->isVisible(), chkRunAnalyzer->isChecked(), isWorking);
|
||||
|
||||
if( this->isVisible() == false ) return;
|
||||
if( chkRunAnalyzer->isChecked() == false ) return;
|
||||
|
||||
BuildEvents(); // call the event builder to build events
|
||||
unsigned long long t0 = getTime_ns();
|
||||
BuildEvents(false); // call the event builder to build events
|
||||
// unsigned long long t1 = getTime_ns();
|
||||
// printf("Event Build time : %llu ns = %.f msec\n", t1 - t0, (t1-t0)/1e6);
|
||||
|
||||
//============ Get events, and do analysis
|
||||
long eventBuilt = evtbder->eventBuilt;
|
||||
long eventBuilt = mb->eventBuilt;
|
||||
|
||||
if( eventBuilt == 0 ) return;
|
||||
|
||||
//============ Get the cut list, if any
|
||||
|
@ -374,13 +435,17 @@ inline void CoincidentAnalyzer::UpdateHistograms(){
|
|||
int y_bd = yDigi->currentData().toInt();
|
||||
int y_ch = yCh->currentData().toInt();
|
||||
|
||||
int a_sn = digi[a_bd]->GetSerialNumber();
|
||||
int x_sn = digi[x_bd]->GetSerialNumber();
|
||||
int y_sn = digi[y_bd]->GetSerialNumber();
|
||||
|
||||
//============ Processing data and fill histograms
|
||||
long eventIndex = evtbder->eventIndex;
|
||||
long eventIndex = mb->eventIndex;
|
||||
long eventStart = eventIndex - eventBuilt + 1;
|
||||
if(eventStart < 0 ) eventStart += MaxNEvent;
|
||||
|
||||
for( long i = eventStart ; i <= eventIndex; i ++ ){
|
||||
std::vector<Hit> event = evtbder->events[i];
|
||||
std::vector<Hit> event = mb->events[i];
|
||||
|
||||
hMulti->Fill((int) event.size());
|
||||
if( event.size() == 0 ) return;
|
||||
|
@ -389,17 +454,17 @@ inline void CoincidentAnalyzer::UpdateHistograms(){
|
|||
int xE = -1, yE = -1;
|
||||
unsigned long long xT = 0;
|
||||
for( int k = 0; k < (int) event.size(); k++ ){
|
||||
//event[k].Print();
|
||||
if( event[k].sn == a_bd && event[k].ch == a_ch) {
|
||||
// event[k].Print();
|
||||
if( event[k].sn == a_sn && event[k].ch == a_ch) {
|
||||
h1->Fill(event[k].energy);
|
||||
aE = event[k].energy;
|
||||
}
|
||||
|
||||
if( event[k].sn == x_bd && event[k].ch == x_ch) {
|
||||
if( event[k].sn == x_sn && event[k].ch == x_ch) {
|
||||
xE = event[k].energy;
|
||||
xT = event[k].timestamp;
|
||||
}
|
||||
if( event[k].sn == y_bd && event[k].ch == y_ch) yE = event[k].energy;
|
||||
if( event[k].sn == y_sn && event[k].ch == y_ch) yE = event[k].energy;
|
||||
}
|
||||
|
||||
if( xE >= 0 && yE >= 0 ) h2D->Fill(xE, yE);
|
||||
|
@ -415,6 +480,10 @@ inline void CoincidentAnalyzer::UpdateHistograms(){
|
|||
if( p == 0 && aE >= 0 ) h1g->Fill(aE); // only for the 1st gate
|
||||
}
|
||||
}
|
||||
|
||||
unsigned long long ta = getTime_ns();
|
||||
if( ta - t0 > sbUpdateTime->value() * 0.9 * GetUpdateTimeInSec() * 1e9 ) break;
|
||||
|
||||
}
|
||||
|
||||
h2D->UpdatePlot();
|
||||
|
@ -422,25 +491,177 @@ inline void CoincidentAnalyzer::UpdateHistograms(){
|
|||
hMulti->UpdatePlot();
|
||||
h1g->UpdatePlot();
|
||||
|
||||
// QList<QString> cutNameList = h2D->GetCutNameList();
|
||||
// for( int p = 0; p < cutList.count(); p ++){
|
||||
// if( cutList[p].isEmpty() ) continue;
|
||||
// double dT = (tMax[p]-tMin[p]) * tick2ns / 1e9; // tick to sec
|
||||
// double rate = count[p]*1.0/(dT);
|
||||
//printf("%llu %llu, %f %d\n", tMin[p], tMax[p], dT, count[p]);
|
||||
//printf("%10s | %d | %f Hz \n", cutNameList[p].toStdString().c_str(), count[p], rate);
|
||||
|
||||
// influx->AddDataPoint("Cut,name=" + cutNameList[p].toStdString()+ " value=" + std::to_string(rate));
|
||||
// influx->WriteData(dataBaseName);
|
||||
// influx->ClearDataPointsBuffer();
|
||||
// }
|
||||
if( influx ){
|
||||
QList<QString> cutNameList = h2D->GetCutNameList();
|
||||
for( int p = 0; p < cutList.count(); p ++){
|
||||
if( cutList[p].isEmpty() ) continue;
|
||||
double dT = (tMax[p]-tMin[p]) / 1e9;
|
||||
double rate = count[p]*1.0/(dT);
|
||||
// printf("%llu %llu, %f %d\n", tMin[p], tMax[p], dT, count[p]);
|
||||
printf("%10s | %d | %f Hz \n", cutNameList[p].toStdString().c_str(), count[p], rate);
|
||||
|
||||
influx->AddDataPoint("Cut,name=" + cutNameList[p].toStdString()+ " value=" + std::to_string(rate));
|
||||
}
|
||||
|
||||
influx->WriteData(dataBaseName.toStdString());
|
||||
influx->ClearDataPointsBuffer();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
inline void CoincidentAnalyzer::SaveHistRange(){
|
||||
inline void CoincidentAnalyzer::SaveSettings(){
|
||||
QString filePath = QFileDialog::getSaveFileName(this,
|
||||
"Save Settings to File",
|
||||
QDir::toNativeSeparators(rawDataPath + "/CoinAnaSettings.txt" ),
|
||||
"Text file (*.txt)");
|
||||
|
||||
if (!filePath.isEmpty()){
|
||||
|
||||
QFile file(filePath);
|
||||
if (file.open(QIODevice::WriteOnly | QIODevice::Text)) {
|
||||
QTextStream out(&file);
|
||||
|
||||
// Define the text to write
|
||||
QStringList lines;
|
||||
|
||||
lines << QString::number(digi[aDigi->currentData().toInt()]->GetSerialNumber());
|
||||
lines << QString::number(aCh->currentData().toInt());
|
||||
lines << QString::number(h1->GetNBin());
|
||||
lines << QString::number(h1->GetXMin());
|
||||
lines << QString::number(h1->GetXMax());
|
||||
|
||||
lines << QString::number(digi[xDigi->currentData().toInt()]->GetSerialNumber());
|
||||
lines << QString::number(xCh->currentData().toInt());
|
||||
lines << QString::number(h2D->GetXNBin());
|
||||
lines << QString::number(h2D->GetXMin());
|
||||
lines << QString::number(h2D->GetXMax());
|
||||
|
||||
lines << QString::number(digi[yDigi->currentData().toInt()]->GetSerialNumber());
|
||||
lines << QString::number(yCh->currentData().toInt());
|
||||
lines << QString::number(h2D->GetYNBin());
|
||||
lines << QString::number(h2D->GetYMin());
|
||||
lines << QString::number(h2D->GetYMax());
|
||||
|
||||
lines << QString::number(sbUpdateTime->value());
|
||||
lines << QString::number(chkBackWardBuilding->isChecked());
|
||||
lines << QString::number(sbBackwardCount->value());
|
||||
|
||||
lines<< dataBaseIP;
|
||||
lines<< dataBaseName;
|
||||
lines<< dataBaseToken;
|
||||
|
||||
lines << "#===== End of File";
|
||||
|
||||
// Write each line to the file
|
||||
for (const QString &line : lines) out << line << "\n";
|
||||
|
||||
// Close the file
|
||||
file.close();
|
||||
qDebug() << "File written successfully to" << filePath;
|
||||
}else{
|
||||
qWarning() << "Unable to open file" << filePath;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
inline void CoincidentAnalyzer::LoadHistRange(){
|
||||
inline void CoincidentAnalyzer::LoadSettings(){
|
||||
|
||||
QString filePath = QFileDialog::getOpenFileName(this,
|
||||
"Load Settings to File",
|
||||
rawDataPath,
|
||||
"Text file (*.txt)");
|
||||
|
||||
int a_sn, a_ch, a_bin;
|
||||
float a_min, a_max;
|
||||
int x_sn, x_ch, x_bin;
|
||||
float x_min, x_max;
|
||||
int y_sn, y_ch, y_bin;
|
||||
float y_min, y_max;
|
||||
|
||||
float updateTime = 1.0;
|
||||
int bkCount = 100;
|
||||
bool isBkEvtBuild = false;
|
||||
|
||||
if (!filePath.isEmpty()) {
|
||||
|
||||
QFile file(filePath);
|
||||
|
||||
if (file.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||
QTextStream in(&file);
|
||||
|
||||
short count = 0;
|
||||
while (!in.atEnd()) {
|
||||
QString line = in.readLine();
|
||||
|
||||
if( count == 0 ) a_sn = line.toInt();
|
||||
if( count == 1 ) a_ch = line.toInt();
|
||||
if( count == 2 ) a_bin = line.toInt();
|
||||
if( count == 3 ) a_min = line.toFloat();
|
||||
if( count == 4 ) a_max = line.toFloat();
|
||||
|
||||
if( count == 5 ) x_sn = line.toFloat();
|
||||
if( count == 6 ) x_ch = line.toFloat();
|
||||
if( count == 7 ) x_bin = line.toFloat();
|
||||
if( count == 8 ) x_min = line.toFloat();
|
||||
if( count == 9 ) x_max = line.toFloat();
|
||||
|
||||
if( count == 10 ) y_sn = line.toFloat();
|
||||
if( count == 11 ) y_ch = line.toFloat();
|
||||
if( count == 12 ) y_bin = line.toFloat();
|
||||
if( count == 13 ) y_min = line.toFloat();
|
||||
if( count == 14 ) y_max = line.toFloat();
|
||||
|
||||
if( count == 15 ) updateTime = line.toFloat();
|
||||
if( count == 16 ) isBkEvtBuild = line.toInt();
|
||||
if( count == 17 ) bkCount = line.toInt();
|
||||
|
||||
if( count == 18 ) dataBaseIP = line;
|
||||
if( count == 19 ) dataBaseName = line;
|
||||
if( count == 20 ) dataBaseToken = line;
|
||||
|
||||
count ++;
|
||||
}
|
||||
|
||||
file.close();
|
||||
qDebug() << "File read successfully from" << filePath;
|
||||
|
||||
if( count >= 21 ){
|
||||
|
||||
sbUpdateTime->setValue(updateTime);
|
||||
chkBackWardBuilding->setChecked(isBkEvtBuild);
|
||||
sbBackwardCount->setValue(bkCount);
|
||||
|
||||
int x_index = xDigi->findText("Digi-" + QString::number(x_sn));
|
||||
int y_index = yDigi->findText("Digi-" + QString::number(y_sn));
|
||||
int a_index = aDigi->findText("Digi-" + QString::number(a_sn));
|
||||
if( x_index == -1 ) qWarning() << " Cannot find digitizer " << x_sn;
|
||||
if( y_index == -1 ) qWarning() << " Cannot find digitizer " << y_sn;
|
||||
if( a_index == -1 ) qWarning() << " Cannot find digitizer " << a_sn;
|
||||
|
||||
xDigi->setCurrentIndex(x_index);
|
||||
yDigi->setCurrentIndex(y_index);
|
||||
aDigi->setCurrentIndex(a_index);
|
||||
|
||||
xCh->setCurrentIndex(x_ch);
|
||||
yCh->setCurrentIndex(y_ch);
|
||||
aCh->setCurrentIndex(a_ch);
|
||||
|
||||
h1->Rebin(a_bin, a_min, a_max);
|
||||
h1g->Rebin(a_bin, a_min, a_max);
|
||||
h2D->Rebin(x_bin, x_min, x_max, y_bin, y_min, y_max);
|
||||
|
||||
SetDatabase(dataBaseIP, dataBaseName, dataBaseToken);
|
||||
if( influx ){
|
||||
leDBName->setText(dataBaseName);
|
||||
leInfluxIP->setText(dataBaseIP);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}else {
|
||||
qWarning() << "Unable to open file" << filePath;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -5,6 +5,8 @@
|
|||
#include "Isotope.h"
|
||||
|
||||
#include <map>
|
||||
#include <QApplication>
|
||||
// #include <QScreen>
|
||||
|
||||
namespace EncoreChMap{
|
||||
|
||||
|
@ -82,8 +84,15 @@ private:
|
|||
|
||||
inline void Encore::SetUpCanvas(){
|
||||
|
||||
setGeometry(0, 0, 1600, 1600);
|
||||
|
||||
//====== resize window if screen too small
|
||||
QScreen * screen = QGuiApplication::primaryScreen();
|
||||
QRect screenGeo = screen->geometry();
|
||||
if( screenGeo.width() < 1000 || screenGeo.height() < 1000) {
|
||||
setGeometry(0, 0, screenGeo.width() - 100, screenGeo.height() -100);
|
||||
}else{
|
||||
setGeometry(0, 0, 1000, 1000);
|
||||
}
|
||||
// setGeometry(0, 0, 1600, 1600);
|
||||
chkRunAnalyzer = new QCheckBox("Run Analyzer", this);
|
||||
layout->addWidget(chkRunAnalyzer, 0, 0);
|
||||
|
||||
|
|
|
@ -31,9 +31,7 @@ public:
|
|||
evtbder = GetEventBuilder();
|
||||
evtbder->SetTimeWindow(500); //ns
|
||||
|
||||
//========== use the influx from the Analyzer
|
||||
influx = new InfluxDB("https://fsunuc.physics.fsu.edu/influx/");
|
||||
dataBaseName = "testing";
|
||||
SetDatabase("https://localhost:8086", "testing", "zKhzKk4Yhf1l9QU-yE2GsIZ1RazqUgoW3NlF8LJqq_xDMwatOJwg1sKrjgq36uLEsQf8Fmn4sJALP7Kkilk14A==");
|
||||
|
||||
SetUpCanvas(); // see below
|
||||
|
||||
|
@ -251,7 +249,7 @@ inline void MCP::UpdateHistograms(){
|
|||
//printf("%10s | %d | %f Hz \n", cutNameList[p].toStdString().c_str(), count[p], rate);
|
||||
|
||||
influx->AddDataPoint("Cut,name=" + cutNameList[p].toStdString()+ " value=" + std::to_string(rate));
|
||||
influx->WriteData(dataBaseName);
|
||||
influx->WriteData(dataBaseName.toStdString());
|
||||
influx->ClearDataPointsBuffer();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,9 +28,7 @@ public:
|
|||
evtbder = GetEventBuilder();
|
||||
evtbder->SetTimeWindow(500);
|
||||
|
||||
//========== use the influx from the Analyzer
|
||||
influx = new InfluxDB("https://fsunuc.physics.fsu.edu/influx/");
|
||||
dataBaseName = "testing";
|
||||
SetDatabase("https://localhost:8086", "testing", "zKhzKk4Yhf1l9QU-yE2GsIZ1RazqUgoW3NlF8LJqq_xDMwatOJwg1sKrjgq36uLEsQf8Fmn4sJALP7Kkilk14A==");
|
||||
|
||||
SetUpCanvas(); // see below
|
||||
|
||||
|
|
178
analyzers/MUSICAnalyzer.h
Normal file
178
analyzers/MUSICAnalyzer.h
Normal file
|
@ -0,0 +1,178 @@
|
|||
#ifndef MUSICANLAYZER_H
|
||||
#define MUSICANLAYZER_H
|
||||
|
||||
#include "Analyser.h"
|
||||
#include "Isotope.h"
|
||||
|
||||
#include <map>
|
||||
#include <QApplication>
|
||||
// #include <QScreen>
|
||||
|
||||
namespace MUSICChMap{
|
||||
|
||||
const std::map<unsigned short, int> SN2Bd = {
|
||||
{16828, 0},
|
||||
{16829, 1},
|
||||
{16827, 2},
|
||||
{23986, 3}
|
||||
};
|
||||
|
||||
//Left 0->15
|
||||
//Right 16->31
|
||||
//Individual{32=Grid, 33=S0, 34=cathode, 35=S17, 36=Si_dE, 100>pulser},
|
||||
//-1=empty
|
||||
const int mapping[4][16] = {
|
||||
// 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15
|
||||
{34, -1, 1, -1, 33, 101, 5, -1, 0, -1, 9, -1, 17, 13, -1, 32},
|
||||
{ 2, -1, 16, -1, 21, 102, 20, -1, 8, -1, 24, -1, 27, 28, -1, 14},
|
||||
{19, -1, 3, -1, 6, 103, 7, -1, 25, -1, 11, -1, 12, 15, -1, 10},
|
||||
{ 4, -1, 18, 36, 23, 104, 22, -1, 29, -1, 26, -1, 31, 30, -1, 35}
|
||||
};
|
||||
|
||||
// Gain matching [ch][bd]
|
||||
const double corr[16][4] = {
|
||||
{ 1.00000, 1.00000, 1.00000, 1.0000},
|
||||
{ 1.00000, 1.00000, 1.03158, 1.0000},
|
||||
{ 1.00000, 1.00000, 0.99240, 1.0000},
|
||||
{ 1.00000, 1.03704, 0.94004, 1.0000},
|
||||
{ 1.01031, 1.02084, 1.10114, 1.0000},
|
||||
{ 1.00000, 0.94685, 1.00513, 1.0000},
|
||||
{ 1.00000, 1.03431, 1.00513, 1.0000},
|
||||
{ 1.00000, 0.92670, 0.96078, 1.0000},
|
||||
{ 1.03431, 0.94685, 0.96314, 1.0000},
|
||||
{ 1.00000, 1.03158, 0.95145, 1.0000},
|
||||
{ 0.95145, 1.00256, 0.97270, 1.0000},
|
||||
{ 1.00000, 1.00256, 0.90950, 1.0000},
|
||||
{ 1.03704, 0.99492, 0.98740, 1.0000},
|
||||
{ 1.00000, 1.00000, 0.99746, 1.0000},
|
||||
{ 0.96078, 1.03980, 1.00513, 1.0000},
|
||||
{ 1.00000, 1.05095, 1.00000, 1.0000},
|
||||
};
|
||||
|
||||
|
||||
};
|
||||
|
||||
class MUSIC : public Analyzer{
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
MUSIC(Digitizer ** digi, unsigned int nDigi, QMainWindow * parent = nullptr): Analyzer(digi, nDigi, parent){
|
||||
|
||||
SetUpdateTimeInSec(1.0);
|
||||
|
||||
SetBackwardBuild(true, 100); // using normal building (acceding in time) or backward building, int the case of backward building, default events to be build is 100.
|
||||
evtbder = GetEventBuilder();
|
||||
evtbder->SetTimeWindow(10000);
|
||||
|
||||
SetUpCanvas();
|
||||
}
|
||||
|
||||
// MUSIC(){};
|
||||
|
||||
void SetUpCanvas();
|
||||
|
||||
public slots:
|
||||
void UpdateHistograms();
|
||||
|
||||
private:
|
||||
|
||||
MultiBuilder *evtbder;
|
||||
|
||||
Histogram2D * hLeft;
|
||||
Histogram2D * hRight;
|
||||
Histogram2D * hLR;
|
||||
|
||||
Histogram1D * hMulti;
|
||||
|
||||
QCheckBox * chkRunAnalyzer;
|
||||
|
||||
};
|
||||
|
||||
|
||||
inline void MUSIC::SetUpCanvas(){
|
||||
|
||||
//====== resize window if screen too small
|
||||
QScreen * screen = QGuiApplication::primaryScreen();
|
||||
QRect screenGeo = screen->geometry();
|
||||
if( screenGeo.width() < 1000 || screenGeo.height() < 1000) {
|
||||
setGeometry(0, 0, screenGeo.width() - 100, screenGeo.height() -100);
|
||||
}else{
|
||||
setGeometry(0, 0, 1000, 1000);
|
||||
}
|
||||
// setGeometry(0, 0, 1600, 1600);
|
||||
chkRunAnalyzer = new QCheckBox("Run Analyzer", this);
|
||||
layout->addWidget(chkRunAnalyzer, 0, 0);
|
||||
|
||||
hLeft = new Histogram2D("Left", "Ch", "Energy", 16, 0, 16, 200, 0, 200, this);
|
||||
layout->addWidget(hLeft, 1, 0);
|
||||
hRight = new Histogram2D("Right", "Ch", "Energy", 16, 0, 16, 200, 0, 200, this);
|
||||
layout->addWidget(hRight, 1, 1);
|
||||
hLR = new Histogram2D("Left + Right", "Ch", "Energy", 17, 0, 16, 200, 0, 200, this);
|
||||
layout->addWidget(hLR, 2, 0);
|
||||
hMulti = new Histogram1D("Multi", "multiplicity", 40, 0, 40);
|
||||
layout->addWidget(hMulti, 2, 1);
|
||||
|
||||
}
|
||||
|
||||
inline void MUSIC::UpdateHistograms(){
|
||||
|
||||
if( this->isVisible() == false ) return;
|
||||
if( chkRunAnalyzer->isChecked() == false ) return;
|
||||
|
||||
BuildEvents(false); // call the event builder to build events
|
||||
|
||||
//============ Get events, and do analysis
|
||||
long eventBuilt = evtbder->eventBuilt;
|
||||
if( eventBuilt == 0 ) return;
|
||||
|
||||
//============ Processing data and fill histograms
|
||||
long eventIndex = evtbder->eventIndex;
|
||||
long eventStart = eventIndex - eventBuilt + 1;
|
||||
if(eventStart < 0 ) eventStart += MaxNEvent;
|
||||
|
||||
// printf("MUSIC::%s----------- 2 : %ld %ld \n", __func__, eventStart, eventIndex);
|
||||
for( long i = eventStart ; i <= eventIndex; i ++ ){
|
||||
std::vector<Hit> event = evtbder->events[i];
|
||||
// printf("MUSIC::%s----------- %ld, %zu\n", __func__, i, event.size());
|
||||
|
||||
hMulti->Fill((int) event.size());
|
||||
if( event.size() == 0 ) return;
|
||||
|
||||
double sum[17] = {0};
|
||||
for( int k = 0; k < (int) event.size(); k++ ){
|
||||
|
||||
// printf("--- %d\n", k);
|
||||
int bd = MUSICChMap::SN2Bd.at(event[k].sn);
|
||||
int ch = event[k].ch;
|
||||
|
||||
int ID = MUSICChMap::mapping[bd][ch];
|
||||
|
||||
if( ID < 0 ) continue;
|
||||
|
||||
double eC = event[k].energy;
|
||||
if( 0 <= ID && ID < 16 ) {
|
||||
eC *= MUSICChMap::corr[ch][bd];
|
||||
hLeft->Fill(ID, eC);
|
||||
sum[ID] += eC;
|
||||
}
|
||||
if( 16 <= ID && ID < 32 ) {
|
||||
eC *= MUSICChMap::corr[ch][bd];
|
||||
hRight->Fill(ID-16, eC );
|
||||
sum[ID-16] += eC ;
|
||||
}
|
||||
}
|
||||
|
||||
for( int ch = 0; ch < 17; ch++){
|
||||
if( sum[ch] > 0 ) hLR->Fill(ch, sum[ch]);
|
||||
//printf("%d | sum %d\n", ch, sum[ch]);
|
||||
}
|
||||
}
|
||||
|
||||
hLeft->UpdatePlot();
|
||||
hRight->UpdatePlot();
|
||||
hMulti->UpdatePlot();
|
||||
hLR->UpdatePlot();
|
||||
|
||||
}
|
||||
|
||||
#endif
|
239
analyzers/NeutronGamma.h
Normal file
239
analyzers/NeutronGamma.h
Normal file
|
@ -0,0 +1,239 @@
|
|||
#ifndef NEUTRONGAMMA_H
|
||||
#define NEUTRONGAMMA_H
|
||||
|
||||
|
||||
/***********************************\
|
||||
*
|
||||
* This Analyzer does not use event builder,
|
||||
* this simply use the energy_short and energy_long for each data.
|
||||
*
|
||||
*************************************/
|
||||
|
||||
#include <QMainWindow>
|
||||
#include <QChart>
|
||||
#include <QChartView>
|
||||
#include <QLabel>
|
||||
#include <QPushButton>
|
||||
#include <QCheckBox>
|
||||
#include <QLineEdit>
|
||||
#include <QGridLayout>
|
||||
#include <QGroupBox>
|
||||
#include <QVector>
|
||||
#include <QRandomGenerator>
|
||||
|
||||
#include "Analyser.h"
|
||||
|
||||
//^====================================================
|
||||
//^====================================================
|
||||
class NeutronGamma : public Analyzer{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
NeutronGamma(Digitizer ** digi, unsigned int nDigi, QString rawDataPath, QMainWindow * parent = nullptr): Analyzer(digi, nDigi, parent){
|
||||
this->digi = digi;
|
||||
this->nDigi = nDigi;
|
||||
this->settingPath = rawDataPath + "/NG_HistogramSettings.txt";
|
||||
|
||||
SetUpdateTimeInSec(1.0);
|
||||
|
||||
isSignalSlotActive = false;
|
||||
SetUpCanvas();
|
||||
|
||||
ClearInternalDataCount();
|
||||
};
|
||||
|
||||
~NeutronGamma(){
|
||||
// for( unsigned int i = 0; i < nDigi; i++ ){
|
||||
// for( int ch = 0; ch < digi[i]->GetNumInputCh(); ch++){
|
||||
// delete hist2D[i][ch];
|
||||
// }
|
||||
// }
|
||||
delete hist2D;
|
||||
}
|
||||
|
||||
void ClearInternalDataCount();
|
||||
|
||||
// void LoadSetting();
|
||||
// void SaveSetting();
|
||||
|
||||
public slots:
|
||||
void UpdateHistograms();
|
||||
|
||||
private:
|
||||
QVector<int> generateNonRepeatedCombination(int size);
|
||||
void SetUpCanvas();
|
||||
|
||||
Digitizer ** digi;
|
||||
unsigned short nDigi;
|
||||
|
||||
Histogram2D * hist2D;
|
||||
|
||||
RComboBox * cbDigi;
|
||||
RComboBox * cbCh;
|
||||
|
||||
QGroupBox * histBox;
|
||||
QGridLayout * histLayout;
|
||||
|
||||
int lastFilledIndex[MaxNDigitizer][MaxNChannels];
|
||||
int loopFilledIndex[MaxNDigitizer][MaxNChannels];
|
||||
|
||||
bool fillHistograms;
|
||||
|
||||
QString settingPath;
|
||||
|
||||
unsigned short maxFillTimeinMilliSec;
|
||||
unsigned short maxFillTimePerDigi;
|
||||
|
||||
bool isSignalSlotActive;
|
||||
|
||||
};
|
||||
|
||||
inline void NeutronGamma::SetUpCanvas(){
|
||||
|
||||
setWindowTitle("Neutron-Gamma Separation");
|
||||
|
||||
QScreen * screen = QGuiApplication::primaryScreen();
|
||||
QRect screenGeo = screen->geometry();
|
||||
if( screenGeo.width() < 1000 || screenGeo.height() < 800) {
|
||||
setGeometry(0, 0, screenGeo.width() - 100, screenGeo.height() - 100);
|
||||
}else{
|
||||
setGeometry(0, 0, 1000, 800);
|
||||
}
|
||||
|
||||
QWidget * layoutWidget = new QWidget(this);
|
||||
setCentralWidget(layoutWidget);
|
||||
QVBoxLayout * layout = new QVBoxLayout(layoutWidget);
|
||||
layoutWidget->setLayout(layout);
|
||||
|
||||
{//^==================================
|
||||
QGroupBox * controlBox = new QGroupBox("Control", this);
|
||||
layout->addWidget(controlBox);
|
||||
QGridLayout * ctrlLayout = new QGridLayout(controlBox);
|
||||
controlBox->setLayout(ctrlLayout);
|
||||
|
||||
|
||||
cbDigi = new RComboBox(this);
|
||||
for( unsigned int i = 0; i < nDigi; i++) cbDigi->addItem("Digi-" + QString::number( digi[i]->GetSerialNumber() ), i);
|
||||
ctrlLayout->addWidget(cbDigi, 0, 0, 1, 2);
|
||||
connect( cbDigi, &RComboBox::currentIndexChanged, this, [=](int index){
|
||||
isSignalSlotActive = false;
|
||||
cbCh->clear();
|
||||
for( int i = 0; i < digi[index]->GetNumInputCh(); i++) cbCh->addItem("ch-" + QString::number( i ), i);
|
||||
|
||||
hist2D->Clear();
|
||||
isSignalSlotActive = true;
|
||||
});
|
||||
|
||||
cbCh = new RComboBox(this);
|
||||
for( int i = 0; i < digi[0]->GetNumInputCh(); i++) cbCh->addItem("ch-" + QString::number( i ), i);
|
||||
ctrlLayout->addWidget(cbCh, 0, 2, 1, 2);
|
||||
// connect( cbCh, &RComboBox::currentIndexChanged, this, &SingleSpectra::ChangeHistView);
|
||||
connect( cbCh, &RComboBox::currentIndexChanged, this, [=](){
|
||||
hist2D->Clear();
|
||||
});
|
||||
|
||||
QCheckBox * chkIsFillHistogram = new QCheckBox("Fill Histograms", this);
|
||||
ctrlLayout->addWidget(chkIsFillHistogram, 0, 8);
|
||||
connect(chkIsFillHistogram, &QCheckBox::stateChanged, this, [=](int state){ fillHistograms = state;});
|
||||
chkIsFillHistogram->setChecked(false);
|
||||
fillHistograms = false;
|
||||
|
||||
QLabel * lbSettingPath = new QLabel( settingPath , this);
|
||||
ctrlLayout->addWidget(lbSettingPath, 1, 0, 1, 8);
|
||||
|
||||
}
|
||||
|
||||
{//^====================================
|
||||
|
||||
histBox = new QGroupBox("Histgrams", this);
|
||||
layout->addWidget(histBox, 10);
|
||||
histLayout = new QGridLayout(histBox);
|
||||
histBox->setLayout(histLayout);
|
||||
|
||||
double eMax = 50000;
|
||||
double eMin = 0;
|
||||
double nBin = 1000;
|
||||
|
||||
// for( unsigned int i = 0; i < MaxNDigitizer; i++){
|
||||
// if( i >= nDigi ) continue;
|
||||
// for( int j = 0; j < digi[i]->GetNumInputCh(); j++){
|
||||
// if( i < nDigi ) {
|
||||
// hist2D[i][j] = new Histogram2D("Digi-" + QString::number(digi[i]->GetSerialNumber()), "Long Energy [ch]", "Short Energy [ch]", nBin, eMin, eMax, nBin, eMin, eMax);
|
||||
// }else{
|
||||
// hist2D[i][j] = nullptr;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// histLayout->addWidget(hist2D[0][0], 0, 0);
|
||||
|
||||
hist2D = new Histogram2D("Neutron-Gamma", "Long Energy [ch]", "PSD = (l-s)/l", nBin, eMin, eMax, nBin, 0, 1);
|
||||
|
||||
histLayout->addWidget(hist2D, 0, 0);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
inline void NeutronGamma::ClearInternalDataCount(){
|
||||
for( unsigned int i = 0; i < nDigi; i++){
|
||||
for( int ch = 0; ch < MaxRegChannel ; ch++) {
|
||||
lastFilledIndex[i][ch] = -1;
|
||||
loopFilledIndex[i][ch] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline void NeutronGamma::UpdateHistograms(){
|
||||
if( !fillHistograms ) return;
|
||||
if( this->isVisible() == false ) return;
|
||||
|
||||
int ID = cbDigi->currentData().toInt();
|
||||
int ch = cbCh->currentData().toInt();
|
||||
|
||||
int lastIndex = digi[ID]->GetData()->GetDataIndex(ch);
|
||||
if( lastIndex < 0 ) return;
|
||||
|
||||
int loopIndex = digi[ID]->GetData()->GetLoopIndex(ch);
|
||||
|
||||
int temp1 = lastIndex + loopIndex * digi[ID]->GetData()->GetDataSize();
|
||||
int temp2 = lastFilledIndex[ID][ch] + loopFilledIndex[ID][ch] * digi[ID]->GetData()->GetDataSize() + 1;
|
||||
|
||||
if( temp1 - temp2 > digi[ID]->GetData()->GetDataSize() ) { //DefaultDataSize = 10k
|
||||
temp2 = temp1 - digi[ID]->GetData()->GetDataSize();
|
||||
lastFilledIndex[ID][ch] = lastIndex;
|
||||
lastFilledIndex[ID][ch] = loopIndex - 1;
|
||||
}
|
||||
|
||||
for( int j = 0 ; j <= temp1 - temp2; j ++){
|
||||
lastFilledIndex[ID][ch] ++;
|
||||
if( lastFilledIndex[ID][ch] > digi[ID]->GetData()->GetDataSize() ) {
|
||||
lastFilledIndex[ID][ch] = 0;
|
||||
loopFilledIndex[ID][ch] ++;
|
||||
}
|
||||
|
||||
uShort data_long = digi[ID]->GetData()->GetEnergy(ch, lastFilledIndex[ID][ch]);
|
||||
uShort data_short = digi[ID]->GetData()->GetEnergy2(ch, lastFilledIndex[ID][ch]);
|
||||
|
||||
// printf(" ch: %d, last fill idx : %d | %d \n", ch, lastFilledIndex[ID][ch], data);
|
||||
|
||||
double psd = (data_long - data_short) *1.0 / data_long;
|
||||
|
||||
hist2D->Fill(data_long, psd);
|
||||
}
|
||||
|
||||
hist2D->UpdatePlot();
|
||||
|
||||
}
|
||||
|
||||
inline QVector<int> NeutronGamma::generateNonRepeatedCombination(int size) {
|
||||
QVector<int> combination;
|
||||
for (int i = 0; i < size; ++i) combination.append(i);
|
||||
|
||||
for (int i = 0; i < size - 1; ++i) {
|
||||
int j = QRandomGenerator::global()->bounded(i, size);
|
||||
combination.swapItemsAt(i, j);
|
||||
}
|
||||
return combination;
|
||||
}
|
||||
|
||||
#endif
|
|
@ -27,9 +27,7 @@ public:
|
|||
evtbder = GetEventBuilder();
|
||||
evtbder->SetTimeWindow(500);
|
||||
|
||||
//========== use the influx from the Analyzer
|
||||
influx = new InfluxDB("https://fsunuc.physics.fsu.edu/influx/");
|
||||
dataBaseName = "testing";
|
||||
SetDatabase("https://localhost:8086", "testing", "zKhzKk4Yhf1l9QU-yE2GsIZ1RazqUgoW3NlF8LJqq_xDMwatOJwg1sKrjgq36uLEsQf8Fmn4sJALP7Kkilk14A==");
|
||||
|
||||
SetUpCanvas(); // see below
|
||||
|
||||
|
|
134
analyzers/RAISOR.h
Normal file
134
analyzers/RAISOR.h
Normal file
|
@ -0,0 +1,134 @@
|
|||
#ifndef RASIOR_h
|
||||
#define RASIOR_h
|
||||
|
||||
/*********************************************
|
||||
* This is online analyzer for RASIOR, ANL
|
||||
*
|
||||
* Created by Ryan @ 2023-10-16
|
||||
*
|
||||
* ******************************************/
|
||||
#include "Analyser.h"
|
||||
|
||||
|
||||
class RAISOR : public Analyzer{
|
||||
|
||||
public:
|
||||
RAISOR(Digitizer ** digi, unsigned int nDigi, QMainWindow * parent = nullptr): Analyzer(digi, nDigi, parent){
|
||||
|
||||
|
||||
SetUpdateTimeInSec(1.0);
|
||||
|
||||
RedefineEventBuilder({0}); // only builder for the 0-th digitizer.
|
||||
tick2ns = digi[0]->GetTick2ns();
|
||||
|
||||
SetBackwardBuild(false, 100); // using normal building (acceding in time) or backward building, int the case of backward building, default events to be build is 100.
|
||||
evtbder = GetEventBuilder();
|
||||
evtbder->SetTimeWindow(500);
|
||||
|
||||
//========== use the influx from the Analyzer
|
||||
influx = new InfluxDB("https://fsunuc.physics.fsu.edu/influx/");
|
||||
dataBaseName = "testing";
|
||||
|
||||
SetUpCanvas(); // see below
|
||||
|
||||
};
|
||||
|
||||
void SetUpCanvas();
|
||||
|
||||
public slots:
|
||||
void UpdateHistograms();
|
||||
|
||||
|
||||
private:
|
||||
|
||||
MultiBuilder *evtbder;
|
||||
|
||||
Histogram2D * hPID;
|
||||
|
||||
int tick2ns;
|
||||
|
||||
float dE, E;
|
||||
unsigned long long dE_t, E_t;
|
||||
|
||||
};
|
||||
|
||||
|
||||
inline void RAISOR::SetUpCanvas(){
|
||||
|
||||
setGeometry(0, 0, 500, 500);
|
||||
|
||||
//============ histograms
|
||||
hPID = new Histogram2D("RAISOR", "E", "dE", 100, 0, 5000, 100, 0, 20000, this);
|
||||
layout->addWidget(hPID, 0, 0);
|
||||
|
||||
}
|
||||
|
||||
inline void RAISOR::UpdateHistograms(){
|
||||
|
||||
if( this->isVisible() == false ) return;
|
||||
|
||||
BuildEvents(false); // call the event builder to build events
|
||||
|
||||
//============ Get events, and do analysis
|
||||
long eventBuilt = evtbder->eventBuilt;
|
||||
if( eventBuilt == 0 ) return;
|
||||
|
||||
//============ Get the cut list, if any
|
||||
QList<QPolygonF> cutList = hPID->GetCutList();
|
||||
const int nCut = cutList.count();
|
||||
unsigned long long tMin[nCut] = {0xFFFFFFFFFFFFFFFF}, tMax[nCut] = {0};
|
||||
unsigned int count[nCut]={0};
|
||||
|
||||
//============ Processing data and fill histograms
|
||||
long eventIndex = evtbder->eventIndex;
|
||||
long eventStart = eventIndex - eventBuilt + 1;
|
||||
if(eventStart < 0 ) eventStart += MaxNEvent;
|
||||
|
||||
for( long i = eventStart ; i <= eventIndex; i ++ ){
|
||||
std::vector<Hit> event = evtbder->events[i];
|
||||
//printf("-------------- %ld\n", i);
|
||||
|
||||
if( event.size() == 0 ) return;
|
||||
|
||||
for( int k = 0; k < (int) event.size(); k++ ){
|
||||
//event[k].Print();
|
||||
if( event[k].ch == 0 ) {dE = event[k].energy; dE_t = event[k].timestamp;}
|
||||
if( event[k].ch == 1 ) {E = event[k].energy; E_t = event[k].timestamp;}
|
||||
|
||||
}
|
||||
|
||||
// printf("(E, dE) = (%f, %f)\n", E, dE);
|
||||
hPID->Fill(E + RandomGauss(0, 100), dE+ RandomGauss(0, 100)); // x, y
|
||||
|
||||
//check events inside any Graphical cut and extract the rate
|
||||
for(int p = 0; p < cutList.count(); p++ ){
|
||||
if( cutList[p].isEmpty() ) continue;
|
||||
if( cutList[p].containsPoint(QPointF(E, dE), Qt::OddEvenFill) ){
|
||||
if( dE_t < tMin[p] ) tMin[p] = dE_t;
|
||||
if( dE_t > tMax[p] ) tMax[p] = dE_t;
|
||||
count[p] ++;
|
||||
//printf(".... %d \n", count[p]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hPID->UpdatePlot();
|
||||
|
||||
//========== output to Influx
|
||||
QList<QString> cutNameList = hPID->GetCutNameList();
|
||||
for( int p = 0; p < cutList.count(); p ++){
|
||||
if( cutList[p].isEmpty() ) continue;
|
||||
double dT = (tMax[p]-tMin[p]) * tick2ns / 1e9; // tick to sec
|
||||
double rate = count[p]*1.0/(dT);
|
||||
//printf("%llu %llu, %f %d\n", tMin[p], tMax[p], dT, count[p]);
|
||||
//printf("%10s | %d | %f Hz \n", cutNameList[p].toStdString().c_str(), count[p], rate);
|
||||
|
||||
influx->AddDataPoint("Cut,name=" + cutNameList[p].toStdString()+ " value=" + std::to_string(rate));
|
||||
influx->WriteData(dataBaseName.toStdString());
|
||||
influx->ClearDataPointsBuffer();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
|
@ -25,9 +25,7 @@ public:
|
|||
evtbder = GetEventBuilder();
|
||||
evtbder->SetTimeWindow(500);
|
||||
|
||||
//========== use the influx from the Analyzer
|
||||
influx = new InfluxDB("https://fsunuc.physics.fsu.edu/influx/");
|
||||
dataBaseName = "testing";
|
||||
SetDatabase("https://localhost:8086", "testing", "zKhzKk4Yhf1l9QU-yE2GsIZ1RazqUgoW3NlF8LJqq_xDMwatOJwg1sKrjgq36uLEsQf8Fmn4sJALP7Kkilk14A==");
|
||||
|
||||
SetUpCanvas(); // see below
|
||||
|
||||
|
@ -261,7 +259,7 @@ inline void RAISOR1::UpdateHistograms(){
|
|||
//printf("%10s | %d | %f Hz \n", cutNameList[p].toStdString().c_str(), count[p], rate);
|
||||
|
||||
influx->AddDataPoint("Cut,name=" + cutNameList[p].toStdString()+ " value=" + std::to_string(rate));
|
||||
influx->WriteData(dataBaseName);
|
||||
influx->WriteData(dataBaseName.toStdString());
|
||||
influx->ClearDataPointsBuffer();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,8 +26,7 @@ public:
|
|||
evtbder->SetTimeWindow(500);
|
||||
|
||||
//========== use the influx from the Analyzer
|
||||
influx = new InfluxDB("https://fsunuc.physics.fsu.edu/influx/");
|
||||
dataBaseName = "testing";
|
||||
SetDatabase("https://localhost:8086", "testing", "zKhzKk4Yhf1l9QU-yE2GsIZ1RazqUgoW3NlF8LJqq_xDMwatOJwg1sKrjgq36uLEsQf8Fmn4sJALP7Kkilk14A==");
|
||||
|
||||
SetUpCanvas(); // see below
|
||||
|
||||
|
@ -289,7 +288,7 @@ inline void RAISOR2::UpdateHistograms(){
|
|||
//printf("%10s | %d | %f Hz \n", cutNameList[p].toStdString().c_str(), count[p], rate);
|
||||
|
||||
influx->AddDataPoint("Cut,name=" + cutNameList[p].toStdString()+ " value=" + std::to_string(rate));
|
||||
influx->WriteData(dataBaseName);
|
||||
influx->WriteData(dataBaseName.toStdString());
|
||||
influx->ClearDataPointsBuffer();
|
||||
}
|
||||
}
|
||||
|
|
93
analyzers/README.md
Normal file
93
analyzers/README.md
Normal file
|
@ -0,0 +1,93 @@
|
|||
# Introduction
|
||||
|
||||
This folder stored all online analyzers. The Analyser.cpp/h is the base class for all analyzer.
|
||||
|
||||
The Analyzer.cpp/h has the MultiBuilder (to handle event building) and InfluxDB (to handle pushing data to influxDB database) classes. In Addision, it has a QThread, a AnalyzerWorker, and a QTimer, these three object handle the threading of UpdateHistograms().
|
||||
|
||||
The AnalyzerWorker moves to the QThread. QTimer::timeout will trigger AnalyzerWorker::UpdateHistograms().
|
||||
|
||||
There is an important bool 'isWorking'. This boolean variable is true when AnalyzerWorker::UpdateHistograms() is running, and it is false when finsihed. This prevent UpdateHistograms() runs twice at the same time.
|
||||
|
||||
There are two virual methods
|
||||
- SetupCanvas()
|
||||
- UpdateHistograms()
|
||||
|
||||
Users must implement these two methods in theie custom analyzer.
|
||||
|
||||
|
||||
# Intruction to make new Analyzer
|
||||
|
||||
The CoindientAnalyzer.h is a good example.
|
||||
|
||||
1. inheirate the Analyzer class
|
||||
```cpp
|
||||
class CustomAnalyzer : public Analyzer{
|
||||
Q_OBJECT
|
||||
public:
|
||||
CustomAnalyzer(Digitizer ** digi, unsigned int nDigi, QMainWindow * parent = nullptr): Analyzer(digi, nDigi, parent){
|
||||
SetUpdateTimeInSec(1.0); // set histogram update period in sec
|
||||
mb->SetTimeWindow(500); // set the event time windows
|
||||
// ... other custom stuffs
|
||||
}
|
||||
|
||||
void SetUpCanvas();
|
||||
public slots:
|
||||
void UpdateHistograms();
|
||||
|
||||
private:
|
||||
|
||||
Histogram2D * h2D;
|
||||
Histogram1D * h1D;
|
||||
// some priavte variables
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
2. implement the SetUpCanvas() method
|
||||
```cpp
|
||||
inline void CustomAnalyzer::SetUpCanvas(){
|
||||
setWindowTitle("Title");
|
||||
setGeometry(0, 0, 1600, 1000);
|
||||
|
||||
h2D = new Histogram2D("Coincident Plot", "XXX", "YYY", 200, 0, 30000, 200, 0, 30000, this, rawDataPath);
|
||||
|
||||
//layout is inheriatge from Analyzer
|
||||
layout->addWidget(h2D, 0, 0); // row-0, col-0
|
||||
|
||||
h1 = new Histogram1D("1D Plot", "XXX", 300, 0, 30000, this);
|
||||
h1->SetColor(Qt::darkGreen);
|
||||
layout->addWidget(h1, 0, 1); // row-0, col-1
|
||||
|
||||
//other GUI elements
|
||||
}
|
||||
```
|
||||
|
||||
3. implement the UpdateHistograms() method
|
||||
```cpp
|
||||
inline void CustomAnalyzer::UpdateHistograms(){
|
||||
// don't update histogram when the windows not visible
|
||||
if( this->isVisible() == false ) return;
|
||||
|
||||
BuildEvents(false); // call the event builder to build events, no verbose
|
||||
|
||||
//check number of event built
|
||||
long eventBuilt = mb->eventBuilt;
|
||||
if( eventBuilt == 0 ) return;
|
||||
|
||||
//============ Processing data and fill histograms
|
||||
long eventIndex = mb->eventIndex;
|
||||
long eventStart = eventIndex - eventBuilt + 1;
|
||||
if(eventStart < 0 ) eventStart += MaxNEvent;
|
||||
|
||||
for( long i = eventStart ; i <= eventIndex; i ++ ){
|
||||
std::vector<Hit> event = mb->events[i];
|
||||
|
||||
//analysis and fill historgam
|
||||
}
|
||||
|
||||
//Render histograms
|
||||
h2D->UpdatePlot();
|
||||
h1D->UpdatePlot();
|
||||
|
||||
}
|
||||
```
|
|
@ -30,8 +30,7 @@ public:
|
|||
RedefineEventBuilder({0}); // only build for the 0-th digitizer, otherwise, it will build event accross all digitizers
|
||||
tick2ns = digi[0]->GetTick2ns();
|
||||
SetBackwardBuild(false, 100); // using normal building (acceding in time) or backward building, int the case of backward building, default events to be build is 100.
|
||||
evtbder = GetEventBuilder();
|
||||
evtbder->SetTimeWindow(500);
|
||||
mb->SetTimeWindow(3000);
|
||||
|
||||
//========== use the influx from the Analyzer
|
||||
influx = new InfluxDB("https://fsunuc.physics.fsu.edu/influx/");
|
||||
|
@ -41,7 +40,7 @@ public:
|
|||
leTarget->setText("12C");
|
||||
leBeam->setText("d");
|
||||
leRecoil->setText("p");
|
||||
sbBfield->setValue(0.76);
|
||||
sbBfield->setValue(0.75);
|
||||
sbAngle->setValue(20);
|
||||
sbEnergy->setValue(16);
|
||||
|
||||
|
@ -67,8 +66,6 @@ public slots:
|
|||
|
||||
private:
|
||||
|
||||
MultiBuilder *evtbder;
|
||||
|
||||
// declaie histograms
|
||||
Histogram2D * hPID;
|
||||
|
||||
|
@ -87,6 +84,7 @@ private:
|
|||
RSpinBox * sbEnergy;
|
||||
RSpinBox * sbAngle;
|
||||
|
||||
RSpinBox * sbEventWin;
|
||||
QCheckBox * chkRunAnalyzer;
|
||||
|
||||
QLineEdit * leMassTablePath;
|
||||
|
@ -212,9 +210,33 @@ inline void SplitPole::SetUpCanvas(){
|
|||
FillConstants();
|
||||
});
|
||||
|
||||
chkRunAnalyzer = new QCheckBox("Run Analyzer", this);
|
||||
boxLayout->addWidget(chkRunAnalyzer, 4, 1);
|
||||
|
||||
QLabel * lbEventWindow = new QLabel("Event Window [ns] ", box);
|
||||
lbEventWindow->setAlignment(Qt::AlignRight | Qt::AlignCenter);
|
||||
boxLayout->addWidget(lbEventWindow, 4, 0);
|
||||
sbEventWin = new RSpinBox(this);
|
||||
sbEventWin->setDecimals(0);
|
||||
sbEventWin->setSingleStep(100);
|
||||
sbEventWin->setMaximum(1000000);
|
||||
boxLayout->addWidget(sbEventWin, 4, 1);
|
||||
sbEventWin->setValue(3000);
|
||||
connect(sbEventWin, &RSpinBox::returnPressed, this, [=](){
|
||||
mb->SetTimeWindow(sbEventWin->value());
|
||||
});
|
||||
|
||||
chkRunAnalyzer = new QCheckBox("Run Analyzer", this);
|
||||
boxLayout->addWidget(chkRunAnalyzer, 4, 3);
|
||||
connect(chkRunAnalyzer, &QCheckBox::stateChanged, this, [=](int state){
|
||||
|
||||
sbBfield->setEnabled(state != Qt::Checked);
|
||||
leTarget->setEnabled(state != Qt::Checked);
|
||||
leBeam->setEnabled(state != Qt::Checked);
|
||||
leRecoil->setEnabled(state != Qt::Checked);
|
||||
sbEnergy->setEnabled(state != Qt::Checked);
|
||||
sbAngle->setEnabled(state != Qt::Checked);
|
||||
sbEventWin->setEnabled(state != Qt::Checked);
|
||||
|
||||
});
|
||||
|
||||
QFrame *separator = new QFrame(box);
|
||||
separator->setFrameShape(QFrame::HLine);
|
||||
|
@ -298,20 +320,20 @@ inline void SplitPole::SetUpCanvas(){
|
|||
}
|
||||
|
||||
//============ histograms
|
||||
hMulti = new Histogram1D("Multiplicity", "", 10, 0, 10, this);
|
||||
hMulti = new Histogram1D("Multiplicity", "", 16, 0, 16, this);
|
||||
layout->addWidget(hMulti, 0, 1);
|
||||
|
||||
// the "this" make the histogram a child of the SplitPole class. When SplitPole destory, all childs destory as well.
|
||||
hPID = new Histogram2D("Split Pole PID", "Scin-L", "Anode-Font", 100, 0, 5000, 100, 0, 5000, this);
|
||||
hPID = new Histogram2D("Split Pole PID", "Scin-L", "Anode-Back", 100, 0, 20000, 100, 0, 40000, this);
|
||||
//layout is inheriatge from Analyzer
|
||||
layout->addWidget(hPID, 1, 0, 2, 1);
|
||||
|
||||
h1 = new Histogram1D("Spectrum", "x", 300, 30, 70, this);
|
||||
h1 = new Histogram1D("Spectrum", "x1", 300, -200, 200, this);
|
||||
h1->SetColor(Qt::darkGreen);
|
||||
//h1->AddDataList("Test", Qt::red); // add another histogram in h1, Max Data List is 10
|
||||
layout->addWidget(h1, 1, 1);
|
||||
|
||||
h1g = new Histogram1D("Spectrum (PID gated)", "Ex", 300, -2, 10, this);
|
||||
h1g = new Histogram1D("Spectrum (PID gated)", "x1", 300, -200, 200, this);
|
||||
layout->addWidget(h1g, 2, 1);
|
||||
|
||||
layout->setColumnStretch(0, 1);
|
||||
|
@ -327,7 +349,7 @@ inline void SplitPole::UpdateHistograms(){
|
|||
BuildEvents(); // call the event builder to build events
|
||||
|
||||
//============ Get events, and do analysis
|
||||
long eventBuilt = evtbder->eventBuilt;
|
||||
long eventBuilt = mb->eventBuilt;
|
||||
if( eventBuilt == 0 ) return;
|
||||
|
||||
//============ Get the cut list, if any
|
||||
|
@ -337,12 +359,12 @@ inline void SplitPole::UpdateHistograms(){
|
|||
unsigned int count[nCut]={0};
|
||||
|
||||
//============ Processing data and fill histograms
|
||||
long eventIndex = evtbder->eventIndex;
|
||||
long eventIndex = mb->eventIndex;
|
||||
long eventStart = eventIndex - eventBuilt + 1;
|
||||
if(eventStart < 0 ) eventStart += MaxNEvent;
|
||||
|
||||
for( long i = eventStart ; i <= eventIndex; i ++ ){
|
||||
std::vector<Hit> event = evtbder->events[i];
|
||||
std::vector<Hit> event = mb->events[i];
|
||||
//printf("-------------- %ld\n", i);
|
||||
|
||||
hMulti->Fill((int) event.size());
|
||||
|
@ -353,28 +375,32 @@ inline void SplitPole::UpdateHistograms(){
|
|||
|
||||
for( int k = 0; k < (int) event.size(); k++ ){
|
||||
//event[k].Print();
|
||||
if( event[k].ch == SPS::ChMap::ScinR ) {hit.eSR = event[k].energy; hit.tSR = event[k].timestamp;}
|
||||
if( event[k].ch == SPS::ChMap::ScinL ) {hit.eSL = event[k].energy; hit.tSL = event[k].timestamp;}
|
||||
if( event[k].ch == SPS::ChMap::dFR ) {hit.eFR = event[k].energy; hit.tFR = event[k].timestamp;}
|
||||
if( event[k].ch == SPS::ChMap::dFL ) {hit.eFL = event[k].energy; hit.tFL = event[k].timestamp;}
|
||||
if( event[k].ch == SPS::ChMap::dBR ) {hit.eBL = event[k].energy; hit.tBL = event[k].timestamp;}
|
||||
if( event[k].ch == SPS::ChMap::dBL ) {hit.eBL = event[k].energy; hit.tBL = event[k].timestamp;}
|
||||
if( event[k].ch == SPS::ChMap::Cathode ) {hit.eCath = event[k].energy; hit.tCath = event[k].timestamp;}
|
||||
if( event[k].ch == SPS::ChMap::AnodeF ) {hit.eAF = event[k].energy; hit.tAF = event[k].timestamp;}
|
||||
if( event[k].ch == SPS::ChMap::AnodeB ) {hit.eAB = event[k].energy; hit.tAB = event[k].timestamp;}
|
||||
if( event[k].ch == SPS::ChMap::ScinR ) {hit.eSR = event[k].energy; hit.tSR = event[k].timestamp + event[k].fineTime/1000.;}
|
||||
if( event[k].ch == SPS::ChMap::ScinL ) {hit.eSL = event[k].energy; hit.tSL = event[k].timestamp + event[k].fineTime/1000.;}
|
||||
if( event[k].ch == SPS::ChMap::dFR ) {hit.eFR = event[k].energy; hit.tFR = event[k].timestamp + event[k].fineTime/1000.;}
|
||||
if( event[k].ch == SPS::ChMap::dFL ) {hit.eFL = event[k].energy; hit.tFL = event[k].timestamp + event[k].fineTime/1000.;}
|
||||
if( event[k].ch == SPS::ChMap::dBR ) {hit.eBL = event[k].energy; hit.tBL = event[k].timestamp + event[k].fineTime/1000.;}
|
||||
if( event[k].ch == SPS::ChMap::dBL ) {hit.eBL = event[k].energy; hit.tBL = event[k].timestamp + event[k].fineTime/1000.;}
|
||||
if( event[k].ch == SPS::ChMap::Cathode ) {hit.eCath = event[k].energy; hit.tCath = event[k].timestamp + event[k].fineTime/1000.;}
|
||||
if( event[k].ch == SPS::ChMap::AnodeF ) {hit.eAF = event[k].energy; hit.tAF = event[k].timestamp + event[k].fineTime/1000.;}
|
||||
if( event[k].ch == SPS::ChMap::AnodeB ) {hit.eAB = event[k].energy; hit.tAB = event[k].timestamp + event[k].fineTime/1000.;}
|
||||
}
|
||||
|
||||
hit.CalData();
|
||||
|
||||
double pidX = hit.eSL;
|
||||
unsigned long long tPidX = hit.tSL;
|
||||
double pidY = hit.eAF;
|
||||
double pidY = hit.eAB;
|
||||
|
||||
hPID->Fill(pidX, pidY); // x, y
|
||||
|
||||
h1->Fill(hit.xAvg);
|
||||
if( pidX > 0 && pidY > 0 ){
|
||||
hPID->Fill(pidX, pidY); // x, y
|
||||
}
|
||||
if( !std::isnan(hit.x1) ) {
|
||||
h1->Fill(hit.x1);
|
||||
}
|
||||
//h1->Fill(hit.eSR, 1);
|
||||
|
||||
|
||||
//check events inside any Graphical cut and extract the rate, using tSR only
|
||||
for(int p = 0; p < cutList.count(); p++ ){
|
||||
if( cutList[p].isEmpty() ) continue;
|
||||
|
@ -383,10 +409,13 @@ inline void SplitPole::UpdateHistograms(){
|
|||
if( tPidX > tMax[p] ) tMax[p] = tPidX;
|
||||
count[p] ++;
|
||||
//printf(".... %d \n", count[p]);
|
||||
if( p == 0 ) {
|
||||
double xAvg = hit.xAvg * 10;
|
||||
double xAvgC = xAvg * sbRhoScale->value() + sbRhoOffset->value();
|
||||
h1g->Fill(hit.Rho2Ex(xAvgC/1000.));
|
||||
// if( p == 0 ) {
|
||||
// double xAvg = hit.xAvg * 10;
|
||||
// double xAvgC = xAvg * sbRhoScale->value() + sbRhoOffset->value();
|
||||
// h1g->Fill(hit.Rho2Ex(xAvgC/1000.));
|
||||
// }
|
||||
if( p == 0 ){
|
||||
h1g->Fill(hit.x1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -406,7 +435,7 @@ inline void SplitPole::UpdateHistograms(){
|
|||
//printf("%10s | %d | %f Hz \n", cutNameList[p].toStdString().c_str(), count[p], rate);
|
||||
|
||||
influx->AddDataPoint("Cut,name=" + cutNameList[p].toStdString()+ " value=" + std::to_string(rate));
|
||||
influx->WriteData(dataBaseName);
|
||||
influx->WriteData(dataBaseName.toStdString());
|
||||
influx->ClearDataPointsBuffer();
|
||||
}
|
||||
|
||||
|
|
|
@ -39,8 +39,8 @@ namespace SPS{
|
|||
const short ScinL = 1;
|
||||
const short dFR = 9;
|
||||
const short dFL = 8;
|
||||
const short dBR = 10;
|
||||
const short dBL = 11;
|
||||
const short dBR = 11;
|
||||
const short dBL = 10;
|
||||
const short Cathode = 7;
|
||||
const short AnodeF = 13;
|
||||
const short AnodeB = 15;
|
||||
|
@ -64,19 +64,19 @@ public:
|
|||
ClearData();
|
||||
}
|
||||
|
||||
unsigned int eSR; unsigned long long tSR;
|
||||
unsigned int eSL; unsigned long long tSL;
|
||||
unsigned int eFR; unsigned long long tFR;
|
||||
unsigned int eFL; unsigned long long tFL;
|
||||
unsigned int eBR; unsigned long long tBR;
|
||||
unsigned int eBL; unsigned long long tBL;
|
||||
unsigned int eSR; unsigned long long tSR;
|
||||
unsigned int eSL; unsigned long long tSL;
|
||||
unsigned int eFR; unsigned long long tFR;
|
||||
unsigned int eFL; unsigned long long tFL;
|
||||
unsigned int eBR; unsigned long long tBR;
|
||||
unsigned int eBL; unsigned long long tBL;
|
||||
unsigned int eCath; unsigned long long tCath;
|
||||
unsigned int eAF; unsigned long long tAF;
|
||||
unsigned int eAB; unsigned long long tAB;
|
||||
unsigned int eAF; unsigned long long tAF;
|
||||
unsigned int eAB; unsigned long long tAB;
|
||||
|
||||
float eSAvg;
|
||||
float x1, x2, theta;
|
||||
float xAvg;
|
||||
double xAvg;
|
||||
|
||||
double GetQ0() const {return Q0;}
|
||||
double GetRho0() const {return rho0;}
|
||||
|
@ -194,14 +194,22 @@ public:
|
|||
isConstantCal = false;
|
||||
}
|
||||
|
||||
void CalData(){
|
||||
void CalData(float scale = 2.){
|
||||
|
||||
if( eSR > 0 && eSL > 0 ) eSAvg = (eSR + eSL)/2;
|
||||
if( eSR > 0 && eSL == 0 ) eSAvg = eSR;
|
||||
if( eSR == 0 && eSL > 0 ) eSAvg = eSL;
|
||||
|
||||
if( tFR > 0 && tFL > 0 ) x1 = (tFL - tFR)/2./2.1;
|
||||
if( tBR > 0 && tBL > 0 ) x2 = (tBL - tBR)/2./1.98;
|
||||
if( tFR > 0 && tFL > 0 ) {
|
||||
if( tFL > tFR) x1 = (tFL - tFR)/scale/2.1;
|
||||
if( tFL < tFR) x1 = (tFR - tFL)/scale/-2.1;
|
||||
}
|
||||
if( tBR > 0 && tBL > 0 ) {
|
||||
if( tBL > tBR) x2 = (tBL - tBR)/scale/1.98;
|
||||
if( tBR > tBL) x2 = (tBR - tBL)/scale/-1.98;
|
||||
}
|
||||
|
||||
// printf("x1: %f, x2 : %f \n", x1, x2);
|
||||
|
||||
if( !std::isnan(x1) && !std::isnan(x2)) {
|
||||
|
||||
|
|
|
@ -25,9 +25,7 @@ public:
|
|||
evtbder = GetEventBuilder();
|
||||
evtbder->SetTimeWindow(500);
|
||||
|
||||
//========== use the influx from the Analyzer
|
||||
influx = new InfluxDB("https://fsunuc.physics.fsu.edu/influx/");
|
||||
dataBaseName = "testing";
|
||||
SetDatabase("https://localhost:8086", "testing", "zKhzKk4Yhf1l9QU-yE2GsIZ1RazqUgoW3NlF8LJqq_xDMwatOJwg1sKrjgq36uLEsQf8Fmn4sJALP7Kkilk14A==");
|
||||
|
||||
SetUpCanvas(); // see below
|
||||
|
||||
|
@ -183,7 +181,7 @@ inline void TEST::UpdateHistograms(){
|
|||
|
||||
for( int k = 0; k < (int) event.size(); k++ ){
|
||||
//event[k].Print();
|
||||
if( event[k].ch == 8 ) {dE = event[k].energy; dE_t = event[k].timestamp;} // Surface Barrier dE detector
|
||||
if( event[k].ch == 8 ) {dE = event[k].energy; dE_t = event[k].timestamp;} // Surface Barrier dE detector
|
||||
if( event[k].ch == 8 ) {E = event[k].energy; E_t = event[k].timestamp;} // Surface Barrier E detector
|
||||
|
||||
if( event[k].ch == 8 ) {e0 = event[k].energy; t0 = event[k].timestamp;} //
|
||||
|
@ -199,20 +197,20 @@ inline void TEST::UpdateHistograms(){
|
|||
hPID->Fill(E + RandomGauss(0, 100), dE + RandomGauss(0, 100)); // x, y
|
||||
//hXX->Fill(e1 + RandomGauss(0, 100), e0 + RandomGauss(0, 100)); //
|
||||
hXX->Fill(e1, e0 ); //
|
||||
hYY->Fill(e3 + RandomGauss(0, 100), e2 + RandomGauss(0, 100));
|
||||
hXY->Fill(((e0-e1)/(e0+e1)) + RandomGauss(0, 100),((e2-e3)/(e2+e3)) + RandomGauss(0, 100));
|
||||
hXE->Fill(e0+e1);
|
||||
hYE->Fill(e2+e3);
|
||||
hX->Fill(((e0-e1)/(e0+e1)));
|
||||
hY->Fill(((e2-e3)/(e2+e3)));
|
||||
hXPE->Fill(((e0-e1)/(e0+e1)) + RandomGauss(0, 100),(e0+e1) + RandomGauss(0, 100));
|
||||
hYPE->Fill(((e2-e3)/(e2+e3)) + RandomGauss(0, 100),(e2+e3) + RandomGauss(0, 100));
|
||||
hXEdE1->Fill((e0+e1)+ RandomGauss(0, 100),dE1 + RandomGauss(0, 100));
|
||||
hYEdE1->Fill((e2+e3) + RandomGauss(0, 100),dE1 + RandomGauss(0, 100));
|
||||
hXEdE2->Fill((e0+e1)+ RandomGauss(0, 100),dE2 + RandomGauss(0, 100));
|
||||
hYEdE2->Fill((e2+e3)+ RandomGauss(0, 100),dE2 + + RandomGauss(0, 100));
|
||||
hXYE->Fill((e0+e1) + RandomGauss(0, 100),(e2+e3) + RandomGauss(0, 100));
|
||||
|
||||
hYY->Fill(e3 + RandomGauss(0, 100), e2 + RandomGauss(0, 100));
|
||||
hXY->Fill(((e0-e1)/(e0+e1)) + RandomGauss(0, 100),((e2-e3)/(e2+e3)) + RandomGauss(0, 100));
|
||||
hXE->Fill(e0+e1);
|
||||
hYE->Fill(e2+e3);
|
||||
hX->Fill(((e0-e1)/(e0+e1)));
|
||||
hY->Fill(((e2-e3)/(e2+e3)));
|
||||
hXPE->Fill(((e0-e1)/(e0+e1)) + RandomGauss(0, 100),(e0+e1) + RandomGauss(0, 100));
|
||||
hYPE->Fill(((e2-e3)/(e2+e3)) + RandomGauss(0, 100),(e2+e3) + RandomGauss(0, 100));
|
||||
hXEdE1->Fill((e0+e1)+ RandomGauss(0, 100),dE1 + RandomGauss(0, 100));
|
||||
hYEdE1->Fill((e2+e3) + RandomGauss(0, 100),dE1 + RandomGauss(0, 100));
|
||||
hXEdE2->Fill((e0+e1)+ RandomGauss(0, 100),dE2 + RandomGauss(0, 100));
|
||||
hYEdE2->Fill((e2+e3)+ RandomGauss(0, 100),dE2 + + RandomGauss(0, 100));
|
||||
hXYE->Fill((e0+e1) + RandomGauss(0, 100),(e2+e3) + RandomGauss(0, 100));
|
||||
|
||||
//check events inside any Graphical cut and extract the rate
|
||||
for(int p = 0; p < cutList.count(); p++ ){
|
||||
if( cutList[p].isEmpty() ) continue;
|
||||
|
@ -264,7 +262,7 @@ inline void TEST::UpdateHistograms(){
|
|||
//printf("%10s | %d | %f Hz \n", cutNameList[p].toStdString().c_str(), count[p], rate);
|
||||
|
||||
influx->AddDataPoint("Cut,name=" + cutNameList[p].toStdString()+ " value=" + std::to_string(rate));
|
||||
influx->WriteData(dataBaseName);
|
||||
influx->WriteData(dataBaseName.toStdString());
|
||||
influx->ClearDataPointsBuffer();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -27,9 +27,7 @@ public:
|
|||
evtbder = GetEventBuilder();
|
||||
evtbder->SetTimeWindow(500);
|
||||
|
||||
//========== use the influx from the Analyzer
|
||||
influx = new InfluxDB("https://fsunuc.physics.fsu.edu/influx/");
|
||||
dataBaseName = "testing";
|
||||
SetDatabase("https://localhost:8086", "testing", "zKhzKk4Yhf1l9QU-yE2GsIZ1RazqUgoW3NlF8LJqq_xDMwatOJwg1sKrjgq36uLEsQf8Fmn4sJALP7Kkilk14A==");
|
||||
|
||||
SetUpCanvas(); // see below
|
||||
|
||||
|
|
2
macro.h
2
macro.h
|
@ -11,6 +11,8 @@
|
|||
#define MaxRecordLength 0x3fff * 8
|
||||
#define MaxSaveFileSize 1024 * 1024 * 1024 * 2
|
||||
|
||||
#define ScalarUpdateinMiliSec 1000 // msec
|
||||
|
||||
#define MaxDisplayTraceTimeLength 20000 //ns
|
||||
#define ScopeUpdateMiliSec 200 // msec
|
||||
#define MaxNumberOfTrace 5 // in an event
|
||||
|
|
27
main.cpp
27
main.cpp
|
@ -3,6 +3,7 @@
|
|||
#include <QProcess>
|
||||
#include <QPushButton>
|
||||
#include <QFile>
|
||||
#include <QLocale>
|
||||
|
||||
#include "FSUDAQ.h"
|
||||
|
||||
|
@ -11,24 +12,28 @@
|
|||
|
||||
#include <sys/resource.h>
|
||||
|
||||
// class CustomApplication : public QApplication{
|
||||
// public:
|
||||
// CustomApplication(int &argc, char **argv) : QApplication(argc, argv) {}
|
||||
#include <csignal>
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
|
||||
// protected:
|
||||
// bool notify(QObject *receiver, QEvent *event) override{
|
||||
// qDebug() << event->type() << "Receiver:" << receiver;
|
||||
// return QApplication::notify(receiver, event);
|
||||
// }
|
||||
// };
|
||||
void abortHandler(int signal) {
|
||||
std::cerr << "Signal received: " << signal << ", aborting..." << std::endl;
|
||||
std::abort(); // Calls abort to generate core dump
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]){
|
||||
|
||||
std::signal(SIGSEGV, abortHandler);
|
||||
|
||||
setpriority(PRIO_PROCESS, 0, -20);
|
||||
|
||||
// CustomApplication a(argc, argv);
|
||||
QApplication a(argc, argv);
|
||||
|
||||
setpriority(PRIO_PROCESS, 0, -20);
|
||||
// Set Locale
|
||||
QLocale::setDefault(QLocale::system());
|
||||
|
||||
// Set Lock file
|
||||
bool isLock = false;
|
||||
int pid = 0;
|
||||
QFile lockFile(DAQLockFile);
|
||||
|
@ -70,7 +75,7 @@ int main(int argc, char *argv[]){
|
|||
pidFile.write( QString::number(QCoreApplication::applicationPid() ).toStdString().c_str() );
|
||||
pidFile.close();
|
||||
|
||||
MainWindow w;
|
||||
FSUDAQ w;
|
||||
w.show();
|
||||
return a.exec();
|
||||
}
|
Loading…
Reference in New Issue
Block a user