diff --git a/Analysis/CMakeLists.txt b/Analysis/CMakeLists.txt index dd206f785b4a0c1ef351c4cd40dc8a81c44b543b..b4897b3d8063245d20402d441630708452c650e5 100644 --- a/Analysis/CMakeLists.txt +++ b/Analysis/CMakeLists.txt @@ -5,3 +5,4 @@ add_subdirectory(IntervalTimeAnaTool) add_subdirectory(ChargeAnaTool) add_subdirectory(HitSpecAnaTool) add_subdirectory(HitRateAnaTool) +add_subdirectory(HitRateDisAnaTool) diff --git a/Analysis/HitRateAnaTool/src/HitRateAnaTool.cc b/Analysis/HitRateAnaTool/src/HitRateAnaTool.cc index aaa46da3d8bfec9df3beb329d01f61328694cd40..190c9483ef6a05d7642eb491587bcebd8dcdb7bc 100644 --- a/Analysis/HitRateAnaTool/src/HitRateAnaTool.cc +++ b/Analysis/HitRateAnaTool/src/HitRateAnaTool.cc @@ -189,7 +189,7 @@ bool HitRateAnaTool::output() { // m_rateCh[i]->SetPoint(j, j + 1, static_cast<double>(m_hitsPerCycle[i].at(j)) / TCYCLE); double err = getStd(m_hitsPerCycle[i], j, j + 10); m_rateCh[i]->SetPoint(np, j / 10 + 1, times * nHits / time); - m_rateCh[i]->SetPointError(np, 0, times * err / TMath::Sqrt(time / TCYCLE)); + m_rateCh[i]->SetPointError(np, 0, err / TMath::Sqrt(nHits)); if (m_catiHitsPerCyc[i / 16].size() > j / 10) { m_catiHitsPerCyc[i / 16].at(j / 10) += nHits; @@ -213,7 +213,7 @@ bool HitRateAnaTool::output() { m_rateCat[i]->Set(size); for (int j = 0; j < size; j ++) { m_rateCat[i]->SetPoint(np, j + 1, times * m_catiHitsPerCyc[i].at(j) / m_catiTimePerCyc[i].at(j)); - m_rateCat[i]->SetPointError(np, 0, times * TMath::Sqrt(m_catiErroPerCyc[i].at(j))); + m_rateCat[i]->SetPointError(np, 0, TMath::Sqrt(m_catiErroPerCyc[i].at(j) / m_catiHitsPerCyc[i].at(j))); np ++; } } diff --git a/Analysis/HitRateDisAnaTool/CMakeLists.txt b/Analysis/HitRateDisAnaTool/CMakeLists.txt new file mode 100644 index 0000000000000000000000000000000000000000..7dc2faacb6ac83745158f7cb8efbeee4c208f35a --- /dev/null +++ b/Analysis/HitRateDisAnaTool/CMakeLists.txt @@ -0,0 +1,4 @@ +PKG(HitRateDisAnaTool + DEPENDS + AnaTool +) diff --git a/Analysis/HitRateDisAnaTool/python/HitRateDisAnaTool/__init__.py b/Analysis/HitRateDisAnaTool/python/HitRateDisAnaTool/__init__.py new file mode 100644 index 0000000000000000000000000000000000000000..50997700dc5b062a7bc40519f40550afaaefd58f --- /dev/null +++ b/Analysis/HitRateDisAnaTool/python/HitRateDisAnaTool/__init__.py @@ -0,0 +1,2 @@ +import Sniper as sn +sn.loadDll("libHitRateDisAnaTool.so") diff --git a/Analysis/HitRateDisAnaTool/src/HitRateDisAnaTool.cc b/Analysis/HitRateDisAnaTool/src/HitRateDisAnaTool.cc new file mode 100644 index 0000000000000000000000000000000000000000..abdacd167c67f8a0ff22756341b984f3d63941ff --- /dev/null +++ b/Analysis/HitRateDisAnaTool/src/HitRateDisAnaTool.cc @@ -0,0 +1,177 @@ +#include "HitRateDisAnaTool.h" + +DECLARE_TOOL(HitRateDisAnaTool); +HitRateDisAnaTool::HitRateDisAnaTool(const string &name) + : ToolBase(name) +{ + declProp("HighRate", m_hrFlag = 1); +} + +HitRateDisAnaTool::~HitRateDisAnaTool() {} + +bool HitRateDisAnaTool::configure(string outDir, SPMTMap *spmtMap) { + LogInfo << "configuring..." << endl; + m_outDir = outDir; + m_spmtMap = spmtMap; + m_nPoint = 0; + + m_canvas.reset(new TCanvas("", "", 4000, 4000)); + m_hitsPerCh.reset(new TH1F("", "HitsPerChannel;Channel;nHit", NCH, 0, NCH)); + m_timePerCh.reset(new TH1F("", "TimePerChannel;Channel;DAQ time", NCH, 0, NCH)); + m_rateDis.reset(new TGraph2D()); + m_hitsPerCh->SetDirectory(0); + m_timePerCh->SetDirectory(0); + m_rateDis->SetDirectory(0); + + m_nCycle = 0; + m_lastNCycle = -1; + + m_rateCh.reserve(NCH); + + for (int i = 0; i < NCH; i ++) { + TString tmp("Ch "); + tmp += i; + m_rateCh.push_back(make_unique<TGraphErrors>()); + m_rateCh[i]->SetMarkerColor(kRed); + m_rateCh[i]->SetLineColor(kBlack); + m_rateCh[i]->SetMarkerStyle(26); + m_rateCh[i]->GetYaxis()->SetTitle(tmp + " hit rate / Hz"); + m_rateCh[i]->GetXaxis()->SetTitle("Time / (16.7 s)"); + } + + std::fill(m_stTime, m_stTime + NCH, -1); + std::fill(m_edTime, m_edTime + NCH, -1); + std::fill(m_lastCoarseTimes, m_lastCoarseTimes + NCH, -1); + std::fill(m_cycle, m_cycle + NCH, -1); + std::fill(m_hits, m_hits + NCH, 0); + return true; +} + +bool HitRateDisAnaTool::reset() { + + m_hitsPerCh->Reset("ICE"); + m_timePerCh->Reset("ICE"); + for (int i = 0; i < NCH; i ++) { + m_hitsPerCycle[i].clear(); + m_timePerCyc[i].clear(); + m_rateCh[i]->Set(0); + } + + for (int i = 0; i < 8; i ++) { + m_catiHitsPerCyc[i].clear(); + m_catiTimePerCyc[i].clear(); + m_catiErroPerCyc[i].clear(); + } + + std::fill(m_stTime, m_stTime + NCH, -1); + std::fill(m_edTime, m_edTime + NCH, -1); + std::fill(m_lastCoarseTimes, m_lastCoarseTimes + NCH, -1); + std::fill(m_cycle, m_cycle + NCH, -1); + std::fill(m_hits, m_hits + NCH, 0); + + m_nCycle = 0; + m_lastNCycle = -1; + return true; +} + +bool HitRateDisAnaTool::analyze(const Params& paras) { + m_evtType = paras.get("EventType"); + m_abcCh = paras.get("ABCChannelNumber"); + m_gcuId = paras.get("GCUId"); + m_runNum = paras.get("RunNum"); + m_coarseTime = paras.get("CoarseTime"); + m_fineTime = paras.get("FineTime"); + + m_hitsPerCh->Fill(m_abcCh); + + if (m_stTime[m_abcCh] = -1) { + m_stTime[m_abcCh] = m_coarseTime; + } + + if (m_cycle[m_abcCh] == -1 || m_cycle[m_abcCh] == paras.get("OverflowCounter")) { + m_hits[m_abcCh] ++; + if (m_coarseTime > m_edTime[m_abcCh]) + m_edTime[m_abcCh] = m_coarseTime; + if (m_coarseTime < m_stTime[m_abcCh]) + m_stTime[m_abcCh] = m_coarseTime; + } + else { + if (m_nCycle - m_hitsPerCycle[m_abcCh].size() > 1) { + for (int i = 0; i < (m_nCycle - m_hitsPerCycle[m_abcCh].size() - 1); i ++) + m_hitsPerCycle[m_abcCh].push_back(0); + } + m_hitsPerCycle[m_abcCh].push_back(m_hits[m_abcCh]); + if (m_hitsPerCycle[m_abcCh].size() > m_nCycle) + m_nCycle = m_hitsPerCycle[m_abcCh].size(); + m_hits[m_abcCh] = 1; + m_timePerCyc[m_abcCh].push_back(25 * static_cast<double>(m_edTime[m_abcCh] - m_stTime[m_abcCh])); + m_stTime[m_abcCh] = m_coarseTime; + m_edTime[m_abcCh] = m_coarseTime; + } + + m_cycle[m_abcCh] = paras.get("OverflowCounter"); + m_timePerCh->SetBinContent(m_abcCh + 1, m_cycle[m_abcCh] * TCYCLE + m_coarseTime * 25); + m_lastCoarseTimes[m_abcCh] = m_coarseTime; + + return true; +} + +bool HitRateDisAnaTool::output() { + TString outFile(m_outDir); + outFile += "_"; + outFile += to_string(m_runNum); + if (m_evtType) + outFile += "_Phy"; + else + outFile += "_Ped"; + m_outPdf = outFile + "_hists.pdf"; + m_outTxt = outFile + "_stat.txt"; + + LogInfo << "Output gcu " << m_gcuId << ", run " << m_runNum << endl; + LogInfo << "PDF dir: " << m_outPdf << endl; + LogInfo << "TXT dir: " << m_outTxt << endl; + + for (int i = 0; i < NCH; i ++) { + m_hitsPerCycle[i].push_back(m_hits[i]); + m_timePerCyc[i].push_back(25 * static_cast<double>(m_edTime[i] - m_stTime[i])); + } + + double times = 1; + if (m_hrFlag) + times = TCYCLE / 12.5E-3; + + for (int i = 0; i < NCH; i ++) { + int size = m_hitsPerCycle[i].size(); + int nPoint = size / 10; + if (size % 10) + nPoint ++; + if (nPoint == 0) + nPoint = 1; + double nHits = 0; + double time = 0; + for (int j = 0; j < size; j += 10) { + nHits += m_hitsPerCycle[i].at(j); + time += static_cast<double>(TCYCLE); + } + TVector3 pos = m_spmtMap->getPosition(m_gcuId, i); + m_rateDis->SetPoint(m_nPoint, pos.X() / 1000., pos.Y() / 1000., nHits / time); + m_nPoint ++; + } + + m_canvas->Clear(); + + m_rateDis->SetTitle(";X / m;Y / m"); + m_rateDis->SetMarkerStyle(22); + m_rateDis->SetMarkerSize(6.0); + + m_canvas->SetLeftMargin(0.15); + m_canvas->SetBottomMargin(0.15); + m_canvas->SetTheta(90); + m_canvas->SetPhi(0.001); + m_canvas->cd(); + m_rateDis->DrawClone("PCOL"); + m_canvas->SaveAs(m_outPdf); + + reset(); + return true; +} diff --git a/Analysis/HitRateDisAnaTool/src/HitRateDisAnaTool.h b/Analysis/HitRateDisAnaTool/src/HitRateDisAnaTool.h new file mode 100644 index 0000000000000000000000000000000000000000..f8e98788ea6edd5f43a2f84b292fffb9401c4c0d --- /dev/null +++ b/Analysis/HitRateDisAnaTool/src/HitRateDisAnaTool.h @@ -0,0 +1,83 @@ +#ifndef HitRateDisAnaTool_h +#define HitRateDisAnaTool_h + +#include "AnaTool/Params.h" +#include "AnaTool/AnaTool.h" +#include "SniperKernel/ToolBase.h" +#include "SniperKernel/ToolFactory.h" + +#include <iostream> +#include <fstream> +#include <vector> +#include <memory> +#include <string> + +#include <TH1F.h> +#include <TH2F.h> +#include <TCanvas.h> +#include <TF1.h> +#include <TString.h> +#include <TVector3.h> +#include <TGraph.h> +#include <TGraph2D.h> +#include <TGraphErrors.h> + +#define CYCLE 67108864 +#define TCYCLE 1.6777216 + +using namespace std; + +class HitRateDisAnaTool : public AnaTool, public ToolBase { + public: + HitRateDisAnaTool(const string &name); + ~HitRateDisAnaTool(); + + bool configure(string, SPMTMap*); + bool analyze(const Params&); + bool output(); + + private: + string m_outDir; + TString m_outPdf; + TString m_outTxt; + + unique_ptr<TCanvas> m_canvas; + + int m_gcuId; + int m_runNum; + int m_evtType; + int m_abcCh; + int m_coarseTime; + int m_fineTime; + int m_nCycle; + int m_lastNCycle; + int m_gCycle; + int m_gLastCT; + int m_lastCoarseTimes[NCH]; + int m_cycle[NCH]; + int m_hits[NCH]; + + int m_stTime[NCH]; + int m_edTime[NCH]; + + int m_hrFlag; + int m_nPoint; + + unique_ptr<TH1F> m_hitsPerCh; + unique_ptr<TH1F> m_timePerCh; + + vector<unique_ptr<TGraphErrors>> m_rateCh; + unique_ptr<TGraph2D> m_rateDis; + + vector<int> m_hitsPerCycle[NCH]; + vector<double> m_catiHitsPerCyc[8]; + vector<double> m_catiTimePerCyc[8]; + vector<double> m_catiErroPerCyc[8]; + vector<double> m_timePerCyc[NCH]; + + SPMTMap *m_spmtMap; + + bool reset(); +}; + +#endif diff --git a/README.md b/README.md index f2e991e4d8491fbd0d2ca5d5b0118e4db005b3fc..50ec59c80a3dadae5508209825f8041756271e40 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,42 @@ Similar to JUNO Offline, two main structures exist: one is named **`algorithm`** 1. **`algorithm`** can accept the input **arguments** and input **data** (only `ROOT` data can be accepted now). The **data** is input as a list written in a text file, **arguments** can be delivered to the **`algorithm`** by setting in the python script. Besides, the **`algorithm`** can call analysis **`tool`** to process the data. 2. **`tool`** contains the true analysis algorithm +## How to use existing method + +```bash +source setup.sh // in the spmtOffline folder +``` + +### Convert binary to ROOT +```bash +python $SHAREROOT/convert.py --input [path of binary file list] --output [output path] +``` + +### Get charge spectrum +```bash +python $SHAREROOT/getChargeSpec.py --input [path of ROOT file list] --output [output path] +``` + +### Get hit rate +```bash +python $SHAREROOT/getHitRate.py --input [path of ROOT file list] --output [output path] +``` + +### Get hit rate distribution in xoy +```bash +python $SHAREROOT/getHitRateDis.py --input [path of ROOT file list] --output [output path] +``` + +### Get time interval +```bash +python $SHAREROOT/getTimeInterval.py --input [path of ROOT file list] --output [output path] +``` + +### Get noise per channel +```bash +python $SHAREROOT/getNoise.py --input [path of ROOT file list] --output [output path] +``` + ## Create your own algorithm Create an **`algorithm`** named `ExampleAlg` in `./Analysis` diff --git a/share/getHitRateDis.py b/share/getHitRateDis.py new file mode 100644 index 0000000000000000000000000000000000000000..7f1a106f343691aa1385c3bce10c73e25f27076f --- /dev/null +++ b/share/getHitRateDis.py @@ -0,0 +1,53 @@ +#!/usr/bin/env python +#-*- coding: utf-8 -*- + +# For NoiseAnaTool +from __future__ import print_function + +import argparse +import sys +import os + +def get_parser(): + parser = argparse.ArgumentParser(description='Commissioning analysis') + parser.add_argument("--input", default="./testList", help="the file which contains input file names") + parser.add_argument("--output", default="./", help="output file name") + parser.add_argument("--highRate", type=int, default=1) + parser.add_argument("--evtmax", type=int, default=-1) + parser.add_argument("--toollist", default="{}/hitRateDisToolList".format(os.environ.get('SHAREROOT'))) + parser.add_argument("--gcu2pos", default="{}/gcu2pos".format(os.environ.get('SHAREROOT'))) + parser.add_argument("--abc2cnt", default="{}/abc2cnt".format(os.environ.get('SHAREROOT'))) + return parser + +parser = get_parser(); +args = parser.parse_args() + +import Sniper +import CommissioningAlg + +# Initial task and algorithm +# ======================================== +task = Sniper.TopTask("spmtAna") +alg = task.createAlg("CommissioningAlg") + +# ======================================== +# Add new tool here +import HitRateDisAnaTool + +# Add new tool here +htTool = alg.createTool("HitRateDisAnaTool") + +# Set arguments +# ======================================== +alg.property("inputList").set(args.input) +alg.property("outputDir").set(args.output) +alg.property("evtMax").set(args.evtmax) +alg.property("toolNameList").set(args.toollist) +alg.property("mapGcu2Pos").set(args.gcu2pos) +alg.property("mapAbc2Cnt").set(args.abc2cnt) + +htTool.property("HighRate").set(args.highRate) + +task.setLogLevel(0) +task.setEvtMax(1) +task.run() diff --git a/share/getNoise.py b/share/getNoise.py new file mode 100644 index 0000000000000000000000000000000000000000..904c40a04cf22b7138d0cd90fb11ec25435bea5b --- /dev/null +++ b/share/getNoise.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python +#-*- coding: utf-8 -*- + +# For NoiseAnaTool +from __future__ import print_function + +import argparse +import sys +import os + +def get_parser(): + parser = argparse.ArgumentParser(description='Commissioning analysis') + parser.add_argument("--input", default="./testList", help="the file which contains input file names") + parser.add_argument("--output", default="./", help="output file name") + parser.add_argument("--evtmax", type=int, default=-1) + parser.add_argument("--toollist", default="{}/noiseToolList".format(os.environ.get('SHAREROOT'))) + return parser + +parser = get_parser(); +args = parser.parse_args() + +import Sniper +import CommissioningAlg + +# Initial task and algorithm +# ======================================== +task = Sniper.TopTask("spmtAna") +alg = task.createAlg("CommissioningAlg") + +# ======================================== +# Add new tool here +import NoiseAnaTool + +# Add new tool here +alg.createTool("NoiseAnaTool") + +# Set arguments +# ======================================== +alg.property("inputList").set(args.input) +alg.property("outputDir").set(args.output) +alg.property("evtMax").set(args.evtmax) +alg.property("toolNameList").set(args.toollist) + +task.setLogLevel(0) +task.setEvtMax(1) +task.run() diff --git a/share/hitRateDisToolList b/share/hitRateDisToolList new file mode 100644 index 0000000000000000000000000000000000000000..d95ab17d79455c4e2eee9aab5061aa985df5ff89 --- /dev/null +++ b/share/hitRateDisToolList @@ -0,0 +1 @@ +HitRateDisAnaTool diff --git a/share/noiseToolList b/share/noiseToolList new file mode 100644 index 0000000000000000000000000000000000000000..d77b07efde617cae575581c09f7e5344a877d685 --- /dev/null +++ b/share/noiseToolList @@ -0,0 +1 @@ +NoiseAnaTool