Compare commits
106 Commits
master
...
devel_suda
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
98b438a54e | ||
|
|
3fdf5e9c41 | ||
|
|
1a16ef41f3 | ||
|
|
f6f07a1b0c | ||
|
|
4de5507285 | ||
|
|
2f43903269 | ||
|
|
7be45f35df | ||
|
|
1e0af0fe9d | ||
|
|
1ace406746 | ||
|
|
d70581784a | ||
|
|
eb54b6ab68 | ||
|
|
e61a63ea13 | ||
|
|
39f7f7da37 | ||
|
|
d3305b24cc | ||
|
|
76baa16390 | ||
|
|
103ddb3958 | ||
|
|
623e72a197 | ||
|
|
1c63cca714 | ||
|
|
9aced93bec | ||
|
|
cbd4bf42a7 | ||
|
|
601caa3881 | ||
|
|
2938411c35 | ||
|
|
8c2657255c | ||
|
|
00f8460e36 | ||
|
|
7260d42d8d | ||
|
|
4401ae8eb2 | ||
|
|
282aa5ecea | ||
|
|
9f949edd00 | ||
|
|
56cc900b61 | ||
|
|
17ab8c884a | ||
|
|
67199cdb60 | ||
|
|
ac035370b4 | ||
|
|
c4b543bdeb | ||
|
|
0a8432e4e3 | ||
|
|
0883ebdb6e | ||
|
|
9c20c4abfe | ||
|
|
13bfafe9c4 | ||
|
|
22e32c7ebc | ||
|
|
4599ad2a38 | ||
|
|
c1ffaa8340 | ||
|
|
19286055ea | ||
|
|
82c2127b4d | ||
|
|
d81e35d5e4 | ||
|
|
97880940be | ||
|
|
aee3a2467d | ||
|
|
c32215e293 | ||
|
|
535afcb704 | ||
|
|
0773b9e6cc | ||
|
|
7582731de4 | ||
|
|
49de3b64a8 | ||
|
|
61473ca14e | ||
|
|
ecd755e09c | ||
|
|
265ebd3372 | ||
|
|
afef56df12 | ||
|
|
579f4e4f6c | ||
|
|
d59b22ff78 | ||
|
|
49610e9c2f | ||
|
|
fa4b1dd2f5 | ||
|
|
877f765357 | ||
|
|
06fbc1afd9 | ||
|
|
b44ffd7fdf | ||
|
|
3d0d176f5a | ||
|
|
4fc05ea338 | ||
|
|
dd2ec66db1 | ||
|
|
a8d4e8f0f6 | ||
|
|
2864036ec8 | ||
|
|
050cb425d5 | ||
|
|
fb355a3cc4 | ||
|
|
5b43d60b30 | ||
|
|
e86ab5ed4d | ||
|
|
9cadfdd191 | ||
|
|
d4582d80ff | ||
|
|
18870ed82b | ||
|
|
5c1c5348f4 | ||
|
|
65ab69ebe6 | ||
|
|
1df7470ca1 | ||
|
|
a7a765c059 | ||
|
|
39e8f41ab1 | ||
|
|
9225620426 | ||
|
|
2225b3a942 | ||
|
|
6cfb38b564 | ||
|
|
cb72c14ca4 | ||
|
|
5995081396 | ||
|
|
d623e0cd17 | ||
|
|
8d7322cf5a | ||
|
|
699b0f8701 | ||
|
|
02213caaee | ||
|
|
56a6389b4f | ||
|
|
b99ad4e4d7 | ||
|
|
a5dfa2ecd3 | ||
|
|
26e943adc8 | ||
|
|
42e093b104 | ||
|
|
3129339647 | ||
|
|
7a70340b18 | ||
|
|
a10081ea81 | ||
|
|
4cb8a2c48c | ||
|
|
fe6dbee171 | ||
|
|
7805481ead | ||
|
|
511b4aa808 | ||
|
|
43233ceb02 | ||
|
|
68fc36a8f6 | ||
|
|
a6e754b958 | ||
|
|
48ede97992 | ||
|
|
f0a393abe2 | ||
|
|
4ba9c73b98 | ||
|
|
238ec8961e |
18
.gitignore
vendored
18
.gitignore
vendored
|
|
@ -4,9 +4,25 @@ EventBuilder*
|
||||||
*.pcm
|
*.pcm
|
||||||
*.root
|
*.root
|
||||||
*.exe
|
*.exe
|
||||||
|
*.err
|
||||||
|
*.seq
|
||||||
|
*.png
|
||||||
Mapper
|
Mapper
|
||||||
AnasenMS
|
AnasenMS
|
||||||
|
|
||||||
data/
|
data/
|
||||||
data_proton/
|
data_proton/
|
||||||
|
Sudarshan/
|
||||||
|
Analyzer_C_ACLiC_dict0713aaa966_dictContent.h
|
||||||
|
.gitignore
|
||||||
|
Analyzer_C_ACLiC_dict5411fecd5c_dictUmbrella.h
|
||||||
|
gainmatch.C
|
||||||
|
gainmatch.h
|
||||||
|
MakePlotsQQQ.C
|
||||||
|
MakePlotsQQQ.h
|
||||||
|
MakePlotsSX3.C
|
||||||
|
MakePlotsSX3.h
|
||||||
|
qqq_gains_det3.dat
|
||||||
|
qqq_relative_gains.dat
|
||||||
|
Armory/CorrelateQQQ.h
|
||||||
|
QQQStage2.C
|
||||||
|
|
|
||||||
58
.vscode/c_cpp_properties.json
vendored
58
.vscode/c_cpp_properties.json
vendored
|
|
@ -1,23 +1,11 @@
|
||||||
{
|
{
|
||||||
"configurations": [
|
"configurations": [
|
||||||
{
|
{
|
||||||
"name": "splitpole",
|
"name": "Hades",
|
||||||
"includePath": [
|
"includePath": [
|
||||||
"${workspaceFolder}/**",
|
"${workspaceFolder}/**",
|
||||||
"/home/splitpole/cern/root/**"
|
"/usr/include/x86_64-linux-gnu/qt6/**",
|
||||||
],
|
"/usr/local/cern/root_v6.26.06/include/**"
|
||||||
"defines": [],
|
|
||||||
"compilerPath": "/usr/bin/gcc",
|
|
||||||
"cStandard": "c17",
|
|
||||||
"cppStandard": "gnu++17",
|
|
||||||
"intelliSenseMode": "linux-gcc-x64"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "Ryan",
|
|
||||||
"includePath": [
|
|
||||||
"${workspaceFolder}/**",
|
|
||||||
"/home/ryan/Downloads/root_build/**",
|
|
||||||
"/home/ryan/Downloads/root_build/include"
|
|
||||||
],
|
],
|
||||||
"defines": [],
|
"defines": [],
|
||||||
"compilerPath": "/usr/bin/gcc",
|
"compilerPath": "/usr/bin/gcc",
|
||||||
|
|
@ -29,7 +17,8 @@
|
||||||
"name": "RyanUbuntu",
|
"name": "RyanUbuntu",
|
||||||
"includePath": [
|
"includePath": [
|
||||||
"${workspaceFolder}/**",
|
"${workspaceFolder}/**",
|
||||||
"/opt/root/**"
|
"/usr/include/x86_64-linux-gnu/qt6/**",
|
||||||
|
"/opt/root/include/**"
|
||||||
],
|
],
|
||||||
"defines": [],
|
"defines": [],
|
||||||
"compilerPath": "/usr/bin/gcc",
|
"compilerPath": "/usr/bin/gcc",
|
||||||
|
|
@ -38,10 +27,11 @@
|
||||||
"intelliSenseMode": "linux-gcc-x64"
|
"intelliSenseMode": "linux-gcc-x64"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "RyanHome",
|
"name": "Anasen",
|
||||||
"includePath": [
|
"includePath": [
|
||||||
"${workspaceFolder}/**",
|
"${workspaceFolder}/**",
|
||||||
"/home/ryan/root_v6.30.06/**"
|
"/usr/include/x86_64-linux-gnu/qt6/**",
|
||||||
|
"/opt/root/include/**"
|
||||||
],
|
],
|
||||||
"defines": [],
|
"defines": [],
|
||||||
"compilerPath": "/usr/bin/gcc",
|
"compilerPath": "/usr/bin/gcc",
|
||||||
|
|
@ -50,10 +40,38 @@
|
||||||
"intelliSenseMode": "linux-gcc-x64"
|
"intelliSenseMode": "linux-gcc-x64"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "Dirac",
|
"name": "Splitpole",
|
||||||
"includePath": [
|
"includePath": [
|
||||||
"${workspaceFolder}/**",
|
"${workspaceFolder}/**",
|
||||||
"/usr/opt/root/**"
|
"/usr/include/x86_64-linux-gnu/qt6/**",
|
||||||
|
"/home/splitpole/cern/root/include/**",
|
||||||
|
"/usr/include/x86_64-linux-gnu/qt6/QtWidgets",
|
||||||
|
"/usr/include/x86_64-linux-gnu/qt6/QtCore"
|
||||||
|
],
|
||||||
|
"defines": [],
|
||||||
|
"compilerPath": "/usr/bin/gcc",
|
||||||
|
"cStandard": "c17",
|
||||||
|
"cppStandard": "gnu++17",
|
||||||
|
"intelliSenseMode": "linux-gcc-x64"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Penguin",
|
||||||
|
"includePath": [
|
||||||
|
"${workspaceFolder}/**",
|
||||||
|
"/usr/include/x86_64-linux-gnu/qt6/**",
|
||||||
|
"/usr/local/cern/root/include/**"
|
||||||
|
],
|
||||||
|
"defines": [],
|
||||||
|
"compilerPath": "/usr/bin/gcc",
|
||||||
|
"cStandard": "c17",
|
||||||
|
"cppStandard": "gnu++17",
|
||||||
|
"intelliSenseMode": "linux-gcc-x64"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "VigneshROG",
|
||||||
|
"includePath": [
|
||||||
|
"${workspaceFolder}/**",
|
||||||
|
"/home/vsitaraman/root/include/**"
|
||||||
],
|
],
|
||||||
"defines": [],
|
"defines": [],
|
||||||
"compilerPath": "/usr/bin/gcc",
|
"compilerPath": "/usr/bin/gcc",
|
||||||
|
|
|
||||||
40
.vscode/settings.json
vendored
40
.vscode/settings.json
vendored
|
|
@ -90,6 +90,42 @@
|
||||||
"processRun.C": "cpp",
|
"processRun.C": "cpp",
|
||||||
"TrackRecon.C": "cpp",
|
"TrackRecon.C": "cpp",
|
||||||
"processRuns.C": "cpp",
|
"processRuns.C": "cpp",
|
||||||
"Analysis.C": "cpp"
|
"Analysis.C": "cpp",
|
||||||
}
|
"datastructs.h": "c",
|
||||||
|
"ANASENPlotEdit.C": "cpp",
|
||||||
|
"GetMean_Q3_new.C": "cpp",
|
||||||
|
"AlphaCal_new.C": "cpp",
|
||||||
|
"f1.C": "cpp",
|
||||||
|
"GeoCal_Maria_new.C": "cpp",
|
||||||
|
"PCPulser_All_new.C": "cpp",
|
||||||
|
"PosCal_2.C": "cpp",
|
||||||
|
"AutoFit.C": "cpp",
|
||||||
|
"Fitting.C": "cpp",
|
||||||
|
"PCGainMatch.C": "cpp",
|
||||||
|
"Analyzer1.C": "cpp",
|
||||||
|
"FitHistogramsWithTSpectrum_Sequential_Improved.C": "cpp",
|
||||||
|
"PlotAndFitCentroids.C": "cpp",
|
||||||
|
"MatchAndPlotCentroids.C": "cpp",
|
||||||
|
"GainMatch.C": "cpp",
|
||||||
|
"GainMatchSX3.C": "cpp",
|
||||||
|
"RelBack_Fix_new.C": "cpp",
|
||||||
|
"SiRelativeGains_Step1_new.C": "cpp",
|
||||||
|
"charconv": "cpp",
|
||||||
|
"format": "cpp",
|
||||||
|
"GainMatchSX3Front.C": "cpp",
|
||||||
|
"GainMatchSX3Front1.C": "cpp",
|
||||||
|
"Calibration.C": "cpp",
|
||||||
|
"GainMatchQQQ.C": "cpp",
|
||||||
|
"UTF-8gainmatch.C": "cpp",
|
||||||
|
"MakePlotsQQQ.C": "cpp",
|
||||||
|
"MakePlotsSX3.C": "cpp",
|
||||||
|
"QQQ_Calibcheck.C": "cpp",
|
||||||
|
"QQQ_Calcheck.C": "cpp",
|
||||||
|
"makeplots.C": "cpp",
|
||||||
|
"GlobalMinimizeQQQ.C": "cpp",
|
||||||
|
"QQQStage2.C": "cpp",
|
||||||
|
"inspect.C": "cpp"
|
||||||
|
},
|
||||||
|
"github-enterprise.uri": "https://fsunuc.physics.fsu.edu",
|
||||||
|
"C_Cpp.default.compilerPath": "/usr/bin/gcc"
|
||||||
}
|
}
|
||||||
946
Analyzer.C
946
Analyzer.C
File diff suppressed because it is too large
Load Diff
15
Analyzer.h
15
Analyzer.h
|
|
@ -18,6 +18,7 @@ public :
|
||||||
Det sx3;
|
Det sx3;
|
||||||
Det qqq;
|
Det qqq;
|
||||||
Det pc ;
|
Det pc ;
|
||||||
|
Det misc;
|
||||||
|
|
||||||
ULong64_t evID;
|
ULong64_t evID;
|
||||||
UInt_t run;
|
UInt_t run;
|
||||||
|
|
@ -40,6 +41,13 @@ public :
|
||||||
TBranch *b_pcCh; //!
|
TBranch *b_pcCh; //!
|
||||||
TBranch *b_pcE; //!
|
TBranch *b_pcE; //!
|
||||||
TBranch *b_pcT; //!
|
TBranch *b_pcT; //!
|
||||||
|
TBranch *b_miscMulti; //!
|
||||||
|
TBranch *b_miscID; //!
|
||||||
|
TBranch *b_miscCh; //!
|
||||||
|
TBranch *b_miscE; //!
|
||||||
|
TBranch *b_miscT; //!
|
||||||
|
TBranch *b_miscTf; //!
|
||||||
|
|
||||||
|
|
||||||
Analyzer(TTree * /*tree*/ =0) : fChain(0) { }
|
Analyzer(TTree * /*tree*/ =0) : fChain(0) { }
|
||||||
virtual ~Analyzer() { }
|
virtual ~Analyzer() { }
|
||||||
|
|
@ -92,6 +100,13 @@ void Analyzer::Init(TTree *tree){
|
||||||
fChain->SetBranchAddress("pcCh", &pc.ch, &b_pcCh);
|
fChain->SetBranchAddress("pcCh", &pc.ch, &b_pcCh);
|
||||||
fChain->SetBranchAddress("pcE", &pc.e, &b_pcE);
|
fChain->SetBranchAddress("pcE", &pc.e, &b_pcE);
|
||||||
fChain->SetBranchAddress("pcT", &pc.t, &b_pcT);
|
fChain->SetBranchAddress("pcT", &pc.t, &b_pcT);
|
||||||
|
fChain->SetBranchAddress("miscMulti", &misc.multi, &b_miscMulti);
|
||||||
|
fChain->SetBranchAddress("miscID", &misc.id, &b_miscID);
|
||||||
|
fChain->SetBranchAddress("miscCh", &misc.ch, &b_miscCh);
|
||||||
|
fChain->SetBranchAddress("miscE", &misc.e, &b_miscE);
|
||||||
|
fChain->SetBranchAddress("miscT", &misc.t, &b_miscT);
|
||||||
|
// fChain->SetBranchAddress("miscF", &misc.tf, &b_miscTf);
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
402
Analyzer1.C
Normal file
402
Analyzer1.C
Normal file
|
|
@ -0,0 +1,402 @@
|
||||||
|
#define Analyzer1_cxx
|
||||||
|
|
||||||
|
#include "Analyzer1.h"
|
||||||
|
#include <TH2.h>
|
||||||
|
#include <TStyle.h>
|
||||||
|
#include <TCanvas.h>
|
||||||
|
#include <TMath.h>
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
#include "Armory/ClassSX3.h"
|
||||||
|
#include "Armory/ClassPW.h"
|
||||||
|
|
||||||
|
#include "TVector3.h"
|
||||||
|
|
||||||
|
TH2F * hsx3IndexVE;
|
||||||
|
TH2F * hqqqIndexVE;
|
||||||
|
TH2F * hpcIndexVE;
|
||||||
|
|
||||||
|
TH2F * hsx3Coin;
|
||||||
|
TH2F * hqqqCoin;
|
||||||
|
TH2F * hpcCoin;
|
||||||
|
|
||||||
|
TH2F * hqqqPolar;
|
||||||
|
TH2F * hsx3VpcIndex;
|
||||||
|
TH2F * hqqqVpcIndex;
|
||||||
|
TH2F * hqqqVpcE;
|
||||||
|
TH2F * hsx3VpcE;
|
||||||
|
TH2F * hanVScatsum;
|
||||||
|
int padID = 0;
|
||||||
|
|
||||||
|
SX3 sx3_contr;
|
||||||
|
PW pw_contr;
|
||||||
|
TVector3 hitPos;
|
||||||
|
bool HitNonZero;
|
||||||
|
|
||||||
|
TH1F * hZProj;
|
||||||
|
|
||||||
|
void Analyzer1::Begin(TTree * /*tree*/){
|
||||||
|
TString option = GetOption();
|
||||||
|
|
||||||
|
hsx3IndexVE = new TH2F("hsx3IndexVE", "SX3 index vs Energy; sx3 index ; Energy", 24*12, 0, 24*12, 400, 0, 5000); hsx3IndexVE->SetNdivisions( -612, "x");
|
||||||
|
hqqqIndexVE = new TH2F("hqqqIndexVE", "QQQ index vs Energy; QQQ index ; Energy", 4*2*16, 0, 4*2*16, 400, 0, 5000); hqqqIndexVE->SetNdivisions( -1204, "x");
|
||||||
|
hpcIndexVE = new TH2F("hpcIndexVE", "PC index vs Energy; PC index ; Energy", 2*24, 0, 2*24, 400, 0, 4000); hpcIndexVE->SetNdivisions( -1204, "x");
|
||||||
|
|
||||||
|
|
||||||
|
hsx3Coin = new TH2F("hsx3Coin", "SX3 Coincident", 24*12, 0, 24*12, 24*12, 0, 24*12);
|
||||||
|
hqqqCoin = new TH2F("hqqqCoin", "QQQ Coincident", 4*2*16, 0, 4*2*16, 4*2*16, 0, 4*2*16);
|
||||||
|
hpcCoin = new TH2F("hpcCoin", "PC Coincident", 2*24, 0, 2*24, 2*24, 0, 2*24);
|
||||||
|
|
||||||
|
hqqqPolar = new TH2F("hqqqPolar", "QQQ Polar ID", 16*4, -TMath::Pi(), TMath::Pi(),16, 10, 50);
|
||||||
|
|
||||||
|
hsx3VpcIndex = new TH2F("hsx3Vpcindex", "sx3 vs pc; sx3 index; pc index", 24*12, 0, 24*12, 48, 0, 48);
|
||||||
|
hsx3VpcIndex->SetNdivisions( -612, "x");
|
||||||
|
hsx3VpcIndex->SetNdivisions( -12, "y");
|
||||||
|
hqqqVpcIndex = new TH2F("hqqqVpcindex", "qqq vs pc; qqq index; pc index", 4*2*16, 0, 4*2*16, 48, 0, 48);
|
||||||
|
hqqqVpcIndex->SetNdivisions( -612, "x");
|
||||||
|
hqqqVpcIndex->SetNdivisions( -12, "y");
|
||||||
|
|
||||||
|
hqqqVpcE = new TH2F("hqqqVpcEnergy", "qqq vs pc; qqq energy; pc energy", 400, 0, 5000, 400, 0, 5000);
|
||||||
|
hqqqVpcE->SetNdivisions( -612, "x");
|
||||||
|
hqqqVpcE->SetNdivisions( -12, "y");
|
||||||
|
|
||||||
|
hsx3VpcE = new TH2F("hsx3VpcEnergy", "sx3 vs pc; sx3 energy; pc energy", 400, 0, 5000, 400, 0, 5000);
|
||||||
|
hsx3VpcE->SetNdivisions( -612, "x");
|
||||||
|
hsx3VpcE->SetNdivisions( -12, "y");
|
||||||
|
|
||||||
|
hZProj = new TH1F("hZProj", "Z Projection", 1200, -600, 600);
|
||||||
|
|
||||||
|
hanVScatsum = new TH2F("hanVScatsum", "Anode vs Cathode Sum; Anode E; Cathode E", 400,0 , 10000, 400, 0 , 16000);
|
||||||
|
|
||||||
|
sx3_contr.ConstructGeo();
|
||||||
|
pw_contr.ConstructGeo();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Bool_t Analyzer1::Process(Long64_t entry){
|
||||||
|
|
||||||
|
// if ( entry > 100 ) return kTRUE;
|
||||||
|
|
||||||
|
hitPos.Clear();
|
||||||
|
HitNonZero = false;
|
||||||
|
|
||||||
|
// if( entry > 1) return kTRUE;
|
||||||
|
// printf("################### ev : %llu \n", entry);
|
||||||
|
|
||||||
|
b_sx3Multi->GetEntry(entry);
|
||||||
|
b_sx3ID->GetEntry(entry);
|
||||||
|
b_sx3Ch->GetEntry(entry);
|
||||||
|
b_sx3E->GetEntry(entry);
|
||||||
|
b_sx3T->GetEntry(entry);
|
||||||
|
b_qqqMulti->GetEntry(entry);
|
||||||
|
b_qqqID->GetEntry(entry);
|
||||||
|
b_qqqCh->GetEntry(entry);
|
||||||
|
b_qqqE->GetEntry(entry);
|
||||||
|
b_qqqT->GetEntry(entry);
|
||||||
|
b_pcMulti->GetEntry(entry);
|
||||||
|
b_pcID->GetEntry(entry);
|
||||||
|
b_pcCh->GetEntry(entry);
|
||||||
|
b_pcE->GetEntry(entry);
|
||||||
|
b_pcT->GetEntry(entry);
|
||||||
|
|
||||||
|
sx3.CalIndex();
|
||||||
|
qqq.CalIndex();
|
||||||
|
pc.CalIndex();
|
||||||
|
|
||||||
|
// sx3.Print();
|
||||||
|
|
||||||
|
//########################################################### Raw data
|
||||||
|
// //======================= SX3
|
||||||
|
|
||||||
|
std::vector<std::pair<int, int>> ID; // first = id, 2nd = index
|
||||||
|
for( int i = 0; i < sx3.multi; i ++){
|
||||||
|
ID.push_back(std::pair<int, int>(sx3.id[i], i));
|
||||||
|
|
||||||
|
hsx3IndexVE->Fill( sx3.index[i], sx3.e[i] );
|
||||||
|
|
||||||
|
for( int j = i+1; j < sx3.multi; j++){
|
||||||
|
hsx3Coin->Fill( sx3.index[i], sx3.index[j]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for( int j = 0; j < pc.multi; j++){
|
||||||
|
hsx3VpcIndex->Fill( sx3.index[i], pc.index[j] );
|
||||||
|
// if( sx3.ch[index] > 8 ){
|
||||||
|
// hsx3VpcE->Fill( sx3.e[i], pc.e[j] );
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if( ID.size() > 0 ){
|
||||||
|
std::sort(ID.begin(), ID.end(), [](const std::pair<int, int> & a, const std::pair<int, int> & b) {
|
||||||
|
return a.first < b.first;
|
||||||
|
} );
|
||||||
|
// printf("##############################\n");
|
||||||
|
// for( size_t i = 0; i < ID.size(); i++) printf("%zu | %d %d \n", i, ID[i].first, ID[i].second );
|
||||||
|
|
||||||
|
std::vector<std::pair<int, int>> sx3ID;
|
||||||
|
sx3ID.push_back(ID[0]);
|
||||||
|
bool found = false;
|
||||||
|
for( size_t i = 1; i < ID.size(); i++){
|
||||||
|
if( ID[i].first == sx3ID.back().first) {
|
||||||
|
sx3ID.push_back(ID[i]);
|
||||||
|
if( sx3ID.size() >= 3) {
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
if( !found ){
|
||||||
|
sx3ID.clear();
|
||||||
|
sx3ID.push_back(ID[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// printf("---------- sx3ID Multi : %zu \n", sx3ID.size());
|
||||||
|
|
||||||
|
if( found ){
|
||||||
|
int sx3ChUp, sx3ChDn, sx3ChBk;
|
||||||
|
float sx3EUp, sx3EDn;
|
||||||
|
// printf("------ sx3 ID : %d, multi: %zu\n", sx3ID[0].first, sx3ID.size());
|
||||||
|
for( size_t i = 0; i < sx3ID.size(); i++ ){
|
||||||
|
int index = sx3ID[i].second;
|
||||||
|
// printf(" %zu | index %d | ch : %d, energy : %d \n", i, index, sx3.ch[index], sx3.e[index]);
|
||||||
|
|
||||||
|
|
||||||
|
if( sx3.ch[index] < 8 ){
|
||||||
|
if( sx3.ch[index] % 2 == 0) {
|
||||||
|
sx3ChDn = sx3.ch[index];
|
||||||
|
sx3EDn = sx3.e[index];
|
||||||
|
}else{
|
||||||
|
sx3ChUp = sx3.ch[index];
|
||||||
|
sx3EUp = sx3.e[index];
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
sx3ChBk = sx3.ch[index];
|
||||||
|
}
|
||||||
|
for( int j = 0; j < pc.multi; j++){
|
||||||
|
// hsx3VpcIndex->Fill( sx3.index[i], pc.index[j] );
|
||||||
|
if( sx3.ch[index] > 8 ){
|
||||||
|
hsx3VpcE->Fill( sx3.e[i], pc.e[j] );
|
||||||
|
// hpcIndexVE->Fill( pc.index[i], pc.e[i] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sx3_contr.CalSX3Pos(sx3ID[0].first, sx3ChUp, sx3ChDn, sx3ChBk, sx3EUp, sx3EDn);
|
||||||
|
hitPos = sx3_contr.GetHitPos();
|
||||||
|
HitNonZero = true;
|
||||||
|
// hitPos.Print();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// //======================= QQQ
|
||||||
|
for( int i = 0; i < qqq.multi; i ++){
|
||||||
|
// for( int j = 0; j < pc.multi; j++){
|
||||||
|
// if(pc.index[j]==4){
|
||||||
|
hqqqIndexVE->Fill( qqq.index[i], qqq.e[i] );
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
for( int j = 0; j < qqq.multi; j++){
|
||||||
|
if ( j == i ) continue;
|
||||||
|
hqqqCoin->Fill( qqq.index[i], qqq.index[j]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for( int j = i + 1; j < qqq.multi; j++){
|
||||||
|
for( int k = 0; k < pc.multi; k++){
|
||||||
|
if(pc.index[k]<24 && pc.e[k]>50 ){
|
||||||
|
hqqqVpcE->Fill( qqq.e[i], pc.e[k] );
|
||||||
|
// hpcIndexVE->Fill( pc.index[i], pc.e[i] );
|
||||||
|
hqqqVpcIndex->Fill( qqq.index[i], pc.index[j] );
|
||||||
|
|
||||||
|
}
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
// if( qqq.used[i] == true ) continue;
|
||||||
|
|
||||||
|
//if( qqq.id[i] == qqq.id[j] && (16 - qqq.ch[i]) * (16 - qqq.ch[j]) < 0 ){ // must be same detector and wedge and ring
|
||||||
|
if( qqq.id[i] == qqq.id[j] ){ // must be same detector
|
||||||
|
|
||||||
|
int chWedge = -1;
|
||||||
|
int chRing = -1;
|
||||||
|
if( qqq.ch[i] < qqq.ch[j]){
|
||||||
|
chRing = qqq.ch[j] - 16;
|
||||||
|
chWedge = qqq.ch[i];
|
||||||
|
}else{
|
||||||
|
chRing = qqq.ch[i];
|
||||||
|
chWedge = qqq.ch[j] - 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
// printf(" ID : %d , chWedge : %d, chRing : %d \n", qqq.id[i], chWedge, chRing);
|
||||||
|
|
||||||
|
double theta = -TMath::Pi()/2 + 2*TMath::Pi()/16/4.*(qqq.id[i]*16 + chWedge +0.5);
|
||||||
|
double rho = 10.+40./16.*(chRing+0.5);
|
||||||
|
// if(qqq.e[i]>50){
|
||||||
|
hqqqPolar->Fill( theta, rho);
|
||||||
|
// }
|
||||||
|
// qqq.used[i] = true;
|
||||||
|
// qqq.used[j] = true;
|
||||||
|
|
||||||
|
if( !HitNonZero ){
|
||||||
|
double x = rho * TMath::Cos(theta);
|
||||||
|
double y = rho * TMath::Sin(theta);
|
||||||
|
hitPos.SetXYZ(x, y, 23 + 75 + 30);
|
||||||
|
HitNonZero = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
// //======================= PC
|
||||||
|
|
||||||
|
ID.clear();
|
||||||
|
int counter=0;
|
||||||
|
std::vector<std::pair<int, double>> E;
|
||||||
|
E.clear();
|
||||||
|
for( int i = 0; i < pc.multi; i ++){
|
||||||
|
|
||||||
|
if( pc.e[i] > 100 ) ID.push_back(std::pair<int, int>(pc.id[i], i));
|
||||||
|
if( pc.e[i] > 100 ) E.push_back(std::pair<int, double>(pc.index[i], pc.e[i]));
|
||||||
|
|
||||||
|
hpcIndexVE->Fill( pc.index[i], pc.e[i] );
|
||||||
|
|
||||||
|
for( int j = i+1; j < pc.multi; j++){
|
||||||
|
hpcCoin->Fill( pc.index[i], pc.index[j]);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
// for( size_t i = 0; i < E.size(); i++) printf("%zu | %d %d \n", i, E[i].first, E[i].second );
|
||||||
|
|
||||||
|
if( E.size()>=3 ){
|
||||||
|
|
||||||
|
int aID = 0;
|
||||||
|
int cID = 0;
|
||||||
|
|
||||||
|
float aE = 0;
|
||||||
|
float cE = 0;
|
||||||
|
bool multi_an =false;
|
||||||
|
// if( ID[0].first < 1 ) {
|
||||||
|
// aID = pc.ch[ID[0].second];
|
||||||
|
// cID = pc.ch[ID[1].second];
|
||||||
|
// }else{
|
||||||
|
// cID = pc.ch[ID[0].second];
|
||||||
|
// aID = pc.ch[ID[1].second];
|
||||||
|
// }
|
||||||
|
// printf("anode= %d, cathode = %d\n", aID, cID);
|
||||||
|
|
||||||
|
// for( int k = 0; k < qqq.multi; k++){
|
||||||
|
// if(qqq.index[k]==75 && pc.index[k]==2 && pc.e[k]>100){
|
||||||
|
for(int l=0;l<E.size();l++){
|
||||||
|
if(E[l].first<24 ){
|
||||||
|
if(!multi_an){
|
||||||
|
aE = E[l].second;
|
||||||
|
}
|
||||||
|
multi_an=true;
|
||||||
|
}
|
||||||
|
else if (E[l].first>=24){
|
||||||
|
cE = E[l].second + cE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
hanVScatsum->Fill(aE,cE);
|
||||||
|
|
||||||
|
if( ID[0].first < 1 ) {
|
||||||
|
aID = pc.ch[ID[0].second];
|
||||||
|
cID = pc.ch[ID[1].second];
|
||||||
|
}else{
|
||||||
|
cID = pc.ch[ID[0].second];
|
||||||
|
aID = pc.ch[ID[1].second];
|
||||||
|
}
|
||||||
|
|
||||||
|
if( HitNonZero){
|
||||||
|
pw_contr.CalTrack( hitPos, aID, cID);
|
||||||
|
hZProj->Fill(pw_contr.GetZ0());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//########################################################### Track constrcution
|
||||||
|
|
||||||
|
|
||||||
|
//############################## DO THE KINEMATICS
|
||||||
|
|
||||||
|
|
||||||
|
return kTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Analyzer1::Terminate(){
|
||||||
|
|
||||||
|
gStyle->SetOptStat("neiou");
|
||||||
|
TCanvas * canvas = new TCanvas("cANASEN", "ANASEN", 2000, 2000);
|
||||||
|
canvas->Divide(3,3);
|
||||||
|
|
||||||
|
//hsx3VpcIndex->Draw("colz");
|
||||||
|
|
||||||
|
//=============================================== pad-1
|
||||||
|
padID ++; canvas->cd(padID); canvas->cd(padID)->SetGrid(1);
|
||||||
|
|
||||||
|
hsx3IndexVE->Draw("colz");
|
||||||
|
|
||||||
|
//=============================================== pad-2
|
||||||
|
padID ++; canvas->cd(padID); canvas->cd(padID)->SetGrid(1);
|
||||||
|
|
||||||
|
hqqqIndexVE->Draw("colz");
|
||||||
|
|
||||||
|
//=============================================== pad-3
|
||||||
|
padID ++; canvas->cd(padID); canvas->cd(padID)->SetGrid(1);
|
||||||
|
|
||||||
|
hpcIndexVE->Draw("colz");
|
||||||
|
|
||||||
|
//=============================================== pad-4
|
||||||
|
padID ++; canvas->cd(padID); canvas->cd(padID)->SetGrid(1);
|
||||||
|
|
||||||
|
hsx3Coin->Draw("colz");
|
||||||
|
|
||||||
|
//=============================================== pad-5
|
||||||
|
padID ++; canvas->cd(padID); canvas->cd(padID)->SetGrid(1);
|
||||||
|
|
||||||
|
canvas->cd(padID)->SetLogz(true);
|
||||||
|
|
||||||
|
hqqqCoin->Draw("colz");
|
||||||
|
|
||||||
|
//=============================================== pad-6
|
||||||
|
padID ++; canvas->cd(padID); canvas->cd(padID)->SetGrid(1);
|
||||||
|
|
||||||
|
hpcCoin->Draw("colz");
|
||||||
|
|
||||||
|
//=============================================== pad-7
|
||||||
|
padID ++; canvas->cd(padID); canvas->cd(padID)->SetGrid(1);
|
||||||
|
|
||||||
|
// hsx3VpcIndex ->Draw("colz");
|
||||||
|
hsx3VpcE->Draw("colz") ;
|
||||||
|
|
||||||
|
//=============================================== pad-8
|
||||||
|
padID ++; canvas->cd(padID); canvas->cd(padID)->SetGrid(1);
|
||||||
|
|
||||||
|
// hqqqVpcIndex ->Draw("colz");
|
||||||
|
|
||||||
|
hqqqVpcE ->Draw("colz");
|
||||||
|
//=============================================== pad-9
|
||||||
|
padID ++;
|
||||||
|
|
||||||
|
// canvas->cd(padID)->DrawFrame(-50, -50, 50, 50);
|
||||||
|
// hqqqPolar->Draw("same colz pol");
|
||||||
|
|
||||||
|
canvas->cd(padID); canvas->cd(padID)->SetGrid(1);
|
||||||
|
// hZProj->Draw();
|
||||||
|
hanVScatsum->Draw("colz");
|
||||||
|
|
||||||
|
}
|
||||||
114
Analyzer1.h
Normal file
114
Analyzer1.h
Normal file
|
|
@ -0,0 +1,114 @@
|
||||||
|
#ifndef Analyzer1_h
|
||||||
|
#define Analyzer1_h
|
||||||
|
|
||||||
|
#include <TROOT.h>
|
||||||
|
#include <TChain.h>
|
||||||
|
#include <TFile.h>
|
||||||
|
#include <TSelector.h>
|
||||||
|
|
||||||
|
#include "Armory/ClassDet.h"
|
||||||
|
|
||||||
|
class Analyzer1 : public TSelector {
|
||||||
|
public :
|
||||||
|
TTree *fChain; //!pointer to the analyzed TTree or TChain
|
||||||
|
|
||||||
|
// Fixed size dimensions of array or collections stored in the TTree if any.
|
||||||
|
|
||||||
|
// Declaration of leaf types
|
||||||
|
Det sx3;
|
||||||
|
Det qqq;
|
||||||
|
Det pc ;
|
||||||
|
|
||||||
|
ULong64_t evID;
|
||||||
|
UInt_t run;
|
||||||
|
|
||||||
|
// List of branches
|
||||||
|
TBranch *b_eventID; //!
|
||||||
|
TBranch *b_run; //!
|
||||||
|
TBranch *b_sx3Multi; //!
|
||||||
|
TBranch *b_sx3ID; //!
|
||||||
|
TBranch *b_sx3Ch; //!
|
||||||
|
TBranch *b_sx3E; //!
|
||||||
|
TBranch *b_sx3T; //!
|
||||||
|
TBranch *b_qqqMulti; //!
|
||||||
|
TBranch *b_qqqID; //!
|
||||||
|
TBranch *b_qqqCh; //!
|
||||||
|
TBranch *b_qqqE; //!
|
||||||
|
TBranch *b_qqqT; //!
|
||||||
|
TBranch *b_pcMulti; //!
|
||||||
|
TBranch *b_pcID; //!
|
||||||
|
TBranch *b_pcCh; //!
|
||||||
|
TBranch *b_pcE; //!
|
||||||
|
TBranch *b_pcT; //!
|
||||||
|
|
||||||
|
Analyzer1(TTree * /*tree*/ =0) : fChain(0) { }
|
||||||
|
virtual ~Analyzer1() { }
|
||||||
|
virtual Int_t Version() const { return 2; }
|
||||||
|
virtual void Begin(TTree *tree);
|
||||||
|
virtual void SlaveBegin(TTree *tree);
|
||||||
|
virtual void Init(TTree *tree);
|
||||||
|
virtual Bool_t Notify();
|
||||||
|
virtual Bool_t Process(Long64_t entry);
|
||||||
|
virtual Int_t GetEntry(Long64_t entry, Int_t getall = 0) { return fChain ? fChain->GetTree()->GetEntry(entry, getall) : 0; }
|
||||||
|
virtual void SetOption(const char *option) { fOption = option; }
|
||||||
|
virtual void SetObject(TObject *obj) { fObject = obj; }
|
||||||
|
virtual void SetInputList(TList *input) { fInput = input; }
|
||||||
|
virtual TList *GetOutputList() const { return fOutput; }
|
||||||
|
virtual void SlaveTerminate();
|
||||||
|
virtual void Terminate();
|
||||||
|
|
||||||
|
ClassDef(Analyzer1,0);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef Analyzer1_cxx
|
||||||
|
void Analyzer1::Init(TTree *tree){
|
||||||
|
|
||||||
|
// Set branch addresses and branch pointers
|
||||||
|
if (!tree) return;
|
||||||
|
fChain = tree;
|
||||||
|
fChain->SetMakeClass(1);
|
||||||
|
|
||||||
|
fChain->SetBranchAddress("evID", &evID, &b_eventID);
|
||||||
|
fChain->SetBranchAddress("run", &run, &b_run);
|
||||||
|
|
||||||
|
sx3.SetDetDimension(24,12);
|
||||||
|
qqq.SetDetDimension(4,32);
|
||||||
|
pc.SetDetDimension(2,24);
|
||||||
|
|
||||||
|
fChain->SetBranchAddress("sx3Multi", &sx3.multi, &b_sx3Multi);
|
||||||
|
fChain->SetBranchAddress("sx3ID", &sx3.id, &b_sx3ID);
|
||||||
|
fChain->SetBranchAddress("sx3Ch", &sx3.ch, &b_sx3Ch);
|
||||||
|
fChain->SetBranchAddress("sx3E", &sx3.e, &b_sx3E);
|
||||||
|
fChain->SetBranchAddress("sx3T", &sx3.t, &b_sx3T);
|
||||||
|
fChain->SetBranchAddress("qqqMulti", &qqq.multi, &b_qqqMulti);
|
||||||
|
fChain->SetBranchAddress("qqqID", &qqq.id, &b_qqqID);
|
||||||
|
fChain->SetBranchAddress("qqqCh", &qqq.ch, &b_qqqCh);
|
||||||
|
fChain->SetBranchAddress("qqqE", &qqq.e, &b_qqqE);
|
||||||
|
fChain->SetBranchAddress("qqqT", &qqq.t, &b_qqqT);
|
||||||
|
fChain->SetBranchAddress("pcMulti", &pc.multi, &b_pcMulti);
|
||||||
|
fChain->SetBranchAddress("pcID", &pc.id, &b_pcID);
|
||||||
|
fChain->SetBranchAddress("pcCh", &pc.ch, &b_pcCh);
|
||||||
|
fChain->SetBranchAddress("pcE", &pc.e, &b_pcE);
|
||||||
|
fChain->SetBranchAddress("pcT", &pc.t, &b_pcT);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Bool_t Analyzer1::Notify(){
|
||||||
|
|
||||||
|
return kTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Analyzer1::SlaveBegin(TTree * /*tree*/){
|
||||||
|
|
||||||
|
TString option = GetOption();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Analyzer1::SlaveTerminate(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif // #ifdef Analyzer_cxx
|
||||||
|
|
@ -103,8 +103,8 @@ void ANASEN_model(int anodeID1 = -1, int anodeID2 = -1, int cathodeID1 = -1, int
|
||||||
new TGeoRotation("rot1", 360/nSX3 * (i + 0.5), 0., 0.)));
|
new TGeoRotation("rot1", 360/nSX3 * (i + 0.5), 0., 0.)));
|
||||||
}
|
}
|
||||||
|
|
||||||
const int qqqR1 = 10;
|
const int qqqR1 = 50;
|
||||||
const int qqqR2 = 50;
|
const int qqqR2 = 100;
|
||||||
TGeoVolume *qqq = geom->MakeTubs("qqq", Al, qqqR1, qqqR2, 0.5, 5, 85);
|
TGeoVolume *qqq = geom->MakeTubs("qqq", Al, qqqR1, qqqR2, 0.5, 5, 85);
|
||||||
qqq->SetLineColor(7);
|
qqq->SetLineColor(7);
|
||||||
for( int i = 0; i < 4; i++){
|
for( int i = 0; i < 4; i++){
|
||||||
|
|
|
||||||
121
Armory/Armory/ANASEN_model.C
Normal file
121
Armory/Armory/ANASEN_model.C
Normal file
|
|
@ -0,0 +1,121 @@
|
||||||
|
#include "TGeoManager.h"
|
||||||
|
#include "TGeoVolume.h"
|
||||||
|
#include "TGeoBBox.h"
|
||||||
|
#include "TCanvas.h"
|
||||||
|
#include "TPolyMarker3D.h"
|
||||||
|
#include "TPolyLine3D.h"
|
||||||
|
|
||||||
|
#include "TMath.h"
|
||||||
|
|
||||||
|
void ANASEN_model(int anodeID1 = -1, int anodeID2 = -1, int cathodeID1 = -1, int cathodeID2 = -1 ) {
|
||||||
|
|
||||||
|
// Create ROOT manager and master volume
|
||||||
|
TGeoManager *geom = new TGeoManager("Detector", "ANASEN");
|
||||||
|
|
||||||
|
//--- define some materials
|
||||||
|
TGeoMaterial *matVacuum = new TGeoMaterial("Vacuum", 0,0,0);
|
||||||
|
TGeoMaterial *matAl = new TGeoMaterial("Al", 26.98,13,2.7);
|
||||||
|
//--- define some media
|
||||||
|
TGeoMedium *Vacuum = new TGeoMedium("Vacuum",1, matVacuum);
|
||||||
|
TGeoMedium *Al = new TGeoMedium("Root Material",2, matAl);
|
||||||
|
|
||||||
|
//--- make the top container volume
|
||||||
|
Double_t worldx = 200.; //mm
|
||||||
|
Double_t worldy = 200.; //mm
|
||||||
|
Double_t worldz = 200.; //mm
|
||||||
|
TGeoVolume *worldBox = geom->MakeBox("ROOT", Vacuum, worldx, worldy, worldz);
|
||||||
|
geom->SetTopVolume(worldBox);
|
||||||
|
|
||||||
|
//--- making axis
|
||||||
|
TGeoVolume *axisX = geom->MakeTube("axisX", Al, 0, 0.1, 5.);
|
||||||
|
axisX->SetLineColor(1);
|
||||||
|
worldBox->AddNode(axisX, 1, new TGeoCombiTrans(5, 0, 0., new TGeoRotation("rotA", 90., 90., 0.)));
|
||||||
|
|
||||||
|
TGeoVolume *axisY = geom->MakeTube("axisY", Al, 0, 0.1, 5.);
|
||||||
|
axisY->SetLineColor(1);
|
||||||
|
worldBox->AddNode(axisY, 1, new TGeoCombiTrans(0, 5, 0., new TGeoRotation("rotB", 0., 90., 0.)));
|
||||||
|
|
||||||
|
TGeoVolume *axisZ = geom->MakeTube("axisZ", Al, 0, 0.1, 5.);
|
||||||
|
axisZ->SetLineColor(1);
|
||||||
|
worldBox->AddNode(axisZ, 1, new TGeoTranslation(0, 0, 5));
|
||||||
|
|
||||||
|
//--- making ANASEN
|
||||||
|
const int nWire = 24;
|
||||||
|
const int wireShift = 3;
|
||||||
|
const int zLen = 300; //mm
|
||||||
|
const int radiusA = 38;
|
||||||
|
const int radiusC = 43;
|
||||||
|
|
||||||
|
//.......... convert to wire center dimensions
|
||||||
|
double dAngle = wireShift * TMath::TwoPi() / nWire;
|
||||||
|
double radiusAnew = radiusA * TMath::Cos( dAngle / 2.);
|
||||||
|
double wireALength = TMath::Sqrt( zLen*zLen + TMath::Power(2* radiusA * TMath::Sin(dAngle/2),2) );
|
||||||
|
double wireATheta = TMath::ATan2( 2* radiusA * TMath::Sin( dAngle / 2.), zLen);
|
||||||
|
|
||||||
|
// printf(" dAngle : %f\n", dAngle);
|
||||||
|
// printf(" newRadius : %f\n", radiusAnew);
|
||||||
|
// printf("wireLength : %f\n", wireALength);
|
||||||
|
// printf("wire Theta : %f\n", wireATheta);
|
||||||
|
|
||||||
|
TGeoVolume *pcA = geom->MakeTube("tub1", Al, 0, 0.01, wireALength/2);
|
||||||
|
pcA->SetLineColor(4);
|
||||||
|
|
||||||
|
for( int i = 0; i < nWire; i++){
|
||||||
|
if( anodeID2 >= 0 && (i < anodeID1 || i > anodeID2) ) continue;
|
||||||
|
worldBox->AddNode(pcA, i+1, new TGeoCombiTrans( radiusAnew * TMath::Cos( TMath::TwoPi() / nWire *i + dAngle / 2),
|
||||||
|
radiusAnew * TMath::Sin( TMath::TwoPi() / nWire *i + dAngle / 2),
|
||||||
|
0,
|
||||||
|
new TGeoRotation("rot1", 360/ nWire * (i + wireShift/2.), wireATheta * 180/ TMath::Pi(), 0.)));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
double radiusCnew = radiusC * TMath::Cos( dAngle / 2.);
|
||||||
|
double wireCLength = TMath::Sqrt( zLen*zLen + TMath::Power(2* radiusC * TMath::Sin(dAngle/2),2) );
|
||||||
|
double wireCTheta = TMath::ATan2( 2* radiusC * TMath::Sin( dAngle / 2.), zLen);
|
||||||
|
|
||||||
|
TGeoVolume *pcC = geom->MakeTube("tub2", Al, 0, 0.01, wireCLength/2);
|
||||||
|
pcC->SetLineColor(6);
|
||||||
|
for( int i = 0; i < nWire; i++){
|
||||||
|
if( cathodeID2 >= 0 && (i < cathodeID1 || i > cathodeID2) ) continue;
|
||||||
|
worldBox->AddNode(pcC, i+1, new TGeoCombiTrans( radiusCnew * TMath::Cos( TMath::TwoPi() / nWire *i - dAngle/2),
|
||||||
|
radiusCnew * TMath::Sin( TMath::TwoPi() / nWire *i - dAngle/2),
|
||||||
|
0,
|
||||||
|
new TGeoRotation("rot1", 360/ nWire * (i - wireShift/2.), -wireCTheta * 180/ TMath::Pi(), 0.)));
|
||||||
|
}
|
||||||
|
|
||||||
|
const int nSX3 = 12;
|
||||||
|
const int sx3Radius = 88;
|
||||||
|
const int sx3Width = 40;
|
||||||
|
const int sx3Length = 75;
|
||||||
|
const int sx3Gap = 5;
|
||||||
|
|
||||||
|
TGeoVolume * sx3 = geom->MakeBox("box", Al, 0.1, sx3Width/2, sx3Length/2);
|
||||||
|
sx3->SetLineColor(kGreen+3);
|
||||||
|
for( int i = 0; i < nSX3; i++){
|
||||||
|
worldBox->AddNode(sx3, 2*i+1., new TGeoCombiTrans( sx3Radius * TMath::Cos( TMath::TwoPi() / nSX3 * (i + 0.5)),
|
||||||
|
sx3Radius * TMath::Sin( TMath::TwoPi() / nSX3 * (i + 0.5)),
|
||||||
|
sx3Length/2+sx3Gap,
|
||||||
|
new TGeoRotation("rot1", 360/nSX3 * (i + 0.5), 0., 0.)));
|
||||||
|
|
||||||
|
worldBox->AddNode(sx3, 2*i+2., new TGeoCombiTrans( sx3Radius * TMath::Cos( TMath::TwoPi() / nSX3 * (i + 0.5)),
|
||||||
|
sx3Radius * TMath::Sin( TMath::TwoPi() / nSX3 * (i + 0.5)),
|
||||||
|
-sx3Length/2-sx3Gap,
|
||||||
|
new TGeoRotation("rot1", 360/nSX3 * (i + 0.5), 0., 0.)));
|
||||||
|
}
|
||||||
|
|
||||||
|
const int qqqR1 = 50;
|
||||||
|
const int qqqR2 = 100;
|
||||||
|
TGeoVolume *qqq = geom->MakeTubs("qqq", Al, qqqR1, qqqR2, 0.5, 5, 85);
|
||||||
|
qqq->SetLineColor(7);
|
||||||
|
for( int i = 0; i < 4; i++){
|
||||||
|
worldBox->AddNode(qqq, i+1, new TGeoCombiTrans( 0,
|
||||||
|
0,
|
||||||
|
100,
|
||||||
|
new TGeoRotation("rot1", 360/4 * (i), 0., 0.)));
|
||||||
|
}
|
||||||
|
|
||||||
|
geom->CloseGeometry();
|
||||||
|
|
||||||
|
geom->SetVisLevel(4);
|
||||||
|
worldBox->Draw("ogle");
|
||||||
|
}
|
||||||
314
Armory/Armory/ClassAnasen.h
Normal file
314
Armory/Armory/ClassAnasen.h
Normal file
|
|
@ -0,0 +1,314 @@
|
||||||
|
#ifndef ClassAnasen_h
|
||||||
|
#define ClassAnasen_h
|
||||||
|
|
||||||
|
#include <cstdio>
|
||||||
|
#include <TMath.h>
|
||||||
|
#include <TVector3.h>
|
||||||
|
|
||||||
|
#include "TGeoManager.h"
|
||||||
|
#include "TGeoVolume.h"
|
||||||
|
#include "TGeoBBox.h"
|
||||||
|
#include "TCanvas.h"
|
||||||
|
#include "TPolyMarker3D.h"
|
||||||
|
#include "TPolyLine3D.h"
|
||||||
|
#include "TRandom.h"
|
||||||
|
|
||||||
|
#include "ClassSX3.h"
|
||||||
|
#include "ClassPW.h"
|
||||||
|
|
||||||
|
class ANASEN{
|
||||||
|
public:
|
||||||
|
ANASEN();
|
||||||
|
~ANASEN();
|
||||||
|
|
||||||
|
void SetUncertainties(double sx3W, double sx3L, double anode, double cathode){
|
||||||
|
sigmaA = anode;
|
||||||
|
sigmaC = cathode;
|
||||||
|
sigmaW = sx3W;
|
||||||
|
sigmaL = sx3L;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawTrack(TVector3 pos, TVector3 direction, bool drawEstimatedTrack = false);
|
||||||
|
void DrawDeducedTrack(TVector3 sx3Pos, int anodeID, int cathodeID);
|
||||||
|
void DrawAnasen(int anodeID1 = -1,
|
||||||
|
int anodeID2 = -1,
|
||||||
|
int cathodeID1 = -1,
|
||||||
|
int cathodeID2 = -1,
|
||||||
|
int sx3ID = -1,
|
||||||
|
bool DrawQQQ = false );
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
PW * GetPW() {return pw;}
|
||||||
|
SX3 * GetSX3() {return sx3;}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
PW * pw;
|
||||||
|
SX3 * sx3;
|
||||||
|
|
||||||
|
double sigmaA, sigmaC; // pw
|
||||||
|
double sigmaW, sigmaL; // sx3
|
||||||
|
|
||||||
|
const float qqqR1 = 50;
|
||||||
|
const float qqqR2 = 100;
|
||||||
|
const float qqqZPos = 23 + 75 + 30;
|
||||||
|
|
||||||
|
void CalGeometry();
|
||||||
|
|
||||||
|
TGeoManager *geom;
|
||||||
|
TGeoVolume *worldBox;
|
||||||
|
|
||||||
|
void Construct3DModel(int anodeID1 = -1,
|
||||||
|
int anodeID2 = -1,
|
||||||
|
int cathodeID1 = -1,
|
||||||
|
int cathodeID2 = -1,
|
||||||
|
int sx3ID = -1,
|
||||||
|
bool DrawQQQ = true);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
//!==============================================
|
||||||
|
inline ANASEN::ANASEN(){
|
||||||
|
|
||||||
|
pw = new PW();
|
||||||
|
sx3 = new SX3();
|
||||||
|
|
||||||
|
CalGeometry();
|
||||||
|
|
||||||
|
geom = nullptr;
|
||||||
|
worldBox = nullptr;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
inline ANASEN::~ANASEN(){
|
||||||
|
|
||||||
|
delete geom;
|
||||||
|
|
||||||
|
delete pw;
|
||||||
|
delete sx3;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//!==============================================
|
||||||
|
inline void ANASEN::CalGeometry(){
|
||||||
|
|
||||||
|
sx3->ConstructGeo();
|
||||||
|
pw->ConstructGeo();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void ANASEN::Construct3DModel(int anodeID1, int anodeID2, int cathodeID1, int cathodeID2, int sx3ID, bool DrawQQQ ){
|
||||||
|
|
||||||
|
if( geom ) delete geom;
|
||||||
|
|
||||||
|
// Create ROOT manager and master volume
|
||||||
|
geom = new TGeoManager("Detector", "ANASEN");
|
||||||
|
|
||||||
|
//--- define some materials
|
||||||
|
TGeoMaterial *matVacuum = new TGeoMaterial("Vacuum", 0,0,0);
|
||||||
|
TGeoMaterial *matAl = new TGeoMaterial("Al", 26.98,13,2.7);
|
||||||
|
//--- define some media
|
||||||
|
TGeoMedium *Vacuum = new TGeoMedium("Vacuum",1, matVacuum);
|
||||||
|
TGeoMedium *Al = new TGeoMedium("Root Material",2, matAl);
|
||||||
|
|
||||||
|
//--- make the top container volume
|
||||||
|
Double_t worldx = 200.; //mm
|
||||||
|
Double_t worldy = 200.; //mm
|
||||||
|
Double_t worldz = 200.; //mm
|
||||||
|
worldBox = geom->MakeBox("ROOT", Vacuum, worldx, worldy, worldz);
|
||||||
|
geom->SetTopVolume(worldBox);
|
||||||
|
|
||||||
|
//--- making axis
|
||||||
|
TGeoVolume *axisX = geom->MakeTube("axisX", Al, 0, 0.1, 5.);
|
||||||
|
axisX->SetLineColor(1);
|
||||||
|
worldBox->AddNode(axisX, 1, new TGeoCombiTrans(5, 0, 0., new TGeoRotation("rotA", 90., 90., 0.)));
|
||||||
|
TGeoVolume *axisY = geom->MakeTube("axisY", Al, 0, 0.1, 5.);
|
||||||
|
axisY->SetLineColor(1);
|
||||||
|
worldBox->AddNode(axisY, 1, new TGeoCombiTrans(0, 5, 0., new TGeoRotation("rotB", 0., 90., 0.)));
|
||||||
|
TGeoVolume *axisZ = geom->MakeTube("axisZ", Al, 0, 0.1, 5.);
|
||||||
|
axisZ->SetLineColor(1);
|
||||||
|
worldBox->AddNode(axisZ, 1, new TGeoTranslation(0, 0, 5));
|
||||||
|
|
||||||
|
//.......... convert to wire center dimensions
|
||||||
|
TGeoVolume *pcA = geom->MakeTube("tub1", Al, 0, 0.01, pw->GetAnodeLength()/2);
|
||||||
|
pcA->SetLineColor(4);
|
||||||
|
|
||||||
|
int startID = 0;
|
||||||
|
int endID = pw->GetNumWire() - 1;
|
||||||
|
|
||||||
|
if( anodeID1 >= 0 && anodeID2 >= 0 ){
|
||||||
|
startID = anodeID1;
|
||||||
|
endID = anodeID2;
|
||||||
|
if( anodeID1 > anodeID2 ) {
|
||||||
|
endID = pw->GetNumWire() + anodeID2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for( int i = startID; i <= endID; i++){
|
||||||
|
TVector3 a = pw->GetAnodneMid(i);
|
||||||
|
double wireTheta = pw->GetAnodeTheta(i) * TMath::RadToDeg();
|
||||||
|
double wirePhi = pw->GetAnodePhi(i) * TMath::RadToDeg() + 90;
|
||||||
|
|
||||||
|
worldBox->AddNode(pcA, i+1, new TGeoCombiTrans( a.X(),
|
||||||
|
a.Y(),
|
||||||
|
a.Z(),
|
||||||
|
new TGeoRotation("rot1", wirePhi, wireTheta, 0.)));
|
||||||
|
}
|
||||||
|
|
||||||
|
TGeoVolume *pcC = geom->MakeTube("tub2", Al, 0, 0.01, pw->GetCathodeLength()/2);
|
||||||
|
pcC->SetLineColor(6);
|
||||||
|
|
||||||
|
startID = 0;
|
||||||
|
endID = pw->GetNumWire() - 1;
|
||||||
|
|
||||||
|
if( cathodeID1 >= 0 && cathodeID2 >= 0 ){
|
||||||
|
startID = cathodeID1;
|
||||||
|
endID = cathodeID2;
|
||||||
|
if( cathodeID1 > cathodeID2 ) {
|
||||||
|
endID = pw->GetNumWire() + cathodeID2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for( int i = startID; i <= endID; i++){
|
||||||
|
TVector3 a = pw->GetCathodneMid(i);
|
||||||
|
double wireTheta = pw->GetCathodeTheta(i) * TMath::RadToDeg();
|
||||||
|
double wirePhi = pw->GetCathodePhi(i) * TMath::RadToDeg() + 90;
|
||||||
|
|
||||||
|
worldBox->AddNode(pcC, i+1, new TGeoCombiTrans( a.X(),
|
||||||
|
a.Y(),
|
||||||
|
a.Z(),
|
||||||
|
new TGeoRotation("rot1", wirePhi , wireTheta, 0.)));
|
||||||
|
}
|
||||||
|
|
||||||
|
TGeoVolume * sx3Det = geom->MakeBox("box", Al, 0.1, sx3->GetWidth()/2, sx3->GetLength()/2);
|
||||||
|
sx3Det->SetLineColor(kGreen+3);
|
||||||
|
|
||||||
|
for( int i = 0; i < sx3->GetNumDet(); i++){
|
||||||
|
if( sx3ID != -1 && i != sx3ID ) continue;
|
||||||
|
TVector3 aUp = sx3->GetUpMid(i); // center of the SX3 upstream
|
||||||
|
TVector3 aDn = sx3->GetDnMid(i); // center of the SX3 Downstream
|
||||||
|
double phi = sx3->GetDetPhi(i) * TMath::RadToDeg() + 90;
|
||||||
|
|
||||||
|
worldBox->AddNode(sx3Det, 2*i+1., new TGeoCombiTrans( aUp.X(),
|
||||||
|
aUp.Y(),
|
||||||
|
aUp.Z(),
|
||||||
|
new TGeoRotation("rot1", phi, 0., 0.)));
|
||||||
|
worldBox->AddNode(sx3Det, 2*i+1., new TGeoCombiTrans( aDn.X(),
|
||||||
|
aDn.Y(),
|
||||||
|
aDn.Z(),
|
||||||
|
new TGeoRotation("rot1", phi, 0., 0.)));
|
||||||
|
}
|
||||||
|
|
||||||
|
if( DrawQQQ ){
|
||||||
|
TGeoVolume *qqq = geom->MakeTubs("qqq", Al, qqqR1, qqqR2, 0.5, 5, 85);
|
||||||
|
qqq->SetLineColor(7);
|
||||||
|
for( int i = 0; i < 4; i++){
|
||||||
|
worldBox->AddNode(qqq, i+1, new TGeoCombiTrans( 0,
|
||||||
|
0,
|
||||||
|
qqqZPos,
|
||||||
|
new TGeoRotation("rot1", 360/4 * (i), 0., 0.)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//!============================================== Drawing functions
|
||||||
|
inline void ANASEN::DrawAnasen(int anodeID1, int anodeID2, int cathodeID1, int cathodeID2, int sx3ID, bool DrawQQQ ){
|
||||||
|
|
||||||
|
Construct3DModel(anodeID1, anodeID2, cathodeID1, cathodeID2, sx3ID, DrawQQQ);
|
||||||
|
|
||||||
|
geom->CloseGeometry();
|
||||||
|
geom->SetVisLevel(4);
|
||||||
|
worldBox->Draw("ogle");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void ANASEN::DrawTrack(TVector3 pos, TVector3 direction, bool drawEstimatedTrack){
|
||||||
|
|
||||||
|
pw->FindWireID(pos, direction);
|
||||||
|
sx3->FindSX3Pos(pos, direction);
|
||||||
|
|
||||||
|
std::pair<short, short> wireID = pw->GetNearestID();
|
||||||
|
|
||||||
|
Construct3DModel(wireID.first, wireID.first, wireID.second, wireID.second, -1, false);
|
||||||
|
|
||||||
|
double theta = direction.Theta() * TMath::RadToDeg();
|
||||||
|
double phi = direction.Phi() * TMath::RadToDeg();
|
||||||
|
// printf("Theta, Phi = %.2f %.2f \n", theta, phi);
|
||||||
|
// pos.Print();
|
||||||
|
TGeoVolume * Track = geom->MakeTube("track", 0, 0, 0.1, 150.);
|
||||||
|
Track->SetLineColor(kRed);
|
||||||
|
worldBox->AddNode(Track, 1, new TGeoCombiTrans( pos.X(), pos.Y(), pos.Z(), new TGeoRotation("rotA", phi + 90, theta, 0.)));
|
||||||
|
|
||||||
|
TGeoVolume * startPos = geom->MakeSphere("startPos", 0, 0, 3);
|
||||||
|
startPos->SetLineColor(kBlack);
|
||||||
|
worldBox->AddNode(startPos, 3, new TGeoCombiTrans( pos.X(), pos.Y(), pos.Z(), new TGeoRotation("rotA", 0, 0, 0.)));
|
||||||
|
|
||||||
|
if( sx3->GetID() >= 0 ){
|
||||||
|
//TVector3 hitPos = sx3->GetHitPos();
|
||||||
|
TVector3 hitPos = sx3->GetHitPosWithSigma(sigmaW, sigmaL);
|
||||||
|
|
||||||
|
TGeoVolume * hit = geom->MakeSphere("hitpos", 0, 0, 3);
|
||||||
|
hit->SetLineColor(kRed);
|
||||||
|
worldBox->AddNode(hit, 2, new TGeoCombiTrans( hitPos.X(), hitPos.Y(), hitPos.Z(), new TGeoRotation("rotA", 0, 0, 0.)));
|
||||||
|
|
||||||
|
if( drawEstimatedTrack ){
|
||||||
|
|
||||||
|
{//===== simple
|
||||||
|
pw->CalTrack(hitPos, wireID.first, wireID.second, true);
|
||||||
|
|
||||||
|
double thetaDeduce = pw->GetTrackTheta() * TMath::RadToDeg();
|
||||||
|
double phiDeduce = pw->GetTrackPhi() * TMath::RadToDeg();
|
||||||
|
|
||||||
|
TGeoVolume * trackDeduce = geom->MakeTube("trackDeduce", 0, 0, 0.1, 100.);
|
||||||
|
trackDeduce->SetLineColor(kOrange);
|
||||||
|
worldBox->AddNode(trackDeduce, 1, new TGeoCombiTrans( hitPos.X(), hitPos.Y(), hitPos.Z(), new TGeoRotation("rotA", phiDeduce + 90, thetaDeduce, 0.)));
|
||||||
|
}
|
||||||
|
|
||||||
|
{//===== complicated
|
||||||
|
PWHitInfo hitInfo = pw->GetHitInfo();
|
||||||
|
pw->CalTrack2(hitPos, hitInfo, sigmaA, sigmaC, true);
|
||||||
|
|
||||||
|
double thetaDeduce = pw->GetTrackTheta() * TMath::RadToDeg();
|
||||||
|
double phiDeduce = pw->GetTrackPhi() * TMath::RadToDeg();
|
||||||
|
|
||||||
|
TGeoVolume * trackDeduce2 = geom->MakeTube("trackDeduce2", 0, 0, 0.1, 100.);
|
||||||
|
trackDeduce2->SetLineColor(kGreen);
|
||||||
|
worldBox->AddNode(trackDeduce2, 1, new TGeoCombiTrans( hitPos.X(), hitPos.Y(), hitPos.Z(), new TGeoRotation("rotA", phiDeduce + 90, thetaDeduce, 0.)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
geom->CloseGeometry();
|
||||||
|
geom->SetVisLevel(4);
|
||||||
|
worldBox->Draw("ogle");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void ANASEN::DrawDeducedTrack(TVector3 sx3Pos, int anodeID, int cathodeID){
|
||||||
|
|
||||||
|
pw->CalTrack(sx3Pos, anodeID, cathodeID);
|
||||||
|
|
||||||
|
Construct3DModel(anodeID, anodeID, cathodeID, cathodeID, -1, false);
|
||||||
|
|
||||||
|
double theta = pw->GetTrackTheta() * TMath::RadToDeg();
|
||||||
|
double phi = pw->GetTrackPhi() * TMath::RadToDeg();
|
||||||
|
|
||||||
|
TGeoVolume * Track = geom->MakeTube("axisX", 0, 0, 0.1, 100.);
|
||||||
|
Track->SetLineColor(kRed);
|
||||||
|
worldBox->AddNode(Track, 1, new TGeoCombiTrans( sx3Pos.X(), sx3Pos.Y(), sx3Pos.Z(), new TGeoRotation("rotA", phi + 90, theta, 0.)));
|
||||||
|
|
||||||
|
TGeoVolume * hit = geom->MakeSphere("hitpos", 0, 0, 3);
|
||||||
|
hit->SetLineColor(kRed);
|
||||||
|
worldBox->AddNode(hit, 2, new TGeoCombiTrans( sx3Pos.X(), sx3Pos.Y(), sx3Pos.Z(), new TGeoRotation("rotA", 0, 0, 0.)));
|
||||||
|
|
||||||
|
geom->CloseGeometry();
|
||||||
|
geom->SetVisLevel(4);
|
||||||
|
worldBox->Draw("ogle");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
66
Armory/Armory/ClassDet.h
Normal file
66
Armory/Armory/ClassDet.h
Normal file
|
|
@ -0,0 +1,66 @@
|
||||||
|
#ifndef ClassDet_h
|
||||||
|
#define ClassDet_h
|
||||||
|
|
||||||
|
#include <cstdio>
|
||||||
|
|
||||||
|
#define MAXMULTI 1000
|
||||||
|
|
||||||
|
class Det{
|
||||||
|
public:
|
||||||
|
Det(): multi(0) {Clear(); }
|
||||||
|
|
||||||
|
unsigned short multi; // max 65535
|
||||||
|
unsigned short id[MAXMULTI];
|
||||||
|
unsigned short ch[MAXMULTI];
|
||||||
|
unsigned short e[MAXMULTI];
|
||||||
|
unsigned long long t[MAXMULTI];
|
||||||
|
unsigned long long tf[MAXMULTI];
|
||||||
|
|
||||||
|
unsigned short sn[MAXMULTI];
|
||||||
|
unsigned short digiCh[MAXMULTI];
|
||||||
|
|
||||||
|
unsigned short index[MAXMULTI]; // id * nCh + ch;
|
||||||
|
bool used[MAXMULTI];
|
||||||
|
|
||||||
|
void Clear(){
|
||||||
|
multi = 0;
|
||||||
|
for( int i = 0; i < MAXMULTI; i++){
|
||||||
|
id[i] = 0;
|
||||||
|
ch[i] = 0;
|
||||||
|
e[i] = 0;
|
||||||
|
t[i] = 0;
|
||||||
|
tf[i] = 0;
|
||||||
|
index[i] = 0;
|
||||||
|
sn[i] = 0;
|
||||||
|
digiCh[i] = 0;
|
||||||
|
used[i] = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Print(){
|
||||||
|
printf("=============================== multi : %u\n", multi);
|
||||||
|
for( int i = 0; i < multi; i++) {
|
||||||
|
printf(" %3d | %2d-%-2d(%5d) %5u %15llu %15llu\n", i, id[i], ch[i], index[i], e[i], t[i], tf[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetDetDimension(unsigned short maxID, unsigned maxCh){
|
||||||
|
nID = maxID;
|
||||||
|
nCh = maxCh;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CalIndex(){
|
||||||
|
for( int i = 0; i < multi; i++){
|
||||||
|
index[i] = id[i] * nCh + ch[i] ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
unsigned short nID;
|
||||||
|
unsigned short nCh;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
246
Armory/Armory/ClassPC1An.h
Normal file
246
Armory/Armory/ClassPC1An.h
Normal file
|
|
@ -0,0 +1,246 @@
|
||||||
|
#ifndef ClassPC_h
|
||||||
|
#define ClassPC_h
|
||||||
|
|
||||||
|
#include <cstdio>
|
||||||
|
#include <TMath.h>
|
||||||
|
#include <TVector3.h>
|
||||||
|
#include <TRandom.h>
|
||||||
|
|
||||||
|
struct PCHit_1An{
|
||||||
|
std::pair<short, short> nearestWire; // anode, cathode
|
||||||
|
std::pair<double, double> nearestDist; // anode, cathode
|
||||||
|
|
||||||
|
short nextNearestWire; // cathode
|
||||||
|
double nextNearestDist; // cathode
|
||||||
|
|
||||||
|
void Clear(){
|
||||||
|
nearestWire.first = -1;
|
||||||
|
nearestWire.second = -1;
|
||||||
|
nearestDist.first = 999999999;
|
||||||
|
nearestDist.second = 999999999;
|
||||||
|
nextNearestWire= -1;
|
||||||
|
nextNearestDist = 999999999;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//!########################################################
|
||||||
|
class PC{ // proportional wire
|
||||||
|
public:
|
||||||
|
PC(){ ClearHitInfo();};
|
||||||
|
~PC(){};
|
||||||
|
|
||||||
|
PCHit_1An GetHitInfo() const {return hitInfo;}
|
||||||
|
std::pair<short, short> GetNearestID() const {return hitInfo.nearestWire;}
|
||||||
|
std::pair<double, double> GetNearestDistance() const {return hitInfo.nearestDist;}
|
||||||
|
short Get2ndNearestID() const {return hitInfo.nextNearestWire;}
|
||||||
|
double Get2ndNearestDistance() const {return hitInfo.nextNearestDist;}
|
||||||
|
|
||||||
|
TVector3 GetTrackPos() const {return trackPos;}
|
||||||
|
TVector3 GetTrackVec() const {return trackVec;}
|
||||||
|
double GetTrackTheta() const {return trackVec.Theta();}
|
||||||
|
double GetTrackPhi() const {return trackVec.Phi();}
|
||||||
|
double GetZ0();
|
||||||
|
|
||||||
|
int GetNumWire() const {return nWire;}
|
||||||
|
double GetDeltaAngle() const {return dAngle;}
|
||||||
|
double GetAnodeLength() const {return anodeLength;}
|
||||||
|
double GetCathodeLength() const {return cathodeLength;}
|
||||||
|
TVector3 GetAnodeDn(short id) const {return An[id].first;}
|
||||||
|
TVector3 GetAnodeUp(short id) const {return An[id].second;}
|
||||||
|
TVector3 GetCathodeDn(short id) const {return Ca[id].first;}
|
||||||
|
TVector3 GetCathodeUp(short id) const {return Ca[id].second;}
|
||||||
|
|
||||||
|
TVector3 GetAnodneMid(short id) const {return (An[id].first + An[id].second) * 0.5; }
|
||||||
|
double GetAnodeTheta(short id) const {return (An[id].first - An[id].second).Theta();}
|
||||||
|
double GetAnodePhi(short id) const {return (An[id].first - An[id].second).Phi();}
|
||||||
|
|
||||||
|
TVector3 GetCathodneMid(short id) const {return (Ca[id].first + Ca[id].second) * 0.5; }
|
||||||
|
double GetCathodeTheta(short id) const {return (Ca[id].first - Ca[id].second).Theta();}
|
||||||
|
double GetCathodePhi(short id) const {return (Ca[id].first - Ca[id].second).Phi();}
|
||||||
|
|
||||||
|
void ClearHitInfo();
|
||||||
|
void ConstructGeo();
|
||||||
|
void FindWireID(TVector3 pos, TVector3 direction, bool verbose = false);
|
||||||
|
void CalTrack3(TVector3 sx3Pos, PCHit_1An hitInfo, double sigmaA = 0, double sigmaC = 0, bool verbose = false);
|
||||||
|
|
||||||
|
void Print(){
|
||||||
|
printf(" The nearest | Anode: %2d(%5.2f) Cathode: %2d(%5.2f)\n", hitInfo.nearestWire.first,
|
||||||
|
hitInfo.nearestDist.first,
|
||||||
|
hitInfo.nearestWire.second,
|
||||||
|
hitInfo.nearestDist.second);
|
||||||
|
|
||||||
|
printf(" The 2nd nearest Cathode: %2d(%5.2f)\n", hitInfo.nextNearestWire,
|
||||||
|
hitInfo.nextNearestDist);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
// PCHitInfo hitInfo;
|
||||||
|
PCHit_1An hitInfo;
|
||||||
|
|
||||||
|
TVector3 trackPos;
|
||||||
|
TVector3 trackVec;
|
||||||
|
|
||||||
|
const int nWire = 24;
|
||||||
|
const int wireShift = 3;
|
||||||
|
const float zLen = 380; //mm
|
||||||
|
const float radiusA = 37;
|
||||||
|
const float radiusC = 43;
|
||||||
|
|
||||||
|
double dAngle;
|
||||||
|
double anodeLength;
|
||||||
|
double cathodeLength;
|
||||||
|
|
||||||
|
std::vector<std::pair<TVector3,TVector3>> An; // the anode wire position vector in space
|
||||||
|
std::vector<std::pair<TVector3,TVector3>> Ca; // the cathode wire position vector in space
|
||||||
|
|
||||||
|
double Distance(TVector3 a1, TVector3 a2, TVector3 b1, TVector3 b2){
|
||||||
|
TVector3 na = a1 - a2;
|
||||||
|
TVector3 nb = b1 - b2;
|
||||||
|
TVector3 nd = (na.Cross(nb)).Unit();
|
||||||
|
return TMath::Abs(nd.Dot(a1-b2));
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
inline void PC::ClearHitInfo(){
|
||||||
|
hitInfo.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void PC::ConstructGeo(){
|
||||||
|
|
||||||
|
An.clear();
|
||||||
|
Ca.clear();
|
||||||
|
|
||||||
|
std::pair<TVector3, TVector3> p1; // anode
|
||||||
|
std::pair<TVector3, TVector3> q1; // cathode
|
||||||
|
|
||||||
|
//anode and cathode start at pos-Y axis and count in right-Hand
|
||||||
|
//anode wire shift is right-hand.
|
||||||
|
//cathode wire shift is left-hand.
|
||||||
|
|
||||||
|
for(int i = 0; i < nWire; i++ ){
|
||||||
|
// Anode rotate right-hand
|
||||||
|
p1.first.SetXYZ( radiusA * TMath::Cos( TMath::TwoPi() / nWire * (i) + TMath::PiOver2()),
|
||||||
|
radiusA * TMath::Sin( TMath::TwoPi() / nWire * (i) + TMath::PiOver2()),
|
||||||
|
zLen/2);
|
||||||
|
p1.second.SetXYZ( radiusA * TMath::Cos( TMath::TwoPi() / nWire * (i + wireShift) + TMath::PiOver2()),
|
||||||
|
radiusA * TMath::Sin( TMath::TwoPi() / nWire * (i + wireShift) + TMath::PiOver2()),
|
||||||
|
-zLen/2);
|
||||||
|
An.push_back(p1);
|
||||||
|
|
||||||
|
// Cathod rotate left-hand
|
||||||
|
q1.first.SetXYZ( radiusC * TMath::Cos( TMath::TwoPi() / nWire * (i) + TMath::PiOver2()),
|
||||||
|
radiusC * TMath::Sin( TMath::TwoPi() / nWire * (i) + TMath::PiOver2()),
|
||||||
|
zLen/2);
|
||||||
|
q1.second.SetXYZ( radiusC * TMath::Cos( TMath::TwoPi() / nWire * (i - wireShift) + TMath::PiOver2()),
|
||||||
|
radiusC * TMath::Sin( TMath::TwoPi() / nWire * (i - wireShift) + TMath::PiOver2()),
|
||||||
|
-zLen/2);
|
||||||
|
Ca.push_back(q1);
|
||||||
|
}
|
||||||
|
|
||||||
|
dAngle = wireShift * TMath::TwoPi() / nWire;
|
||||||
|
anodeLength = TMath::Sqrt( zLen*zLen + TMath::Power(2* radiusA * TMath::Sin(dAngle/2),2) );
|
||||||
|
cathodeLength = TMath::Sqrt( zLen*zLen + TMath::Power(2* radiusC * TMath::Sin(dAngle/2),2) );
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void PC::FindWireID(TVector3 pos, TVector3 direction, bool verbose ){
|
||||||
|
|
||||||
|
hitInfo.Clear();
|
||||||
|
double phi = direction.Phi();
|
||||||
|
|
||||||
|
for( int i = 0; i < nWire; i++){
|
||||||
|
|
||||||
|
double disA = 99999999;
|
||||||
|
double phiS = An[i].first.Phi() - TMath::PiOver4();
|
||||||
|
double phiL = An[i].second.Phi() + TMath::PiOver4();
|
||||||
|
// printf("A%2d: %f %f | %f\n", i, phiS * TMath::RadToDeg(), phiL * TMath::RadToDeg(), phi * TMath::RadToDeg());
|
||||||
|
if( phi > 0 && phiS > phiL ) phiL = phiL + TMath::TwoPi();
|
||||||
|
if( phi < 0 && phiS > phiL ) phiS = phiS - TMath::TwoPi();
|
||||||
|
|
||||||
|
if( phiS < phi && phi < phiL) {
|
||||||
|
disA = Distance( pos, pos + direction, An[i].first, An[i].second);
|
||||||
|
if( disA < hitInfo.nearestDist.first ){
|
||||||
|
hitInfo.nearestDist.first = disA;
|
||||||
|
hitInfo.nearestWire.first = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
double disC = 99999999;
|
||||||
|
phiS = Ca[i].second.Phi()- TMath::PiOver4();
|
||||||
|
phiL = Ca[i].first.Phi() + TMath::PiOver4();
|
||||||
|
// printf("C%2d: %f %f\n", i, phiS * TMath::RadToDeg(), phiL * TMath::RadToDeg());
|
||||||
|
if( phi > 0 && phiS > phiL ) phiL = phiL + TMath::TwoPi();
|
||||||
|
if( phi < 0 && phiS > phiL ) phiS = phiS - TMath::TwoPi();
|
||||||
|
|
||||||
|
if(phiS < phi && phi < phiL) {
|
||||||
|
disC = Distance( pos, pos + direction, Ca[i].first, Ca[i].second);
|
||||||
|
if( disC < hitInfo.nearestDist.second ){
|
||||||
|
hitInfo.nearestDist.second = disC;
|
||||||
|
hitInfo.nearestWire.second = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(verbose) printf(" %2d | %8.2f, %8.2f\n", i, disA, disC);
|
||||||
|
}
|
||||||
|
|
||||||
|
short cathode1 = hitInfo.nearestWire.second;
|
||||||
|
short ccc1 = cathode1 - 1; if( ccc1 < 0 ) ccc1 += nWire;
|
||||||
|
short ccc2 = (cathode1 + 1) % nWire;
|
||||||
|
|
||||||
|
double haha1 = Distance( pos, pos + direction, Ca[ccc1].first, Ca[ccc1].second);
|
||||||
|
double haha2 = Distance( pos, pos + direction, Ca[ccc2].first, Ca[ccc2].second);
|
||||||
|
if( haha1 < haha2){
|
||||||
|
hitInfo.nextNearestWire = ccc1;
|
||||||
|
hitInfo.nextNearestDist = haha1;
|
||||||
|
}else{
|
||||||
|
hitInfo.nextNearestWire = ccc2;
|
||||||
|
hitInfo.nextNearestDist= haha2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( verbose ) Print();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void PC::CalTrack3(TVector3 sx3Pos, PCHit_1An hitInfo, double sigmaA, double sigmaC, bool verbose){
|
||||||
|
|
||||||
|
trackPos = sx3Pos;
|
||||||
|
|
||||||
|
double p1 = TMath::Abs(hitInfo.nearestDist.first + gRandom->Gaus(0, sigmaA));
|
||||||
|
short anodeID1 = hitInfo.nearestWire.first;
|
||||||
|
|
||||||
|
double q1 = TMath::Abs(hitInfo.nearestDist.second + gRandom->Gaus(0, sigmaC));
|
||||||
|
double q2 = TMath::Abs(hitInfo.nextNearestDist+ gRandom->Gaus(0, sigmaC));
|
||||||
|
double fracC = q1 / (q1 + q2);
|
||||||
|
short cathodeID1 = hitInfo.nearestWire.second;
|
||||||
|
short cathodeID2 = hitInfo.nextNearestWire;
|
||||||
|
TVector3 shiftC1 = (Ca[cathodeID2].first - Ca[cathodeID1].first) * fracC;
|
||||||
|
TVector3 shiftC2 = (Ca[cathodeID2].second - Ca[cathodeID1].second) * fracC;
|
||||||
|
|
||||||
|
TVector3 a1 = An[anodeID1].first;
|
||||||
|
|
||||||
|
TVector3 c1 = Ca[cathodeID1].first + shiftC1;
|
||||||
|
TVector3 c2 = Ca[cathodeID1].second + shiftC2;
|
||||||
|
|
||||||
|
TVector3 n1 = (sx3Pos - a1).Unit();
|
||||||
|
TVector3 n2 = (c1 - c2).Cross((sx3Pos - c2)).Unit();
|
||||||
|
|
||||||
|
// if the handiness of anode and cathode revered, it should be n2 cross n1
|
||||||
|
trackVec = (n2.Cross(n1)).Unit();
|
||||||
|
|
||||||
|
if( verbose ) printf("Theta, Phi = %f, %f \n", trackVec.Theta() *TMath::RadToDeg(), trackVec.Phi()*TMath::RadToDeg());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
inline double PC::GetZ0(){
|
||||||
|
|
||||||
|
double x = trackPos.X();
|
||||||
|
double y = trackPos.Y();
|
||||||
|
double rho = TMath::Sqrt(x*x + y*y);
|
||||||
|
double theta = trackVec.Theta();
|
||||||
|
|
||||||
|
return trackPos.Z() - rho / TMath::Tan(theta);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
315
Armory/Armory/ClassPW.h
Normal file
315
Armory/Armory/ClassPW.h
Normal file
|
|
@ -0,0 +1,315 @@
|
||||||
|
#ifndef ClassPW_h
|
||||||
|
#define ClassPW_h
|
||||||
|
|
||||||
|
#include <cstdio>
|
||||||
|
#include <TMath.h>
|
||||||
|
#include <TVector3.h>
|
||||||
|
#include <TRandom.h>
|
||||||
|
|
||||||
|
struct PWHitInfo
|
||||||
|
{
|
||||||
|
std::pair<short, short> nearestWire; // anode, cathode
|
||||||
|
std::pair<double, double> nearestDist; // anode, cathode
|
||||||
|
|
||||||
|
std::pair<short, short> nextNearestWire; // anode, cathode
|
||||||
|
std::pair<double, double> nextNearestDist; // anode, cathode
|
||||||
|
|
||||||
|
void Clear()
|
||||||
|
{
|
||||||
|
nearestWire.first = -1;
|
||||||
|
nearestWire.second = -1;
|
||||||
|
nearestDist.first = 999999999;
|
||||||
|
nearestDist.second = 999999999;
|
||||||
|
nextNearestWire.first = -1;
|
||||||
|
nextNearestWire.second = -1;
|
||||||
|
nextNearestDist.first = 999999999;
|
||||||
|
nextNearestDist.second = 999999999;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Coord
|
||||||
|
{
|
||||||
|
float x, y, z;
|
||||||
|
Coord() : x(0), y(0), z(0) {}
|
||||||
|
Coord(const TVector3 &vec)
|
||||||
|
{
|
||||||
|
x = vec.X(); // TVector3's X() returns the x-coordinate
|
||||||
|
y = vec.Y(); // TVector3's Y() returns the y-coordinate
|
||||||
|
z = vec.Z(); // TVector3's Z() returns the z-coordinate
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//! ########################################################
|
||||||
|
class PW
|
||||||
|
{ // proportional wire
|
||||||
|
public:
|
||||||
|
PW() { ClearHitInfo(); };
|
||||||
|
~PW() {};
|
||||||
|
|
||||||
|
PWHitInfo GetHitInfo() const { return hitInfo; }
|
||||||
|
std::pair<short, short> GetNearestID() const { return hitInfo.nearestWire; }
|
||||||
|
std::pair<double, double> GetNearestDistance() const { return hitInfo.nearestDist; }
|
||||||
|
std::pair<short, short> Get2ndNearestID() const { return hitInfo.nextNearestWire; }
|
||||||
|
std::pair<double, double> Get2ndNearestDistance() const { return hitInfo.nextNearestDist; }
|
||||||
|
|
||||||
|
std::vector<std::pair<TVector3, TVector3>> An; // the anode wire position vector in space
|
||||||
|
std::vector<std::pair<TVector3, TVector3>> Ca; // the cathode wire position vector in space
|
||||||
|
|
||||||
|
TVector3 GetTrackPos() const { return trackPos; }
|
||||||
|
TVector3 GetTrackVec() const { return trackVec; }
|
||||||
|
double GetTrackTheta() const { return trackVec.Theta(); }
|
||||||
|
double GetTrackPhi() const { return trackVec.Phi(); }
|
||||||
|
double GetZ0();
|
||||||
|
|
||||||
|
int GetNumWire() const { return nWire; }
|
||||||
|
double GetDeltaAngle() const { return dAngle; }
|
||||||
|
double GetAnodeLength() const { return anodeLength; }
|
||||||
|
double GetCathodeLength() const { return cathodeLength; }
|
||||||
|
TVector3 GetAnodeDn(short id) const { return An[id].first; }
|
||||||
|
TVector3 GetAnodeUp(short id) const { return An[id].second; }
|
||||||
|
TVector3 GetCathodeDn(short id) const { return Ca[id].first; }
|
||||||
|
TVector3 GetCathodeUp(short id) const { return Ca[id].second; }
|
||||||
|
|
||||||
|
TVector3 GetAnodneMid(short id) const { return (An[id].first + An[id].second) * 0.5; }
|
||||||
|
double GetAnodeTheta(short id) const { return (An[id].first - An[id].second).Theta(); }
|
||||||
|
double GetAnodePhi(short id) const { return (An[id].first - An[id].second).Phi(); }
|
||||||
|
|
||||||
|
TVector3 GetCathodneMid(short id) const { return (Ca[id].first + Ca[id].second) * 0.5; }
|
||||||
|
double GetCathodeTheta(short id) const { return (Ca[id].first - Ca[id].second).Theta(); }
|
||||||
|
double GetCathodePhi(short id) const { return (Ca[id].first - Ca[id].second).Phi(); }
|
||||||
|
|
||||||
|
void ClearHitInfo();
|
||||||
|
void ConstructGeo();
|
||||||
|
void FindWireID(TVector3 pos, TVector3 direction, bool verbose = false);
|
||||||
|
void CalTrack(TVector3 sx3Pos, int anodeID, int cathodeID, bool verbose = false);
|
||||||
|
void CalTrack2(TVector3 sx3Pos, TVector3 anodeInt, bool verbose = false);
|
||||||
|
|
||||||
|
void Print()
|
||||||
|
{
|
||||||
|
printf(" The nearest | Anode: %2d(%5.2f) Cathode: %2d(%5.2f)\n", hitInfo.nearestWire.first,
|
||||||
|
hitInfo.nearestDist.first,
|
||||||
|
hitInfo.nearestWire.second,
|
||||||
|
hitInfo.nearestDist.second);
|
||||||
|
|
||||||
|
printf(" The 2nd nearest | Anode: %2d(%5.2f) Cathode: %2d(%5.2f)\n", hitInfo.nextNearestWire.first,
|
||||||
|
hitInfo.nextNearestDist.first,
|
||||||
|
hitInfo.nextNearestWire.second,
|
||||||
|
hitInfo.nextNearestDist.second);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
PWHitInfo hitInfo;
|
||||||
|
|
||||||
|
TVector3 trackPos;
|
||||||
|
TVector3 trackVec;
|
||||||
|
|
||||||
|
const int nWire = 24;
|
||||||
|
const int wireShift = 3;
|
||||||
|
const float zLen = 380; // mm
|
||||||
|
const float radiusA = 37;
|
||||||
|
const float radiusC = 43;
|
||||||
|
|
||||||
|
double dAngle;
|
||||||
|
double anodeLength;
|
||||||
|
double cathodeLength;
|
||||||
|
|
||||||
|
// std::vector<std::pair<TVector3, TVector3>> An; // the anode wire position vector in space
|
||||||
|
// std::vector<std::pair<TVector3, TVector3>> Ca; // the cathode wire position vector in space
|
||||||
|
|
||||||
|
double Distance(TVector3 a1, TVector3 a2, TVector3 b1, TVector3 b2)
|
||||||
|
{
|
||||||
|
TVector3 na = a1 - a2;
|
||||||
|
TVector3 nb = b1 - b2;
|
||||||
|
TVector3 nd = (na.Cross(nb)).Unit();
|
||||||
|
return TMath::Abs(nd.Dot(a1 - b2));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
inline void PW::ClearHitInfo()
|
||||||
|
{
|
||||||
|
hitInfo.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void PW::ConstructGeo()
|
||||||
|
{
|
||||||
|
|
||||||
|
An.clear();
|
||||||
|
Ca.clear();
|
||||||
|
|
||||||
|
std::pair<TVector3, TVector3> p1; // anode
|
||||||
|
std::pair<TVector3, TVector3> q1; // cathode
|
||||||
|
|
||||||
|
// anode and cathode start at pos-Y axis and count in right-Hand
|
||||||
|
// anode wire shift is right-hand.
|
||||||
|
// cathode wire shift is left-hand.
|
||||||
|
|
||||||
|
for (int i = 0; i < nWire; i++)
|
||||||
|
{
|
||||||
|
// Anode rotate right-hand
|
||||||
|
p1.first.SetXYZ(radiusA * TMath::Cos(TMath::TwoPi() / nWire * (i) + TMath::PiOver2()),
|
||||||
|
radiusA * TMath::Sin(TMath::TwoPi() / nWire * (i) + TMath::PiOver2()),
|
||||||
|
zLen / 2);
|
||||||
|
p1.second.SetXYZ(radiusA * TMath::Cos(TMath::TwoPi() / nWire * (i + wireShift) + TMath::PiOver2()),
|
||||||
|
radiusA * TMath::Sin(TMath::TwoPi() / nWire * (i + wireShift) + TMath::PiOver2()),
|
||||||
|
-zLen / 2);
|
||||||
|
An.push_back(p1);
|
||||||
|
|
||||||
|
// Cathod rotate left-hand with the 3 wire offset accounted for (+1 from the calculated offset from the PC coincidence spectrum)
|
||||||
|
q1.first.SetXYZ(radiusC * TMath::Cos(TMath::TwoPi() / nWire * (i + wireShift + 1) + TMath::PiOver2()),
|
||||||
|
radiusC * TMath::Sin(TMath::TwoPi() / nWire * (i + wireShift + 1) + TMath::PiOver2()),
|
||||||
|
zLen / 2);
|
||||||
|
q1.second.SetXYZ(radiusC * TMath::Cos(TMath::TwoPi() / nWire * (i + 1) + TMath::PiOver2()),
|
||||||
|
radiusC * TMath::Sin(TMath::TwoPi() / nWire * (i + 1) + TMath::PiOver2()),
|
||||||
|
-zLen / 2);
|
||||||
|
Ca.push_back(q1);
|
||||||
|
}
|
||||||
|
// correcting for the fact that the order of the cathode wires is reversed
|
||||||
|
std::reverse(Ca.begin(), Ca.end());
|
||||||
|
// adjusting for the 3 wire offset, the rbegin and rend are used as the rotation of the wires is done in the opposite direction i.e. 1,2,3 -> 3,1,2
|
||||||
|
// NOT NECESSARY ANY MORE, HAS BEEN IMCORPORATED INTO THE WIREOFFSET IN THE BEGINNING
|
||||||
|
// std::rotate(Ca.rbegin(), Ca.rbegin() + 4, Ca.rend());
|
||||||
|
|
||||||
|
dAngle = wireShift * TMath::TwoPi() / nWire;
|
||||||
|
anodeLength = TMath::Sqrt(zLen * zLen + TMath::Power(2 * radiusA * TMath::Sin(dAngle / 2), 2));
|
||||||
|
cathodeLength = TMath::Sqrt(zLen * zLen + TMath::Power(2 * radiusC * TMath::Sin(dAngle / 2), 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void PW::FindWireID(TVector3 pos, TVector3 direction, bool verbose)
|
||||||
|
{
|
||||||
|
|
||||||
|
hitInfo.Clear();
|
||||||
|
double phi = direction.Phi();
|
||||||
|
|
||||||
|
for (int i = 0; i < nWire; i++)
|
||||||
|
{
|
||||||
|
|
||||||
|
double disA = 99999999;
|
||||||
|
double phiS = An[i].first.Phi() - TMath::PiOver4();
|
||||||
|
double phiL = An[i].second.Phi() + TMath::PiOver4();
|
||||||
|
// printf("A%2d: %f %f | %f\n", i, phiS * TMath::RadToDeg(), phiL * TMath::RadToDeg(), phi * TMath::RadToDeg());
|
||||||
|
if (phi > 0 && phiS > phiL)
|
||||||
|
phiL = phiL + TMath::TwoPi();
|
||||||
|
if (phi < 0 && phiS > phiL)
|
||||||
|
phiS = phiS - TMath::TwoPi();
|
||||||
|
|
||||||
|
if (phiS < phi && phi < phiL)
|
||||||
|
{
|
||||||
|
disA = Distance(pos, pos + direction, An[i].first, An[i].second);
|
||||||
|
if (disA < hitInfo.nearestDist.first)
|
||||||
|
{
|
||||||
|
hitInfo.nearestDist.first = disA;
|
||||||
|
hitInfo.nearestWire.first = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
double disC = 99999999;
|
||||||
|
phiS = Ca[i].second.Phi() - TMath::PiOver4();
|
||||||
|
phiL = Ca[i].first.Phi() + TMath::PiOver4();
|
||||||
|
// printf("C%2d: %f %f\n", i, phiS * TMath::RadToDeg(), phiL * TMath::RadToDeg());
|
||||||
|
if (phi > 0 && phiS > phiL)
|
||||||
|
phiL = phiL + TMath::TwoPi();
|
||||||
|
if (phi < 0 && phiS > phiL)
|
||||||
|
phiS = phiS - TMath::TwoPi();
|
||||||
|
|
||||||
|
if (phiS < phi && phi < phiL)
|
||||||
|
{
|
||||||
|
disC = Distance(pos, pos + direction, Ca[i].first, Ca[i].second);
|
||||||
|
if (disC < hitInfo.nearestDist.second)
|
||||||
|
{
|
||||||
|
hitInfo.nearestDist.second = disC;
|
||||||
|
hitInfo.nearestWire.second = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (verbose)
|
||||||
|
printf(" %2d | %8.2f, %8.2f\n", i, disA, disC);
|
||||||
|
}
|
||||||
|
|
||||||
|
//==== find the 2nd nearest wire
|
||||||
|
short anode1 = hitInfo.nearestWire.first;
|
||||||
|
short aaa1 = anode1 - 1;
|
||||||
|
if (aaa1 < 0)
|
||||||
|
aaa1 += nWire;
|
||||||
|
short aaa2 = (anode1 + 1) % nWire;
|
||||||
|
|
||||||
|
double haha1 = Distance(pos, pos + direction, An[aaa1].first, An[aaa1].second);
|
||||||
|
double haha2 = Distance(pos, pos + direction, An[aaa2].first, An[aaa2].second);
|
||||||
|
if (haha1 < haha2)
|
||||||
|
{
|
||||||
|
hitInfo.nextNearestWire.first = aaa1;
|
||||||
|
hitInfo.nextNearestDist.first = haha1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hitInfo.nextNearestWire.first = aaa2;
|
||||||
|
hitInfo.nextNearestDist.first = haha2;
|
||||||
|
}
|
||||||
|
|
||||||
|
short cathode1 = hitInfo.nearestWire.second;
|
||||||
|
short ccc1 = cathode1 - 1;
|
||||||
|
if (ccc1 < 0)
|
||||||
|
ccc1 += nWire;
|
||||||
|
short ccc2 = (cathode1 + 1) % nWire;
|
||||||
|
|
||||||
|
haha1 = Distance(pos, pos + direction, Ca[ccc1].first, Ca[ccc1].second);
|
||||||
|
haha2 = Distance(pos, pos + direction, Ca[ccc2].first, Ca[ccc2].second);
|
||||||
|
if (haha1 < haha2)
|
||||||
|
{
|
||||||
|
hitInfo.nextNearestWire.second = ccc1;
|
||||||
|
hitInfo.nextNearestDist.second = haha1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hitInfo.nextNearestWire.second = ccc2;
|
||||||
|
hitInfo.nextNearestDist.second = haha2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (verbose)
|
||||||
|
Print();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void PW::CalTrack(TVector3 sx3Pos, int anodeID, int cathodeID, bool verbose)
|
||||||
|
{
|
||||||
|
|
||||||
|
trackPos = sx3Pos;
|
||||||
|
|
||||||
|
TVector3 n1 = (An[anodeID].first - An[anodeID].second).Cross((sx3Pos - An[anodeID].second)).Unit();
|
||||||
|
TVector3 n2 = (Ca[cathodeID].first - Ca[cathodeID].second).Cross((sx3Pos - Ca[cathodeID].second)).Unit();
|
||||||
|
|
||||||
|
// if the handiness of anode and cathode revered, it should be n2 cross n1
|
||||||
|
trackVec = (n2.Cross(n1)).Unit();
|
||||||
|
|
||||||
|
if (verbose)
|
||||||
|
printf("Theta, Phi = %f, %f \n", trackVec.Theta() * TMath::RadToDeg(), trackVec.Phi() * TMath::RadToDeg());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void PW::CalTrack2(TVector3 siPos, TVector3 anodeInt, bool verbose)
|
||||||
|
{
|
||||||
|
|
||||||
|
double mx, my;
|
||||||
|
double z;
|
||||||
|
mx = siPos.X() / (siPos.X() - anodeInt.X());
|
||||||
|
my = siPos.Y() / (siPos.Y() - anodeInt.Y());
|
||||||
|
z=siPos.Z() + mx * (anodeInt.Z() - siPos.Z());
|
||||||
|
// if (mx == my)
|
||||||
|
{
|
||||||
|
trackVec=TVector3(0,0,z);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (verbose)
|
||||||
|
printf("X slope = %f and Y slope = %f \n", mx, my);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline double PW::GetZ0()
|
||||||
|
{
|
||||||
|
|
||||||
|
double x = trackPos.X();
|
||||||
|
double y = trackPos.Y();
|
||||||
|
double rho = TMath::Sqrt(x * x + y * y);
|
||||||
|
double theta = trackVec.Theta();
|
||||||
|
|
||||||
|
return trackVec.Z();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
257
Armory/Armory/ClassSX3.h
Normal file
257
Armory/Armory/ClassSX3.h
Normal file
|
|
@ -0,0 +1,257 @@
|
||||||
|
#ifndef ClassSX3_h
|
||||||
|
#define ClassSX3_h
|
||||||
|
|
||||||
|
#include <cstdio>
|
||||||
|
#include <TMath.h>
|
||||||
|
#include <TVector3.h>
|
||||||
|
#include <TRandom.h>
|
||||||
|
|
||||||
|
class SX3{
|
||||||
|
public:
|
||||||
|
SX3(){Clear();};
|
||||||
|
~SX3(){}
|
||||||
|
|
||||||
|
short GetID() const {return id;}
|
||||||
|
short GetChUp() const {return chUp;}
|
||||||
|
short GetChDn() const {return chDn;}
|
||||||
|
short GetChBk() const {return chBk;}
|
||||||
|
|
||||||
|
TVector3 GetHitPos() const {return hitPos;}
|
||||||
|
TVector3 GetHitPosWithSigma(double sigmaY_mm, double sigmaZ_mm);
|
||||||
|
|
||||||
|
double GetZFrac() const {return zFrac;} // range from -0.5 to 0.5
|
||||||
|
|
||||||
|
void Clear();
|
||||||
|
void ConstructGeo();
|
||||||
|
void FindSX3Pos(TVector3 pos, TVector3 direction, bool verbose = false);
|
||||||
|
void CalSX3Pos(unsigned short ID, unsigned short chUp, unsigned short chDown, unsigned short chBack, float eUp, float eDown);
|
||||||
|
|
||||||
|
double GetNumDet() const {return numDet;}
|
||||||
|
double GetWidth() const {return width;}
|
||||||
|
double GetLength() const {return length;}
|
||||||
|
TVector3 GetDnL(short id) const {return SDn[id].first; } // lower strip ID
|
||||||
|
TVector3 GetDnH(short id) const {return SDn[id].second; } // higher strip ID
|
||||||
|
TVector3 GetUpL(short id) const {return SUp[id].first; } // lower strip ID
|
||||||
|
TVector3 GetUpH(short id) const {return SUp[id].second; } // higher strip ID
|
||||||
|
|
||||||
|
TVector3 GetDnMid(short id) const { return (SDn[id].first + SDn[id].second)*0.5;}
|
||||||
|
TVector3 GetUpMid(short id) const { return (SUp[id].first + SUp[id].second)*0.5;}
|
||||||
|
|
||||||
|
double GetDetPhi(short id) const { return (SUp[id].second - SUp[id].first).Phi();}
|
||||||
|
|
||||||
|
void Print(){
|
||||||
|
if( id == -1 ){
|
||||||
|
printf("Did not hit any SX3.\n");
|
||||||
|
}else{
|
||||||
|
printf("ID: %d, U,D,B: %d %d %d| zFrac : %.2f\n", id, chUp, chDn, chBk, zFrac);
|
||||||
|
printf("Hit Pos: %.2f, %.2f, %.2f\n", hitPos.X(), hitPos.Y(), hitPos.Z());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// void CalZFrac(){
|
||||||
|
// zFrac = (eUp - eDn)/(eUp + eDn);
|
||||||
|
// }
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
const int numDet = 12;
|
||||||
|
const float radius = 88;
|
||||||
|
const float width = 40;
|
||||||
|
const float length = 75;
|
||||||
|
const float gap = 46;
|
||||||
|
|
||||||
|
short id; // -1 when no hit
|
||||||
|
short chUp;
|
||||||
|
short chDn;
|
||||||
|
short chBk;
|
||||||
|
|
||||||
|
double zFrac; // from +1 (downstream) to -1 (upstream)
|
||||||
|
|
||||||
|
double eUp;
|
||||||
|
double eDn;
|
||||||
|
double eBk;
|
||||||
|
|
||||||
|
TVector3 hitPos;
|
||||||
|
|
||||||
|
std::vector<std::pair<TVector3,TVector3>> SDn; // coners of the SX3 0-11, z = mid point
|
||||||
|
std::vector<std::pair<TVector3,TVector3>> SUp; // coners of the SX3 12-23, z = mid point
|
||||||
|
std::vector<TVector3> SNorml; // normal of the SX3 (outward)
|
||||||
|
|
||||||
|
|
||||||
|
std::pair<double, double> Intersect(TVector3 p1, TVector3 p2, TVector3 q1, TVector3 q2, bool verbose){
|
||||||
|
|
||||||
|
//see https://nukephysik101.wordpress.com/2023/12/30/intersect-between-2-line-segments/
|
||||||
|
//zero all z-component
|
||||||
|
TVector3 a0 = p1; a0.SetZ(0);
|
||||||
|
TVector3 a1 = p2; a1.SetZ(0);
|
||||||
|
|
||||||
|
TVector3 b0 = q1; b0.SetZ(0);
|
||||||
|
TVector3 b1 = q2; b1.SetZ(0);
|
||||||
|
|
||||||
|
double A = ((b0-b1).Cross(a0-a1)).Mag();
|
||||||
|
|
||||||
|
double h = ((b0-a0).Cross(b1-a0)).Z()/ A;
|
||||||
|
double k = ((a1-b0).Cross(a0-b0)).Z()/ A;
|
||||||
|
|
||||||
|
if( verbose ) printf(" ----h, k : %f, %f\n", h, k);
|
||||||
|
|
||||||
|
return std::pair<double,double>(h,k);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
inline void SX3::Clear(){
|
||||||
|
id = -1;
|
||||||
|
chUp = -1;
|
||||||
|
chDn = -1;
|
||||||
|
chBk = -1;
|
||||||
|
zFrac = TMath::QuietNaN();
|
||||||
|
|
||||||
|
eUp = TMath::QuietNaN();
|
||||||
|
eDn = TMath::QuietNaN();
|
||||||
|
eBk = TMath::QuietNaN();
|
||||||
|
|
||||||
|
SDn.clear();
|
||||||
|
SUp.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void SX3::ConstructGeo(){
|
||||||
|
TVector3 sa, sb, sc, sn;
|
||||||
|
|
||||||
|
for(int i = 0; i < numDet; i++){
|
||||||
|
sa.SetXYZ( radius, -width/2, gap/2 + length/2 );
|
||||||
|
sb.SetXYZ( radius, width/2, gap/2 + length/2 );
|
||||||
|
|
||||||
|
double rot = TMath::TwoPi() / numDet * (i - 0.5) - TMath::PiOver2();
|
||||||
|
|
||||||
|
sa.RotateZ( rot );
|
||||||
|
sb.RotateZ( rot );
|
||||||
|
SDn.push_back(std::pair<TVector3,TVector3>(sa,sb));
|
||||||
|
|
||||||
|
sc.SetXYZ( radius, -width/2, gap/2 );
|
||||||
|
sc.RotateZ( rot );
|
||||||
|
|
||||||
|
sn = ((sc-sa).Cross(sb-sa)).Unit();
|
||||||
|
SNorml.push_back(sn);
|
||||||
|
|
||||||
|
sa.SetXYZ( radius, -width/2, -gap/2 - length/2 );
|
||||||
|
sb.SetXYZ( radius, width/2, -gap/2 - length/2 );
|
||||||
|
|
||||||
|
sa.RotateZ( rot );
|
||||||
|
sb.RotateZ( rot );
|
||||||
|
SUp.push_back(std::pair<TVector3,TVector3>(sa,sb));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void SX3::FindSX3Pos(TVector3 pos, TVector3 direction, bool verbose){
|
||||||
|
|
||||||
|
id = -1;
|
||||||
|
for( int i = 0 ; i < numDet; i++){
|
||||||
|
|
||||||
|
if(verbose) printf(" %d ", i);
|
||||||
|
std::pair<double, double> frac = Intersect( pos, pos + direction, SDn[i].first, SDn[i].second, verbose);
|
||||||
|
|
||||||
|
|
||||||
|
if( frac.second < 0 || frac.second > 1 ) continue;
|
||||||
|
hitPos = pos + frac.first * direction;
|
||||||
|
|
||||||
|
double dis = hitPos.Dot(SNorml[i]);
|
||||||
|
|
||||||
|
if(verbose) {
|
||||||
|
printf("reduced distance : %f\n", dis);
|
||||||
|
printf(" %d*", (i+1)%numDet);
|
||||||
|
Intersect( pos, pos + direction, SDn[(i+1)%numDet].first, SDn[(i+1)%numDet].second, verbose);
|
||||||
|
}
|
||||||
|
|
||||||
|
if( TMath::Abs(dis - radius) > 0.1 ) continue;
|
||||||
|
|
||||||
|
chDn = 2 * TMath::Floor(frac.second * 4);
|
||||||
|
chUp = chDn + 1;
|
||||||
|
|
||||||
|
double zPos = hitPos.Z();
|
||||||
|
if( (gap/2 < zPos && zPos < gap/2 + length ) || (-gap/2 - length < zPos && zPos < -gap/2 ) ){
|
||||||
|
|
||||||
|
id = zPos > 0 ? i : i + 12;
|
||||||
|
|
||||||
|
zFrac = zPos > 0 ? (zPos - gap/2. - length/2.)/length : (zPos - ( - gap/2. - length/2.) )/length ;
|
||||||
|
|
||||||
|
chBk = TMath::Floor( (zFrac + 0.5) * 4 ) + 8;
|
||||||
|
|
||||||
|
if( verbose) Print();
|
||||||
|
return ;
|
||||||
|
|
||||||
|
}else{
|
||||||
|
if( verbose ) printf(" zPos out of sensitive region\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( verbose) Print();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline TVector3 SX3::GetHitPosWithSigma(double sigmaY_mm, double sigmaZ_mm){
|
||||||
|
|
||||||
|
double phi = SNorml[id%numDet].Phi();
|
||||||
|
|
||||||
|
TVector3 haha = hitPos;
|
||||||
|
haha.RotateZ(-phi);
|
||||||
|
|
||||||
|
double y = haha.Y() + gRandom->Gaus(0, sigmaY_mm);
|
||||||
|
if( sigmaY_mm < 0 ){
|
||||||
|
double deltaW = width/4;
|
||||||
|
y = TMath::Floor((haha.Y()-deltaW)/deltaW)*deltaW + deltaW*1.5; // when ever land on each strip, set the position to be center of the strip.
|
||||||
|
if( y >= 25 ) y = 15;
|
||||||
|
}
|
||||||
|
|
||||||
|
double z = haha.Z() + gRandom->Gaus(0, sigmaZ_mm);
|
||||||
|
if( sigmaZ_mm < 0 ){
|
||||||
|
haha.Z();
|
||||||
|
double delta = length/4;
|
||||||
|
int sign = z > 0 ? 1 : -1;
|
||||||
|
z = TMath::Floor( (abs(z)-gap/2)/delta )*delta + 0.5 * delta + gap/2;
|
||||||
|
if( z >= 107.375 ) z = 88.625;
|
||||||
|
z = sign * z;
|
||||||
|
}
|
||||||
|
|
||||||
|
haha.SetY(y);
|
||||||
|
haha.SetZ(z);
|
||||||
|
haha.RotateZ(phi);
|
||||||
|
|
||||||
|
return haha;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void SX3::CalSX3Pos(unsigned short ID, unsigned short chUp, unsigned short chDown, unsigned short chBack, float eUp, float eDown){
|
||||||
|
|
||||||
|
hitPos.Clear();
|
||||||
|
|
||||||
|
|
||||||
|
if( (chUp - chDown) != 1 || (chDown % 2) != 0) return ;
|
||||||
|
|
||||||
|
int reducedID = ID % numDet;
|
||||||
|
|
||||||
|
TVector3 sa, sb;
|
||||||
|
|
||||||
|
if( ID < numDet ){ //down
|
||||||
|
sa = SDn[reducedID].second;
|
||||||
|
sb = SDn[reducedID].first;
|
||||||
|
}else{
|
||||||
|
sa = SUp[reducedID].second;
|
||||||
|
sb = SUp[reducedID].first;
|
||||||
|
}
|
||||||
|
|
||||||
|
hitPos.SetX( (sb.X() - sa.X()) * chUp/8 + sa.X());
|
||||||
|
hitPos.SetY( (sb.Y() - sa.Y()) * chUp/8 + sa.Y());
|
||||||
|
|
||||||
|
if( eUp == 0 || eDown == 0 ){
|
||||||
|
hitPos.SetZ( sa.Z() + (2*(chBk - 7)-1) * length / 8 );
|
||||||
|
}else{
|
||||||
|
double frac = (eUp - eDown)/(eUp + eDown); // from +1 (downstream) to -1 (upstream)
|
||||||
|
double zPos = sa.Z() + length * frac/2;
|
||||||
|
hitPos.SetZ( zPos );
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
468
Armory/Armory/ClassTransfer.h
Normal file
468
Armory/Armory/ClassTransfer.h
Normal file
|
|
@ -0,0 +1,468 @@
|
||||||
|
#ifndef ClassTransfer_h
|
||||||
|
#define ClassTransfer_h
|
||||||
|
|
||||||
|
#include "TBenchmark.h"
|
||||||
|
#include "TLorentzVector.h"
|
||||||
|
#include "TVector3.h"
|
||||||
|
#include "TMath.h"
|
||||||
|
#include "TFile.h"
|
||||||
|
#include "TTree.h"
|
||||||
|
#include "TRandom.h"
|
||||||
|
#include "TMacro.h"
|
||||||
|
#include "TGraph.h"
|
||||||
|
#include <vector>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
#include "Isotope.h"
|
||||||
|
|
||||||
|
class ReactionConfig{
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
ReactionConfig(){}
|
||||||
|
~ReactionConfig(){}
|
||||||
|
|
||||||
|
int beamA, beamZ;
|
||||||
|
int targetA, targetZ;
|
||||||
|
int recoilLightA, recoilLightZ;
|
||||||
|
int recoilHeavyA, recoilHeavyZ;
|
||||||
|
|
||||||
|
float beamEnergy; ///MeV/u
|
||||||
|
float beamEnergySigma; ///beam-energy_sigma_in_MeV/u
|
||||||
|
float beamAngle; ///beam-angle_in_mrad
|
||||||
|
float beamAngleSigma; ///beam-emittance_in_mrad
|
||||||
|
float beamX; ///x_offset_of_Beam_in_mm
|
||||||
|
float beamY; ///y_offset_of_Beam_in_mm
|
||||||
|
int numEvents; ///number_of_Event_being_generated
|
||||||
|
bool isTargetScattering; ///isTargetScattering
|
||||||
|
float targetDensity; ///target_density_in_g/cm3
|
||||||
|
float targetThickness; ///targetThickness_in_cm
|
||||||
|
std::string beamStoppingPowerFile; ///stopping_power_for_beam
|
||||||
|
std::string recoilLightStoppingPowerFile; ///stopping_power_for_light_recoil
|
||||||
|
std::string recoilHeavyStoppingPowerFile; ///stopping_power_for_heavy_recoil
|
||||||
|
bool isDecay; ///isDacay
|
||||||
|
int heavyDecayA; ///decayNucleus_A
|
||||||
|
int heavyDecayZ; ///decayNucleus_Z
|
||||||
|
bool isRedo; ///isReDo
|
||||||
|
std::vector<float> beamEx; ///excitation_energy_of_A[MeV]
|
||||||
|
|
||||||
|
|
||||||
|
void SetReaction(int beamA, int beamZ,
|
||||||
|
int targetA, int targetZ,
|
||||||
|
int recoilA, int recoilZ, float beamEnergy_AMeV){
|
||||||
|
this->beamA = beamA;
|
||||||
|
this->beamZ = beamZ;
|
||||||
|
this->targetA = targetA;
|
||||||
|
this->targetZ = targetZ;
|
||||||
|
this->recoilLightA = recoilA;
|
||||||
|
this->recoilLightZ = recoilZ;
|
||||||
|
|
||||||
|
recoilHeavyA = this->beamA + this->targetA - recoilLightA;
|
||||||
|
recoilHeavyZ = this->beamZ + this->targetZ - recoilLightZ;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void LoadReactionConfig(TMacro * macro){
|
||||||
|
|
||||||
|
if( macro == NULL ) return ;
|
||||||
|
|
||||||
|
int numLine = macro->GetListOfLines()->GetSize();
|
||||||
|
|
||||||
|
for( int i = 0; i < numLine; i ++){
|
||||||
|
|
||||||
|
std::vector<std::string> str = SplitStr(macro->GetListOfLines()->At(i)->GetName(), " ");
|
||||||
|
|
||||||
|
///printf("%d | %s\n", i, str[0].c_str());
|
||||||
|
|
||||||
|
if( str[0].find_first_of("#") == 0 ) break;
|
||||||
|
|
||||||
|
if( i == 0 ) beamA = atoi(str[0].c_str());
|
||||||
|
if( i == 1 ) beamZ = atoi(str[0].c_str());
|
||||||
|
if( i == 2 ) targetA = atoi(str[0].c_str());
|
||||||
|
if( i == 3 ) targetZ = atoi(str[0].c_str());
|
||||||
|
if( i == 4 ) recoilLightA = atoi(str[0].c_str());
|
||||||
|
if( i == 5 ) recoilLightZ = atoi(str[0].c_str());
|
||||||
|
if( i == 6 ) beamEnergy = atof(str[0].c_str());
|
||||||
|
if( i == 7 ) beamEnergySigma = atof(str[0].c_str());
|
||||||
|
if( i == 8 ) beamAngle = atof(str[0].c_str());
|
||||||
|
if( i == 9 ) beamAngleSigma = atof(str[0].c_str());
|
||||||
|
if( i == 10 ) beamX = atof(str[0].c_str());
|
||||||
|
if( i == 11 ) beamY = atof(str[0].c_str());
|
||||||
|
if( i == 12 ) numEvents = atoi(str[0].c_str());
|
||||||
|
if( i == 13 ) {
|
||||||
|
if( str[0].compare("false") == 0 ) isTargetScattering = false;
|
||||||
|
if( str[0].compare("true") == 0 ) isTargetScattering = true;
|
||||||
|
}
|
||||||
|
if( i == 14 ) targetDensity = atof(str[0].c_str());
|
||||||
|
if( i == 15 ) targetThickness = atof(str[0].c_str());
|
||||||
|
if( i == 16 ) beamStoppingPowerFile = str[0];
|
||||||
|
if( i == 17 ) recoilLightStoppingPowerFile = str[0];
|
||||||
|
if( i == 18 ) recoilHeavyStoppingPowerFile = str[0];
|
||||||
|
if( i == 19 ) {
|
||||||
|
if( str[0].compare("false") == 0 ) isDecay = false;
|
||||||
|
if( str[0].compare("true") == 0 ) isDecay = true;
|
||||||
|
}
|
||||||
|
if( i == 20 ) heavyDecayA = atoi(str[0].c_str());
|
||||||
|
if( i == 21 ) heavyDecayZ = atoi(str[0].c_str());
|
||||||
|
if( i == 22 ) {
|
||||||
|
if( str[0].compare("false") == 0 ) isRedo = false;
|
||||||
|
if( str[0].compare("true" ) == 0 ) isRedo = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( i >= 23) {
|
||||||
|
beamEx.push_back( atof(str[0].c_str()) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
recoilHeavyA = beamA + targetA - recoilLightA;
|
||||||
|
recoilHeavyZ = beamZ + targetZ - recoilLightZ;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrintReactionConfig(){
|
||||||
|
|
||||||
|
printf("=====================================================\n");
|
||||||
|
printf(" beam : A = %3d, Z = %2d \n", beamA, beamZ);
|
||||||
|
printf(" target : A = %3d, Z = %2d \n", targetA, targetZ);
|
||||||
|
printf(" light : A = %3d, Z = %2d \n", recoilLightA, recoilLightZ);
|
||||||
|
|
||||||
|
printf(" beam Energy : %.2f +- %.2f MeV/u, dE/E = %5.2f %%\n", beamEnergy, beamEnergySigma, beamEnergySigma/beamEnergy);
|
||||||
|
printf(" Angle : %.2f +- %.2f mrad\n", beamAngle, beamAngleSigma);
|
||||||
|
printf(" offset : (x,y) = (%.2f, %.2f) mmm \n", beamX, beamY);
|
||||||
|
|
||||||
|
printf("##### number of Simulation Events : %d \n", numEvents);
|
||||||
|
|
||||||
|
printf(" is target scattering : %s \n", isTargetScattering ? "Yes" : "No");
|
||||||
|
|
||||||
|
if(isTargetScattering){
|
||||||
|
printf(" target density : %.f g/cm3\n", targetDensity);
|
||||||
|
printf(" thickness : %.f cm\n", targetThickness);
|
||||||
|
printf(" beam stopping file : %s \n", beamStoppingPowerFile.c_str());
|
||||||
|
printf(" recoil light stopping file : %s \n", recoilLightStoppingPowerFile.c_str());
|
||||||
|
printf(" recoil heavy stopping file : %s \n", recoilHeavyStoppingPowerFile.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
printf(" is simulate decay : %s \n", isDecay ? "Yes" : "No");
|
||||||
|
if( isDecay ){
|
||||||
|
printf(" heavy decay : A = %d, Z = %d \n", heavyDecayA, heavyDecayZ);
|
||||||
|
}
|
||||||
|
printf(" is Redo until hit array : %s \n", isRedo ? "Yes" : "No");
|
||||||
|
|
||||||
|
printf(" beam Ex : %.2f MeV \n", beamEx[0]);
|
||||||
|
for( int i = 1; i < (int) beamEx.size(); i++){
|
||||||
|
printf(" %.2f MeV \n", beamEx[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
printf("=====================================================\n");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
//=======================================================
|
||||||
|
//#######################################################
|
||||||
|
// Class for Transfer Reaction
|
||||||
|
// reaction notation A(a,b)B
|
||||||
|
// A = incident particle
|
||||||
|
// a = target
|
||||||
|
// b = light scattered particle
|
||||||
|
// B = heavy scattered particle
|
||||||
|
//=======================================================
|
||||||
|
class TransferReaction {
|
||||||
|
public:
|
||||||
|
TransferReaction();
|
||||||
|
~TransferReaction();
|
||||||
|
|
||||||
|
void SetA(int A, int Z, double Ex);
|
||||||
|
void Seta(int A, int Z);
|
||||||
|
void Setb(int A, int Z);
|
||||||
|
void SetB(int A, int Z);
|
||||||
|
void SetIncidentEnergyAngle(double KEA, double theta, double phi);
|
||||||
|
void SetExA(double Ex);
|
||||||
|
void SetExB(double Ex);
|
||||||
|
void SetReactionFromFile(string settingFile);
|
||||||
|
|
||||||
|
TString GetReactionName();
|
||||||
|
TString GetReactionName_Latex();
|
||||||
|
|
||||||
|
ReactionConfig GetRectionConfig() { return reaction;}
|
||||||
|
|
||||||
|
double GetMass_A(){return mA + ExA;}
|
||||||
|
double GetMass_a(){return ma;}
|
||||||
|
double GetMass_b(){return mb;}
|
||||||
|
double GetMass_B(){return mB + ExB;}
|
||||||
|
|
||||||
|
double GetCMTotalKE() {return Etot - mA - ma;}
|
||||||
|
double GetQValue() {return mA + ExA + ma - mb - mB - ExB;}
|
||||||
|
double GetMaxExB() {return Etot - mb - mB;}
|
||||||
|
|
||||||
|
TLorentzVector GetPA(){return PA;}
|
||||||
|
TLorentzVector GetPa(){return Pa;}
|
||||||
|
TLorentzVector GetPb(){return Pb;}
|
||||||
|
TLorentzVector GetPB(){return PB;}
|
||||||
|
|
||||||
|
void CalReactionConstant();
|
||||||
|
|
||||||
|
TLorentzVector * Event(double thetaCM, double phiCM);
|
||||||
|
|
||||||
|
double GetEx(){return Ex;}
|
||||||
|
double GetThetaCM(){return thetaCM;}
|
||||||
|
|
||||||
|
double GetMomentumbCM() {return p;}
|
||||||
|
double GetReactionBeta() {return beta;}
|
||||||
|
double GetReactionGamma() {return gamma;}
|
||||||
|
double GetCMTotalEnergy() {return Etot;}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
ReactionConfig reaction;
|
||||||
|
|
||||||
|
string nameA, namea, nameb, nameB;
|
||||||
|
double thetaIN, phiIN;
|
||||||
|
double mA, ma, mb, mB;
|
||||||
|
|
||||||
|
double TA, T; // TA = KE of A pre u, T = total energy
|
||||||
|
double ExA, ExB;
|
||||||
|
double Ex, thetaCM; //calculated Ex using inverse mapping from e and z to thetaCM
|
||||||
|
|
||||||
|
bool isReady;
|
||||||
|
bool isBSet;
|
||||||
|
|
||||||
|
double k; // CM Boost momentum
|
||||||
|
double beta, gamma; //CM boost beta
|
||||||
|
double Etot;
|
||||||
|
double p; // CM frame momentum of b, B
|
||||||
|
|
||||||
|
TLorentzVector PA, Pa, Pb, PB;
|
||||||
|
|
||||||
|
TString format(TString name);
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
TransferReaction::TransferReaction(){
|
||||||
|
|
||||||
|
thetaIN = 0.;
|
||||||
|
phiIN = 0.;
|
||||||
|
SetA(24, 12, 0);
|
||||||
|
Seta(4,2);
|
||||||
|
Setb(1,1);
|
||||||
|
SetB(27,13);
|
||||||
|
TA = 2.5;
|
||||||
|
T = TA * reaction.beamA;
|
||||||
|
|
||||||
|
ExA = 0;
|
||||||
|
ExB = 0;
|
||||||
|
|
||||||
|
Ex = TMath::QuietNaN();
|
||||||
|
thetaCM = TMath::QuietNaN();
|
||||||
|
|
||||||
|
CalReactionConstant();
|
||||||
|
|
||||||
|
TLorentzVector temp (0,0,0,0);
|
||||||
|
PA = temp;
|
||||||
|
Pa = temp;
|
||||||
|
Pb = temp;
|
||||||
|
PB = temp;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
TransferReaction::~TransferReaction(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void TransferReaction::SetA(int A, int Z, double Ex = 0){
|
||||||
|
Isotope temp (A, Z);
|
||||||
|
mA = temp.Mass;
|
||||||
|
reaction.beamA = A;
|
||||||
|
reaction.beamZ = Z;
|
||||||
|
ExA = Ex;
|
||||||
|
nameA = temp.Name;
|
||||||
|
isReady = false;
|
||||||
|
isBSet = true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void TransferReaction::Seta(int A, int Z){
|
||||||
|
Isotope temp (A, Z);
|
||||||
|
ma = temp.Mass;
|
||||||
|
reaction.targetA = A;
|
||||||
|
reaction.targetZ = Z;
|
||||||
|
namea = temp.Name;
|
||||||
|
isReady = false;
|
||||||
|
isBSet = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TransferReaction::Setb(int A, int Z){
|
||||||
|
Isotope temp (A, Z);
|
||||||
|
mb = temp.Mass;
|
||||||
|
reaction.recoilLightA = A;
|
||||||
|
reaction.recoilLightZ = Z;
|
||||||
|
nameb = temp.Name;
|
||||||
|
isReady = false;
|
||||||
|
isBSet = false;
|
||||||
|
}
|
||||||
|
void TransferReaction::SetB(int A, int Z){
|
||||||
|
Isotope temp (A, Z);
|
||||||
|
mB = temp.Mass;
|
||||||
|
reaction.recoilHeavyA = A;
|
||||||
|
reaction.recoilHeavyZ = Z;
|
||||||
|
nameB = temp.Name;
|
||||||
|
isReady = false;
|
||||||
|
isBSet = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TransferReaction::SetIncidentEnergyAngle(double KEA, double theta, double phi){
|
||||||
|
this->TA = KEA;
|
||||||
|
this->T = TA * reaction.beamA;
|
||||||
|
this->thetaIN = theta;
|
||||||
|
this->phiIN = phi;
|
||||||
|
isReady = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TransferReaction::SetExA(double Ex){
|
||||||
|
this->ExA = Ex;
|
||||||
|
isReady = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TransferReaction::SetExB(double Ex){
|
||||||
|
this->ExB = Ex;
|
||||||
|
isReady = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TransferReaction::SetReactionFromFile(string settingFile){
|
||||||
|
|
||||||
|
TMacro * haha = new TMacro();
|
||||||
|
if( haha->ReadFile(settingFile.c_str()) > 0 ) {
|
||||||
|
reaction.LoadReactionConfig(haha);
|
||||||
|
|
||||||
|
SetA(reaction.beamA, reaction.beamZ);
|
||||||
|
Seta(reaction.targetA, reaction.targetZ);
|
||||||
|
Setb(reaction.recoilLightA, reaction.recoilLightZ);
|
||||||
|
SetB(reaction.recoilHeavyA, reaction.recoilHeavyZ);
|
||||||
|
|
||||||
|
SetIncidentEnergyAngle(reaction.beamEnergy, 0, 0);
|
||||||
|
CalReactionConstant();
|
||||||
|
}else{
|
||||||
|
|
||||||
|
printf("cannot read file %s.\n", settingFile.c_str());
|
||||||
|
isReady = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
TString TransferReaction::GetReactionName(){
|
||||||
|
TString rName;
|
||||||
|
rName.Form("%s(%s,%s)%s", nameA.c_str(), namea.c_str(), nameb.c_str(), nameB.c_str());
|
||||||
|
return rName;
|
||||||
|
}
|
||||||
|
|
||||||
|
TString TransferReaction::format(TString name){
|
||||||
|
if( name.IsAlpha() ) return name;
|
||||||
|
int len = name.Length();
|
||||||
|
TString temp = name;
|
||||||
|
TString temp2 = name;
|
||||||
|
if( temp.Remove(0, len-2).IsAlpha()){
|
||||||
|
temp2.Remove(len-2);
|
||||||
|
}else{
|
||||||
|
temp = name;
|
||||||
|
temp.Remove(0, len-1);
|
||||||
|
temp2.Remove(len-1);
|
||||||
|
}
|
||||||
|
return "^{"+temp2+"}"+temp;
|
||||||
|
}
|
||||||
|
|
||||||
|
TString TransferReaction::GetReactionName_Latex(){
|
||||||
|
TString rName;
|
||||||
|
rName.Form("%s(%s,%s)%s", format(nameA).Data(), format(namea).Data(), format(nameb).Data(), format(nameB).Data());
|
||||||
|
return rName;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TransferReaction::CalReactionConstant(){
|
||||||
|
if( !isBSet){
|
||||||
|
reaction.recoilHeavyA = reaction.beamA + reaction.targetA - reaction.recoilLightA;
|
||||||
|
reaction.recoilHeavyZ = reaction.beamZ + reaction.targetZ - reaction.recoilLightZ;
|
||||||
|
Isotope temp (reaction.recoilHeavyA, reaction.recoilHeavyZ);
|
||||||
|
mB = temp.Mass;
|
||||||
|
isBSet = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
k = TMath::Sqrt(TMath::Power(mA + ExA + T, 2) - (mA + ExA) * (mA + ExA));
|
||||||
|
beta = k / (mA + ExA + ma + T);
|
||||||
|
gamma = 1 / TMath::Sqrt(1- beta * beta);
|
||||||
|
Etot = TMath::Sqrt(TMath::Power(mA + ExA + ma + T,2) - k * k);
|
||||||
|
p = TMath::Sqrt( (Etot*Etot - TMath::Power(mb + mB + ExB,2)) * (Etot*Etot - TMath::Power(mb - mB - ExB,2)) ) / 2 / Etot;
|
||||||
|
|
||||||
|
PA.SetXYZM(0, 0, k, mA + ExA);
|
||||||
|
PA.RotateY(thetaIN);
|
||||||
|
PA.RotateZ(phiIN);
|
||||||
|
|
||||||
|
Pa.SetXYZM(0,0,0,ma);
|
||||||
|
|
||||||
|
isReady = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
TLorentzVector * TransferReaction::Event(double thetaCM, double phiCM)
|
||||||
|
{
|
||||||
|
if( isReady == false ){
|
||||||
|
CalReactionConstant();
|
||||||
|
}
|
||||||
|
|
||||||
|
//TLorentzVector Pa(0, 0, 0, ma);
|
||||||
|
|
||||||
|
//---- to CM frame
|
||||||
|
TLorentzVector Pc = PA + Pa;
|
||||||
|
TVector3 b = Pc.BoostVector();
|
||||||
|
|
||||||
|
TVector3 vb(0,0,0);
|
||||||
|
|
||||||
|
if( b.Mag() > 0 ){
|
||||||
|
TVector3 v0 (0,0,0);
|
||||||
|
TVector3 nb = v0 - b;
|
||||||
|
|
||||||
|
TLorentzVector PAc = PA;
|
||||||
|
PAc.Boost(nb);
|
||||||
|
TVector3 vA = PAc.Vect();
|
||||||
|
|
||||||
|
TLorentzVector Pac = Pa;
|
||||||
|
Pac.Boost(nb);
|
||||||
|
TVector3 va = Pac.Vect();
|
||||||
|
|
||||||
|
//--- construct vb
|
||||||
|
vb = va;
|
||||||
|
vb.SetMag(p);
|
||||||
|
|
||||||
|
TVector3 ub = vb.Orthogonal();
|
||||||
|
vb.Rotate(thetaCM, ub);
|
||||||
|
vb.Rotate(phiCM + TMath::PiOver2(), va); // somehow, the calculation turn the vector 90 degree.
|
||||||
|
//vb.Rotate(phiCM , va); // somehow, the calculation turn the vector 90 degree.
|
||||||
|
}
|
||||||
|
|
||||||
|
//--- from Pb
|
||||||
|
TLorentzVector Pbc;
|
||||||
|
Pbc.SetVectM(vb, mb);
|
||||||
|
|
||||||
|
//--- from PB
|
||||||
|
TLorentzVector PBc;
|
||||||
|
//PBc.SetVectM(vB, mB + ExB);
|
||||||
|
PBc.SetVectM(-vb, mB + ExB);
|
||||||
|
|
||||||
|
//---- to Lab Frame
|
||||||
|
TLorentzVector Pb = Pbc;
|
||||||
|
Pb.Boost(b);
|
||||||
|
TLorentzVector PB = PBc;
|
||||||
|
PB.Boost(b);
|
||||||
|
|
||||||
|
TLorentzVector * output = new TLorentzVector[4];
|
||||||
|
output[0] = PA;
|
||||||
|
output[1] = Pa;
|
||||||
|
output[2] = Pb;
|
||||||
|
output[3] = PB;
|
||||||
|
|
||||||
|
this->Pb = Pb;
|
||||||
|
this->PB = PB;
|
||||||
|
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
414
Armory/Armory/HistPlotter.h
Normal file
414
Armory/Armory/HistPlotter.h
Normal file
|
|
@ -0,0 +1,414 @@
|
||||||
|
#ifndef HISTPLOTTER_H
|
||||||
|
#define HISTPLOTTER_H
|
||||||
|
#include <TCanvas.h>
|
||||||
|
#include <TROOT.h>
|
||||||
|
#include <TSystem.h>
|
||||||
|
#include <TStyle.h>
|
||||||
|
#include <iostream>
|
||||||
|
#include <TFile.h>
|
||||||
|
#include <TMemFile.h>
|
||||||
|
#include <TH1.h>
|
||||||
|
#include <TH2.h>
|
||||||
|
#include <TCutG.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <utility>
|
||||||
|
#include <fstream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <set>
|
||||||
|
#include <TGraphErrors.h>
|
||||||
|
|
||||||
|
class HistPlotter {
|
||||||
|
private:
|
||||||
|
long long barrier_count, barrier_limit; //meant to keep track of how often to call FillN() on histograms
|
||||||
|
enum {TFILE, TMEMFILE} filetype;
|
||||||
|
std::unordered_map<std::string,TObject*> oMap; //!< Maps std::string to all TH1, TH2 objects in the class
|
||||||
|
std::unordered_map<std::string,TObject*> cutsMap; //!< Maps std::string to TCutG objects held by the class
|
||||||
|
std::set<std::string> folderList; //!< List of all folder names used to nest objects
|
||||||
|
std::unordered_map<TObject*,std::string> foldersForObjects; //!< Map that returns the folder corresponding to the object whose pointer is specified
|
||||||
|
TFile *ofile=nullptr; //!< TFile pointer for the output file
|
||||||
|
TMemFile *omfile=nullptr; //!< TFile pointer for the output memfile
|
||||||
|
|
||||||
|
//Caches to permit FillN() calls
|
||||||
|
std::unordered_map<std::string, std::vector<double>> onedimcache;
|
||||||
|
std::unordered_map<std::string, std::pair<std::vector<double>, std::vector<double>>> twodimcache;
|
||||||
|
inline void FillN_All_Histograms();
|
||||||
|
public:
|
||||||
|
HistPlotter(std::string outfile, std::string type);
|
||||||
|
inline void FlushToDisk(); //!< Writes all objects to file before closing, nesting objects in folders as is found necessary
|
||||||
|
inline void PrintObjects(); //!< Dump objects to std::cout for inspection
|
||||||
|
inline void ReadCuts(std::string);
|
||||||
|
inline TCutG* FindCut(std::string cut) {
|
||||||
|
return static_cast<TCutG*>(cutsMap.at(cut));
|
||||||
|
}
|
||||||
|
inline void set_barrier_limit(long long limit) { barrier_limit = limit; }
|
||||||
|
inline void barrier_increment() {
|
||||||
|
barrier_count++;
|
||||||
|
if(barrier_count == barrier_limit) {
|
||||||
|
FillN_All_Histograms();
|
||||||
|
barrier_count=0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*! \fn void FindCut()
|
||||||
|
\brief
|
||||||
|
- Searches for a cut by name 'cut' in the internal list of cuts 'cutsMap'. Ugly fails (via unresolved at()) if such a cut isn't found.
|
||||||
|
\param filename - name of the plainxtext file containing the cut file locations and identifiers
|
||||||
|
\return Pointer to the TCutG object that matches the name. Very useful to use this as plotter.FindCut("protonbarrelpid")->IsInside(deltaE, E) for instance.
|
||||||
|
*/
|
||||||
|
|
||||||
|
inline void SetNewTitle(std::string name, std::string title) {
|
||||||
|
auto result = oMap.find(name); //result is an iterator
|
||||||
|
if(result==oMap.end()) return; //no warnings, could be changed in future
|
||||||
|
else
|
||||||
|
static_cast<TNamed*>(oMap.at(name))->SetTitle(title.c_str()); // set new title
|
||||||
|
}
|
||||||
|
|
||||||
|
//Smart functions that create a new histogram if it doesn't exist.
|
||||||
|
inline void FillGraph(const std::string &name, float valuex, float valuey, float errx=0, float erry=0);
|
||||||
|
inline void Fill1D(const std::string& name,int nbinsx, float xlow, float xhigh, float value);
|
||||||
|
inline void Fill2D(const std::string& name,int nbinsx, float xlow, float xhigh
|
||||||
|
,int nbinsy, float ylow, float yhigh, float valuex, float valuey);
|
||||||
|
inline void Fill1D(const std::string& name,int nbinsx, float xlow, float xhigh, float value, const std::string& folder);
|
||||||
|
inline void Fill2D(const std::string& name,int nbinsx, float xlow, float xhigh
|
||||||
|
,int nbinsy, float ylow, float yhigh, float valuex, float valuey, const std::string& folder);
|
||||||
|
//TObject* findObject(std::string key);
|
||||||
|
};
|
||||||
|
|
||||||
|
HistPlotter::HistPlotter(std::string outfile, std::string type="") {
|
||||||
|
/*!
|
||||||
|
\brief Constructor. Opens a TFile instance with the specified filename
|
||||||
|
\param outfile : std::string that holds the desired output ROOT filename
|
||||||
|
\return None
|
||||||
|
*/
|
||||||
|
if(type=="" || type == "TFILE") {
|
||||||
|
ofile = new TFile(outfile.c_str(),"recreate");
|
||||||
|
filetype = TFILE;
|
||||||
|
} else if(type =="TMEMFILE") {
|
||||||
|
omfile = new TMemFile(outfile.c_str(),"recreate");
|
||||||
|
filetype=TMEMFILE;
|
||||||
|
} else {
|
||||||
|
std::cout << "Unknown type "<< type << " specified for HistPlotter (use \"TFILE\" or \"TMEMFILE\"), using default \"TFILE\" " << std::endl;
|
||||||
|
ofile = new TFile(outfile.c_str(),"recreate");
|
||||||
|
filetype = TFILE;
|
||||||
|
}
|
||||||
|
barrier_count=0;
|
||||||
|
barrier_limit=1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HistPlotter::FillN_All_Histograms() {
|
||||||
|
for(auto it=oMap.begin(); it!=oMap.end(); it++ ) {
|
||||||
|
//it->first is std::string 'name', it->second is the TObject
|
||||||
|
if(it->second->InheritsFrom("TH1F")) {
|
||||||
|
//FillN(size, array-of-doubles, array-of-weights); //we set array-of-weights to (1,1,1,.. (size)
|
||||||
|
static_cast<TH1F*>(it->second)->FillN(onedimcache[it->first].size(), //size
|
||||||
|
onedimcache[it->first].data(), //array
|
||||||
|
std::vector<double>(onedimcache[it->first].size(),1.0).data()); //weight of ones
|
||||||
|
onedimcache[it->first].clear();
|
||||||
|
} else if(it->second->InheritsFrom("TH2F")) {
|
||||||
|
//FillN(size, array-of-doubles, array-of-weights); //we set array-of-weights to (1,1,1,.. (size))
|
||||||
|
static_cast<TH2F*>(it->second)->FillN(twodimcache[it->first].first.size(), //size
|
||||||
|
twodimcache[it->first].first.data(), //x array
|
||||||
|
twodimcache[it->first].second.data(), //y array
|
||||||
|
std::vector<double>(twodimcache[it->first].first.size(),1.0).data()); //weight of ones
|
||||||
|
twodimcache[it->first].first.clear();
|
||||||
|
twodimcache[it->first].second.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::cout << "." << std::endl;
|
||||||
|
}
|
||||||
|
void HistPlotter::FlushToDisk() {
|
||||||
|
/*! \fn void FlushToDisk()
|
||||||
|
\brief Function that can be used at any point to exit smoothly by saving all ROOT objects in memory
|
||||||
|
to the output file before closing it. Obeys the binding of histograms to separate folders, if so specified.
|
||||||
|
\return No return -- void
|
||||||
|
*/
|
||||||
|
if(filetype==TMEMFILE && omfile) {
|
||||||
|
std::cout << "Not flushing a TMemfile .. exiting .." << std::endl;
|
||||||
|
delete omfile;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(ofile->IsZombie() || !ofile) {
|
||||||
|
std::cerr << "Output file is zombie, finishing up without writing to disk!" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
FillN_All_Histograms();
|
||||||
|
for(auto it=oMap.begin(); it!=oMap.end(); it++ ) {
|
||||||
|
//omap maps: name(first) to object address(second).
|
||||||
|
// foldersForObjects maps: object address(first) to foldername(second)
|
||||||
|
auto result = foldersForObjects.find(it->second); //returns <TObject* histogram,std::string foldername> pair if found
|
||||||
|
if(result!=foldersForObjects.end()) { //we try to create folder if needed and cd to it
|
||||||
|
ofile->mkdir(result->second.c_str(),"",kTRUE); // args: name, title, returnExistingDirectory
|
||||||
|
ofile->cd(result->second.c_str());
|
||||||
|
} else {
|
||||||
|
ofile->cd(); //toplevel for all default histograms. Default setting
|
||||||
|
}
|
||||||
|
it->second->Write();
|
||||||
|
}
|
||||||
|
|
||||||
|
//Create a directory for all cuts, and save all cuts in them
|
||||||
|
ofile->mkdir("gCUTS","",kTRUE);
|
||||||
|
ofile->cd("gCUTS");
|
||||||
|
for(auto it=cutsMap.begin(); it!=cutsMap.end(); it++) {
|
||||||
|
(static_cast<TNamed*>(it->second))->SetName(it->first.c_str());
|
||||||
|
it->second->Write();
|
||||||
|
}
|
||||||
|
ofile->Close();
|
||||||
|
std::cout << "Wrote " << oMap.size() << " histograms to TFile " << std::string(ofile->GetName()) << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HistPlotter::FillGraph(const std::string& name, float valuex, float valuey, float errx, float erry) {
|
||||||
|
/*! \fn void FillGraph()
|
||||||
|
\brief
|
||||||
|
- Creates a TGraphError in memory with name 'name' if it doesn't exist, and fills it with valuex, valuey
|
||||||
|
- Writes present state to disk and fails with return value -1 if the name clashes with another object that's not of type TGraph*
|
||||||
|
|
||||||
|
\param name name of the TGraph
|
||||||
|
\param valuex The xvalue
|
||||||
|
\param valuey The yvalue
|
||||||
|
\param errx The x error
|
||||||
|
\param erry The y error
|
||||||
|
\return No return void
|
||||||
|
*/
|
||||||
|
auto result = oMap.find(name);
|
||||||
|
if(result==oMap.end()) {
|
||||||
|
TGraphErrors *tempG = new TGraphErrors();
|
||||||
|
tempG->SetName(name.c_str());
|
||||||
|
oMap.insert(std::make_pair(name,static_cast<TObject*>(tempG)));
|
||||||
|
}
|
||||||
|
if(!oMap.at(name)->InheritsFrom("TGraphErrors")) {
|
||||||
|
std::cerr << "Object " << name << " refers to something other than a TGraph*, not filling it hence!" << std::endl;
|
||||||
|
std::cerr << "Abort.." << std::endl;
|
||||||
|
FlushToDisk();
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
// static_cast<TGraphErrors*>(oMap.at(name))->AddPointError(valuex,valuey,errx,erry);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HistPlotter::Fill1D(const std::string& name, int nbinsx, float xlow, float xhigh, float value) {
|
||||||
|
/*! \fn void Fill1D()
|
||||||
|
\brief
|
||||||
|
- Creates a TH1F in memory with name 'name' if it doesn't exist, and fills it with valuex, valuey
|
||||||
|
- Writes present state to disk and fails with return value -1 if the name clashes with another object that's not of type TH1*
|
||||||
|
|
||||||
|
\param name name of the TH1F histogram
|
||||||
|
\param nbinsx Number of bins in the histogram
|
||||||
|
\param xlow Lower limit on x-axis
|
||||||
|
\param xhigh Upper limit on x-axis
|
||||||
|
\param value The bin corresponding to value in (nbinsx, xlow, xhigh) is incremented by 1
|
||||||
|
\return No return void
|
||||||
|
*/
|
||||||
|
auto result = oMap.find(name); //result is an iterator
|
||||||
|
if(result==oMap.end()) {
|
||||||
|
TH1F* temp1D = new TH1F(name.c_str(), name.c_str(), nbinsx, xlow, xhigh);
|
||||||
|
oMap.insert(std::make_pair(name,static_cast<TObject*>(temp1D)));
|
||||||
|
onedimcache.insert(std::make_pair(name, std::vector<double>()));
|
||||||
|
onedimcache[name].reserve(16384);
|
||||||
|
} else if(foldersForObjects.find(oMap.at(name))!=foldersForObjects.end()) { //shouldn't have a folder associated with it
|
||||||
|
std::cerr << "Object " << name << " already registered at " << foldersForObjects[oMap[name]] << ", choose a different name for the histogram to be stored in toplevel .." << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Check if the string 'name' maps to a 1D hist. If there's any other object by this name raise issue
|
||||||
|
if(!oMap.at(name)->InheritsFrom("TH1F")) {
|
||||||
|
std::cerr << "Object " << name << " refers to something other than a TH1*, not filling it hence!" << std::endl;
|
||||||
|
std::cerr << "Abort.." << std::endl;
|
||||||
|
FlushToDisk();
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
onedimcache[name].emplace_back(value);
|
||||||
|
//static_cast<TH1F*>(oMap.at(name))->Fill(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HistPlotter::Fill1D(const std::string& name, int nbinsx, float xlow, float xhigh, float value, const std::string& foldername) {
|
||||||
|
/*! \fn void Fill1D()
|
||||||
|
\brief
|
||||||
|
- Creates a TH1F in memory with name 'name' if it doesn't exist, and fills it with valuex, valuey
|
||||||
|
- Writes present state to disk and fails with return value -1 if the name clashes with another object that's not of type TH1*
|
||||||
|
- Remembers the foldername this particular histogram maps to, if provided. If not, defaults to toplevel.
|
||||||
|
|
||||||
|
\param name name of the TH1F histogram
|
||||||
|
\param nbinsx Number of bins in the histogram
|
||||||
|
\param xlow Lower limit on x-axis
|
||||||
|
\param xhigh Upper limit on x-axis
|
||||||
|
\param value The bin corresponding to value in (nbinsx, xlow, xhigh) is incremented by 1
|
||||||
|
\param foldername Name of the folder to put this histogram into. Defaults to toplevel if left empty
|
||||||
|
\return No return -- void
|
||||||
|
*/
|
||||||
|
|
||||||
|
auto result = oMap.find(name); //result is an iterator
|
||||||
|
if(result==oMap.end()) {
|
||||||
|
TH1F* temp1D = new TH1F(name.c_str(), name.c_str(), nbinsx, xlow, xhigh);
|
||||||
|
oMap.insert(std::make_pair(name,static_cast<TObject*>(temp1D)));
|
||||||
|
onedimcache.insert(std::make_pair(name, std::vector<double>()));
|
||||||
|
onedimcache[name].reserve(16384);
|
||||||
|
if(foldername!="") {
|
||||||
|
if(folderList.find(foldername)==folderList.end()) {
|
||||||
|
folderList.insert(foldername);
|
||||||
|
}
|
||||||
|
foldersForObjects.insert(std::make_pair(static_cast<TObject*>(temp1D),foldername));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//object is present in map, but we enforce unique names
|
||||||
|
//it must already have a folder attached to it
|
||||||
|
if(foldersForObjects.find(oMap.at(name))==foldersForObjects.end()) {
|
||||||
|
std::cerr << "Object " << name << " already registered at toplevel, choose a different name for the histogram to be stored in " << foldername << " folder .." << std::endl;
|
||||||
|
} else if(foldersForObjects[oMap[name]]!=foldername) {
|
||||||
|
std::cerr << "Object " << name << " already registered at " << foldersForObjects[oMap[name]] << ", choose a different name for the histogram to be stored in " << foldername << " folder .." << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//Check if the string 'name' maps to a 1D hist. If there's any other object by this name raise issue
|
||||||
|
if(!oMap.at(name)->InheritsFrom("TH1F")) {
|
||||||
|
std::cerr << "Object " << name << " refers to something other than a TH1*, not filling it hence!" << std::endl;
|
||||||
|
std::cerr << "Abort.." << std::endl;
|
||||||
|
FlushToDisk();
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
onedimcache[name].emplace_back(value);
|
||||||
|
//static_cast<TH1F*>(oMap.at(name))->Fill(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HistPlotter::Fill2D(const std::string& name, int nbinsx, float xlow, float xhigh, int nbinsy, float ylow, float yhigh, float valuex, float valuey) {
|
||||||
|
/*! \fn void Fill2D()
|
||||||
|
\brief
|
||||||
|
- Creates a TH2F in memory with name 'name' if it doesn't exist, and fills it with valuex, valuey
|
||||||
|
- Writes present state to disk and fails with return value -1 if the name clashes with another object that's not of type TH2*
|
||||||
|
\param name name of the TH1F histogram
|
||||||
|
\param nbinsx Number of xbins in the histogram
|
||||||
|
\param xlow Lower limit on x-axis
|
||||||
|
\param xhigh Upper limit on x-axis
|
||||||
|
\param nbinsy Number of ybins in the histogram
|
||||||
|
\param ylow Lower limit on y-axis
|
||||||
|
\param yhigh Upper limit on y-axis
|
||||||
|
\param valuex
|
||||||
|
\param valuey The bin corresponding to (valuex, valuey) in (nbinsx, xlow, xhigh, ybinsx, ylow, yhigh) is incremented by 1
|
||||||
|
\return No return -- void
|
||||||
|
*/
|
||||||
|
|
||||||
|
auto result = oMap.find(name); //result is an iterator
|
||||||
|
if(result==oMap.end()) {
|
||||||
|
TH2F* temp2D = new TH2F(name.c_str(), name.c_str(), nbinsx, xlow, xhigh, nbinsy, ylow, yhigh);
|
||||||
|
oMap.insert(std::make_pair(name,static_cast<TObject*>(temp2D)));
|
||||||
|
twodimcache.insert(std::make_pair(name, std::make_pair(std::vector<double>(),std::vector<double>())));
|
||||||
|
twodimcache[name].first.reserve(16384);
|
||||||
|
twodimcache[name].second.reserve(16384);
|
||||||
|
} else if(foldersForObjects.find(oMap.at(name))!=foldersForObjects.end()) { //shouldn't have a folder associated with it
|
||||||
|
std::cerr << "Object " << name << " already registered at " << foldersForObjects[oMap[name]] << ", choose a different name for the histogram to be stored in toplevel .." << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Check if the string 'name' maps to a 1D hist. If there's any other object by this name raise issue
|
||||||
|
if(!oMap.at(name)->InheritsFrom("TH2F")) {
|
||||||
|
std::cerr << "Object " << name << " refers to something other than a TH2*, not filling it hence!" << std::endl;
|
||||||
|
std::cerr << "Abort.." << std::endl;
|
||||||
|
FlushToDisk();
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
twodimcache[name].first.emplace_back(valuex);
|
||||||
|
twodimcache[name].second.emplace_back(valuey);
|
||||||
|
//static_cast<TH2F*>(oMap.at(name))->Fill(valuex,valuey);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HistPlotter::Fill2D(const std::string& name, int nbinsx, float xlow, float xhigh, int nbinsy, float ylow, float yhigh, float valuex, float valuey, const std::string& foldername) {
|
||||||
|
/*! \fn void Fill2D()
|
||||||
|
\brief
|
||||||
|
- Creates a TH2F in memory with name 'name' if it doesn't exist, and fills it with valuex, valuey
|
||||||
|
- Writes present state to disk and fails with return value -1 if the name clashes with another object that's not of type TH2*
|
||||||
|
- Remembers the foldername this particular histogram maps to, if provided. If not defaults to toplevel
|
||||||
|
|
||||||
|
\param name name of the TH1F histogram
|
||||||
|
\param nbinsx Number of xbins in the histogram
|
||||||
|
\param xlow Lower limit on x-axis
|
||||||
|
\param xhigh Upper limit on x-axis
|
||||||
|
\param nbinsy Number of ybins in the histogram
|
||||||
|
\param ylow Lower limit on y-axis
|
||||||
|
\param yhigh Upper limit on y-axis
|
||||||
|
\param valuex
|
||||||
|
\param valuey The bin corresponding to (valuex, valuey) in (nbinsx, xlow, xhigh, ybinsx, ylow, yhigh) is incremented by 1
|
||||||
|
\param foldername Name of the folder to put this histogram into. Defaults to toplevel if left empty
|
||||||
|
\return No return -- void
|
||||||
|
*/
|
||||||
|
|
||||||
|
auto result = oMap.find(name); //result is an iterator
|
||||||
|
if(result==oMap.end()) {
|
||||||
|
TH2F* temp2D = new TH2F(name.c_str(), name.c_str(), nbinsx, xlow, xhigh, nbinsy, ylow, yhigh);
|
||||||
|
oMap.insert(std::make_pair(name,static_cast<TObject*>(temp2D)));
|
||||||
|
twodimcache.insert(std::make_pair(name, std::make_pair(std::vector<double>(),std::vector<double>())));
|
||||||
|
twodimcache[name].first.reserve(16384);
|
||||||
|
twodimcache[name].second.reserve(16384);
|
||||||
|
if(foldername!="") {
|
||||||
|
if(folderList.find(foldername)==folderList.end()) {
|
||||||
|
folderList.insert(foldername);
|
||||||
|
}
|
||||||
|
foldersForObjects.insert(std::make_pair(static_cast<TObject*>(temp2D),foldername));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//object is present in map, but we enforce unique names
|
||||||
|
//it must already have a folder attached to it
|
||||||
|
if(foldersForObjects.find(oMap.at(name))==foldersForObjects.end()) {
|
||||||
|
std::cerr << "Object " << name << " already registered at toplevel, choose a different name for the histogram to be stored in " << foldername << " folder .." << std::endl;
|
||||||
|
} else if(foldersForObjects[oMap.at(name)]!=foldername) {
|
||||||
|
std::cerr << "Object " << name << " already registered at " << foldersForObjects[oMap[name]] << ", choose a different name for the histogram to be stored in " << foldername << " folder .." << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Check if the string 'name' maps to a 1D hist. If there's any other object by this name raise issue
|
||||||
|
if(!oMap.at(name)->InheritsFrom("TH2F")) {
|
||||||
|
std::cerr << "Object " << name << " refers to something other than a TH2*, not filling it hence!" << std::endl;
|
||||||
|
std::cerr << "Abort.." << std::endl;
|
||||||
|
FlushToDisk();
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
twodimcache[name].first.emplace_back(valuex);
|
||||||
|
twodimcache[name].second.emplace_back(valuey);
|
||||||
|
//static_cast<TH2F*>(oMap.at(name))->Fill(valuex,valuey);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HistPlotter::ReadCuts(std::string filename) {
|
||||||
|
/*! \fn void ReadCuts()
|
||||||
|
\brief Reads a list of cuts from a file. The file must have the format below, two columns
|
||||||
|
- Column#1 - path to a file that contains a single TCutG object named "CUTG", the default name in ROOT.
|
||||||
|
- Column#2 - The identifier name you plan to use in the code, like 'protonbarrelpid' or something, that will be searched by FindCut()
|
||||||
|
\param filename name of the plainxtext file containing the cut file locations and identifiers
|
||||||
|
\return No return -- void
|
||||||
|
*/
|
||||||
|
|
||||||
|
std::ifstream infile;
|
||||||
|
infile.open(filename);
|
||||||
|
std::string cutfilename, cutname;
|
||||||
|
for(std::string line; std::getline(infile, line); ) {
|
||||||
|
if(line.size()!=0 && line[0]=='#')
|
||||||
|
; //don't do anything with '#' lines
|
||||||
|
else {
|
||||||
|
std::stringstream ss(line);
|
||||||
|
ss>>cutfilename>>cutname;
|
||||||
|
|
||||||
|
TFile f(cutfilename.c_str());
|
||||||
|
if(f.IsZombie()) {
|
||||||
|
std::cerr << "Cannot open cutfile " << cutfilename << " .. skipping.." << std::endl;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
TCutG *cut = (TCutG*)(f.Get("CUTG"));
|
||||||
|
cutsMap.insert(std::make_pair(cutname,static_cast<TObject*>(cut)));
|
||||||
|
f.Close();
|
||||||
|
} //else
|
||||||
|
}//for loop
|
||||||
|
infile.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
void HistPlotter::PrintObjects() {
|
||||||
|
/*
|
||||||
|
void PrintObjects()
|
||||||
|
Prints the contents of the unordered_maps oMap and cutsMap to facilitate debugging
|
||||||
|
|
||||||
|
*/
|
||||||
|
std::cout << "Type | Name " << std::endl;
|
||||||
|
std::cout << "---- | --------------------- " << std::endl;
|
||||||
|
for(auto it=oMap.begin(); it!=oMap.end(); it++ ) {
|
||||||
|
std::cout << it->second->ClassName() << " | "<< it->first << std::endl;
|
||||||
|
}
|
||||||
|
for(auto it=cutsMap.begin(); it!=cutsMap.end(); it++ ) {
|
||||||
|
std::cout << it->second->ClassName() << " | "<< it->first << std::endl;
|
||||||
|
}
|
||||||
|
std::cout << "---- | --------------------- " << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
522
Armory/Armory/Isotope.h
Normal file
522
Armory/Armory/Isotope.h
Normal file
|
|
@ -0,0 +1,522 @@
|
||||||
|
/***********************************************************************
|
||||||
|
*
|
||||||
|
* This is Isotope.h, To extract the isotope mass from massXX.txt
|
||||||
|
*
|
||||||
|
*-------------------------------------------------------
|
||||||
|
* created by Ryan (Tsz Leung) Tang, Nov-18, 2018
|
||||||
|
* email: goluckyryan@gmail.com
|
||||||
|
* ********************************************************************/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef ISOTOPE_H
|
||||||
|
#define ISOTOPE_H
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <string>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include "constant.h" // amu
|
||||||
|
#include <stdlib.h> //atoi
|
||||||
|
#include <algorithm>
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
|
string massData="mass20.txt";
|
||||||
|
|
||||||
|
// about the mass**.txt
|
||||||
|
// Mass Excess = (ATOMIC MASS - A)*amu | e.g. n : (1.088664.91585E-6-1)*amu
|
||||||
|
// mass excess uncertaintly
|
||||||
|
// BEA = (Z*M(1H) + N*M(1n) - Me(A,Z))/A , Me is the mass with electrons
|
||||||
|
// BEA = (Z*mp + N*mn - M(A,Z))/A , M is the mass without electrons
|
||||||
|
|
||||||
|
class Isotope {
|
||||||
|
public:
|
||||||
|
int A, Z;
|
||||||
|
double Mass, MassError, BEA;
|
||||||
|
string Name, Symbol;
|
||||||
|
string dataSource;
|
||||||
|
|
||||||
|
Isotope(){ dataSource = massData; };
|
||||||
|
Isotope(int a, int z){ dataSource = massData; SetIso(a,z); };
|
||||||
|
Isotope(string name){ dataSource = massData; SetIsoByName(name); };
|
||||||
|
|
||||||
|
void SetIso(int a, int z);
|
||||||
|
void SetIsoByName(string name);
|
||||||
|
|
||||||
|
double CalSp(int Np, int Nn); // this for the Np-proton, Nn-neutron removal
|
||||||
|
double CalSp2(int a, int z); // this is for (a,z) nucleus removal
|
||||||
|
|
||||||
|
double CalBeta(double T){
|
||||||
|
// double Etot = Mass + T;
|
||||||
|
double gamma = 1 + T/Mass;
|
||||||
|
double beta = sqrt(1 - 1 / gamma / gamma ) ;
|
||||||
|
return beta;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Print();
|
||||||
|
void ListShell();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void FindMassByAZ(int a, int z); // give mass, massError, BEA, Name, Symbol;
|
||||||
|
void FindMassByName(string name); // give Z, mass, massError, BEA;
|
||||||
|
|
||||||
|
int TwoJ(int nShell);
|
||||||
|
string Orbital(int nShell);
|
||||||
|
int magic(int i){
|
||||||
|
switch (i){
|
||||||
|
case 0: return 2; break;
|
||||||
|
case 1: return 8; break;
|
||||||
|
case 2: return 20; break;
|
||||||
|
case 3: return 28; break;
|
||||||
|
case 4: return 40; break;
|
||||||
|
case 5: return 50; break;
|
||||||
|
case 6: return 82; break;
|
||||||
|
case 7: return 128; break;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int magicShellID(int i){
|
||||||
|
switch (i){
|
||||||
|
case 0: return 0; break;
|
||||||
|
case 1: return 2; break;
|
||||||
|
case 2: return 5; break;
|
||||||
|
case 3: return 6; break;
|
||||||
|
case 4: return 9; break;
|
||||||
|
case 5: return 10; break;
|
||||||
|
case 6: return 15; break;
|
||||||
|
case 7: return 21; break;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int fileStartLine;
|
||||||
|
int fileEndLine;
|
||||||
|
int lineMass050_099;
|
||||||
|
int lineMass100_149;
|
||||||
|
int lineMass150_199;
|
||||||
|
int lineMass200;
|
||||||
|
|
||||||
|
|
||||||
|
void setFileLines(){
|
||||||
|
fileStartLine = 37;
|
||||||
|
fileEndLine = 3594;
|
||||||
|
|
||||||
|
lineMass050_099 = 466;
|
||||||
|
lineMass100_149 = 1160;
|
||||||
|
lineMass150_199 = 1994;
|
||||||
|
lineMass200 = 2774;
|
||||||
|
}
|
||||||
|
|
||||||
|
char * heliosPath;
|
||||||
|
bool isFindOnce;
|
||||||
|
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
inline void Isotope::SetIso(int a, int z){
|
||||||
|
this->A = a;
|
||||||
|
this->Z = z;
|
||||||
|
FindMassByAZ(a,z);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void Isotope::SetIsoByName(string name){
|
||||||
|
FindMassByName(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void Isotope::FindMassByAZ(int A, int Z){
|
||||||
|
string line;
|
||||||
|
int lineNum=0;
|
||||||
|
int list_A, list_Z;
|
||||||
|
|
||||||
|
ifstream myfile;
|
||||||
|
int flag=0;
|
||||||
|
|
||||||
|
setFileLines();
|
||||||
|
|
||||||
|
int numLineStart = fileStartLine;
|
||||||
|
int numLineEnd = fileEndLine;
|
||||||
|
|
||||||
|
if ( A >= 50 && A < 100) numLineStart = lineMass050_099;
|
||||||
|
if ( A >=100 && A < 150) numLineStart = lineMass100_149;
|
||||||
|
if ( A >=150 && A < 200) numLineStart = lineMass150_199;
|
||||||
|
if ( A >=200 ) numLineStart = lineMass200;
|
||||||
|
|
||||||
|
myfile.open(dataSource.c_str());
|
||||||
|
|
||||||
|
if (myfile.is_open()) {
|
||||||
|
while (/*! myfile.eof() &&*/ flag == 0 && lineNum <numLineEnd){
|
||||||
|
lineNum ++ ;
|
||||||
|
//printf("%3d ",lineNum);
|
||||||
|
getline (myfile,line);
|
||||||
|
|
||||||
|
if (lineNum >= numLineStart ){
|
||||||
|
list_Z = atoi((line.substr(10,5)).c_str());
|
||||||
|
list_A = atoi((line.substr(15,5)).c_str());
|
||||||
|
|
||||||
|
if ( A == list_A && Z == list_Z) {
|
||||||
|
this->BEA = atof((line.substr(54,11)).c_str());
|
||||||
|
this->Mass = list_Z*mp + (list_A-list_Z)*mn - this->BEA/1000*list_A;
|
||||||
|
this->MassError = atof((line.substr(65,7)).c_str());
|
||||||
|
string str = line.substr(20,2);
|
||||||
|
str.erase(remove(str.begin(), str.end(), ' '), str.end());
|
||||||
|
this->Symbol = str;
|
||||||
|
|
||||||
|
ostringstream ss;
|
||||||
|
ss << A << this->Symbol;
|
||||||
|
this->Name = ss.str();
|
||||||
|
flag = 1;
|
||||||
|
}else if ( list_A > A) {
|
||||||
|
this->BEA = -404;
|
||||||
|
this->Mass = -404;
|
||||||
|
this->MassError = -404;
|
||||||
|
this->Symbol = "non";
|
||||||
|
this->Name = "non";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( this->Name == "1H" ) this->Name = "p";
|
||||||
|
if( this->Name == "2H" ) this->Name = "d";
|
||||||
|
if( this->Name == "3H" ) this->Name = "t";
|
||||||
|
if( this->Name == "4He" ) this->Name = "a";
|
||||||
|
|
||||||
|
myfile.close();
|
||||||
|
}else {
|
||||||
|
printf("Unable to open %s\n", dataSource.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void Isotope::FindMassByName(string name){
|
||||||
|
|
||||||
|
// done seperate the Mass number and the name
|
||||||
|
if( name == "n" ) {
|
||||||
|
this->Name = "1n";
|
||||||
|
this->BEA = 0;
|
||||||
|
this->Mass = mn;
|
||||||
|
this->MassError = 0;
|
||||||
|
this->Name = "n";
|
||||||
|
this->A = 1;
|
||||||
|
this->Z = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if( name == "p" ) name = "1H";
|
||||||
|
if( name == "d" ) name = "2H";
|
||||||
|
if( name == "t" ) name = "3H";
|
||||||
|
if( name == "a" ) name = "4He";
|
||||||
|
|
||||||
|
string temp = name;
|
||||||
|
int lastDigit = 0;
|
||||||
|
|
||||||
|
for(int i=0; temp[i]; i++){
|
||||||
|
if(temp[i] == '0') lastDigit = i;
|
||||||
|
if(temp[i] == '1') lastDigit = i;
|
||||||
|
if(temp[i] == '2') lastDigit = i;
|
||||||
|
if(temp[i] == '3') lastDigit = i;
|
||||||
|
if(temp[i] == '4') lastDigit = i;
|
||||||
|
if(temp[i] == '5') lastDigit = i;
|
||||||
|
if(temp[i] == '6') lastDigit = i;
|
||||||
|
if(temp[i] == '7') lastDigit = i;
|
||||||
|
if(temp[i] == '8') lastDigit = i;
|
||||||
|
if(temp[i] == '9') lastDigit = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->Symbol = temp.erase(0, lastDigit +1);
|
||||||
|
//check is Symbol is 2 charaters, if not, add " " at the end
|
||||||
|
if( this->Symbol.length() == 1 ){
|
||||||
|
this->Symbol = this->Symbol + " ";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
temp = name;
|
||||||
|
int len = temp.length();
|
||||||
|
temp = temp.erase(lastDigit+1, len);
|
||||||
|
|
||||||
|
this->A = atoi(temp.c_str());
|
||||||
|
//printf(" Symbol = |%s| , Mass = %d\n", this->Symbol.c_str(), this->A);
|
||||||
|
|
||||||
|
// find the nucleus in the data
|
||||||
|
string line;
|
||||||
|
int lineNum=0;
|
||||||
|
int list_A;
|
||||||
|
string list_symbol;
|
||||||
|
|
||||||
|
ifstream myfile;
|
||||||
|
int flag=0;
|
||||||
|
|
||||||
|
setFileLines();
|
||||||
|
|
||||||
|
int numLineStart = fileStartLine;
|
||||||
|
int numLineEnd = fileEndLine;
|
||||||
|
|
||||||
|
if ( A >= 50 && A < 100) numLineStart = lineMass050_099;
|
||||||
|
if ( A >=100 && A < 150) numLineStart = lineMass100_149;
|
||||||
|
if ( A >=150 && A < 200) numLineStart = lineMass150_199;
|
||||||
|
if ( A >=200 ) numLineStart = lineMass200;
|
||||||
|
|
||||||
|
myfile.open(dataSource.c_str());
|
||||||
|
|
||||||
|
if (myfile.is_open()) {
|
||||||
|
while (/*! myfile.eof() &&*/ flag == 0 && lineNum <numLineEnd){
|
||||||
|
lineNum ++ ;
|
||||||
|
//printf("%3d ",lineNum);
|
||||||
|
getline (myfile,line);
|
||||||
|
|
||||||
|
if (lineNum >= numLineStart ){
|
||||||
|
list_symbol = line.substr(20,2);
|
||||||
|
list_A = atoi((line.substr(15,5)).c_str());
|
||||||
|
|
||||||
|
//printf(" A = %d, Sym = |%s| \n", list_A, list_symbol.c_str());
|
||||||
|
|
||||||
|
if ( this->A == list_A && this->Symbol == list_symbol) {
|
||||||
|
this->Z = atoi((line.substr(10,5)).c_str());
|
||||||
|
this->BEA = atof((line.substr(54,11)).c_str());
|
||||||
|
this->Mass = this->Z*mp + (list_A-this->Z)*mn - this->BEA/1000*list_A;
|
||||||
|
this->MassError = atof((line.substr(65,7)).c_str());
|
||||||
|
|
||||||
|
string str = line.substr(20,2);
|
||||||
|
str.erase(remove(str.begin(), str.end(), ' '), str.end());
|
||||||
|
this->Symbol = str;
|
||||||
|
|
||||||
|
ostringstream ss;
|
||||||
|
ss << this->A << this->Symbol;
|
||||||
|
this->Name = ss.str();
|
||||||
|
flag = 1;
|
||||||
|
}else if ( list_A > this->A) {
|
||||||
|
this->BEA = -404;
|
||||||
|
this->Mass = -404;
|
||||||
|
this->MassError = -404;
|
||||||
|
this->Symbol = "non";
|
||||||
|
this->Name = "non";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
myfile.close();
|
||||||
|
}else {
|
||||||
|
printf("Unable to open %s\n", dataSource.c_str());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline double Isotope::CalSp(int Np, int Nn){
|
||||||
|
Isotope nucleusD(A - Np - Nn, Z - Np);
|
||||||
|
|
||||||
|
if( nucleusD.Mass != -404){
|
||||||
|
return nucleusD.Mass + Nn*mn + Np*mp - this->Mass;
|
||||||
|
}else{
|
||||||
|
return -404;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline double Isotope::CalSp2(int a, int z){
|
||||||
|
Isotope nucleusD(A - a , Z - z);
|
||||||
|
Isotope nucleusS(a,z);
|
||||||
|
|
||||||
|
if( nucleusD.Mass != -404 && nucleusS.Mass != -404){
|
||||||
|
return nucleusD.Mass + nucleusS.Mass - this->Mass;
|
||||||
|
}else{
|
||||||
|
return -404;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int Isotope::TwoJ(int nShell){
|
||||||
|
|
||||||
|
switch(nShell){
|
||||||
|
case 0: return 1; break; // 0s1/2
|
||||||
|
case 1: return 3; break; // 0p3/2
|
||||||
|
case 2: return 1; break; // 0p1/2 -- 8
|
||||||
|
case 3: return 5; break; // 0d5/2
|
||||||
|
case 4: return 1; break; // 1s1/2
|
||||||
|
case 5: return 3; break; // 0d3/2 -- 20
|
||||||
|
case 6: return 7; break; // 0f7/2 -- 28
|
||||||
|
case 7: return 3; break; // 1p3/2
|
||||||
|
case 8: return 1; break; // 1p1/2
|
||||||
|
case 9: return 5; break; // 0f5/2 -- 40
|
||||||
|
case 10: return 9; break; // 0g9/2 -- 50
|
||||||
|
case 11: return 7; break; // 0g7/2
|
||||||
|
case 12: return 5; break; // 1d5/2
|
||||||
|
case 13: return 11; break; // 0h11/2
|
||||||
|
case 14: return 3; break; // 1d3/2
|
||||||
|
case 15: return 1; break; // 2s1/2 -- 82
|
||||||
|
case 16: return 9; break; // 0h9/2
|
||||||
|
case 17: return 7; break; // 1f7/2
|
||||||
|
case 18: return 13; break; // 0i13/2
|
||||||
|
case 19: return 3; break; // 2p3/2
|
||||||
|
case 20: return 5; break; // 1f5/2
|
||||||
|
case 21: return 1; break; // 1p1/2 -- 126
|
||||||
|
case 22: return 9; break; // 1g9/2
|
||||||
|
case 23: return 11; break; // 0i11/2
|
||||||
|
case 24: return 15; break; // 0j15/2
|
||||||
|
case 25: return 5; break; // 2d5/2
|
||||||
|
case 26: return 1; break; // 3s1/2
|
||||||
|
case 27: return 3; break; // 2d3/2
|
||||||
|
case 28: return 7; break; // 1g7/2
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline string Isotope::Orbital(int nShell){
|
||||||
|
|
||||||
|
switch(nShell){
|
||||||
|
case 0: return "0s1 "; break; //
|
||||||
|
case 1: return "0p3 "; break; //
|
||||||
|
case 2: return "0p1 "; break; //-- 8
|
||||||
|
case 3: return "0d5 "; break; //
|
||||||
|
case 4: return "1s1 "; break; //
|
||||||
|
case 5: return "0d3 "; break; //-- 20
|
||||||
|
case 6: return "0f7 "; break; //-- 28
|
||||||
|
case 7: return "1p3 "; break; //
|
||||||
|
case 8: return "1p1 "; break; //
|
||||||
|
case 9: return "0f5 "; break; //-- 40
|
||||||
|
case 10: return "0g9 "; break; //-- 50
|
||||||
|
case 11: return "0g7 "; break; //
|
||||||
|
case 12: return "1d5 "; break; //
|
||||||
|
case 13: return "0h11"; break; //
|
||||||
|
case 14: return "1d3 "; break; //
|
||||||
|
case 15: return "2s1 "; break; //-- 82
|
||||||
|
case 16: return "0h9 "; break; //
|
||||||
|
case 17: return "1f7 "; break; //
|
||||||
|
case 18: return "0i13"; break; //
|
||||||
|
case 19: return "2p3 "; break; //
|
||||||
|
case 20: return "1f5 "; break; //
|
||||||
|
case 21: return "1p1 "; break; //-- 126
|
||||||
|
case 22: return "1g9 "; break; //
|
||||||
|
case 23: return "0i11"; break; //
|
||||||
|
case 24: return "0j15"; break; //
|
||||||
|
case 25: return "2d5 "; break; //
|
||||||
|
case 26: return "3s1 "; break; //
|
||||||
|
case 27: return "2d3 "; break; //
|
||||||
|
case 28: return "1g7 "; break; //
|
||||||
|
}
|
||||||
|
|
||||||
|
return "nan";
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void Isotope::ListShell(){
|
||||||
|
|
||||||
|
if( Mass < 0 ) return;
|
||||||
|
|
||||||
|
int n = A-Z;
|
||||||
|
int p = Z;
|
||||||
|
|
||||||
|
int k = std::min(n,p);
|
||||||
|
int nMagic = 0;
|
||||||
|
for( int i = 0; i < 7; i++){
|
||||||
|
if( magic(i) < k && k <= magic(i+1) ){
|
||||||
|
nMagic = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int coreShell = magicShellID(nMagic-1);
|
||||||
|
int coreZ1 = magic(nMagic-1);
|
||||||
|
int coreZ2 = magic(nMagic);
|
||||||
|
|
||||||
|
Isotope core1( 2*coreZ1, coreZ1);
|
||||||
|
Isotope core2( 2*coreZ2, coreZ2);
|
||||||
|
|
||||||
|
printf("------------------ Core:%3s, inner Core:%3s \n", (core2.Name).c_str(), (core1.Name).c_str());
|
||||||
|
printf(" || ");
|
||||||
|
int t = std::max(n,p);
|
||||||
|
int nShell = 0;
|
||||||
|
do{
|
||||||
|
int occ = TwoJ(nShell)+1;
|
||||||
|
if( nShell > coreShell) {
|
||||||
|
printf("%4s", Orbital(nShell).c_str());
|
||||||
|
if( nShell == 0 || nShell == 2 || nShell == 5 || nShell ==6 || nShell == 9 || nShell == 10 || nShell == 15 || nShell == 21){
|
||||||
|
printf("|");
|
||||||
|
}else{
|
||||||
|
printf(",");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
t = t - occ;
|
||||||
|
nShell++;
|
||||||
|
}while( t > 0 && nShell < 29);
|
||||||
|
for( int i = 1; i <= 6; i++){
|
||||||
|
if (nShell < 28) {
|
||||||
|
printf("%4s,", Orbital(nShell).c_str());
|
||||||
|
}else if( nShell == 28 ) {
|
||||||
|
printf("%4s", Orbital(nShell).c_str());
|
||||||
|
}
|
||||||
|
nShell ++;
|
||||||
|
}
|
||||||
|
if (nShell < 29) printf("%4s", Orbital(nShell).c_str());
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
|
||||||
|
printf(" Z = %3d || ", p);
|
||||||
|
nShell = 0;
|
||||||
|
do{
|
||||||
|
int occ = TwoJ(nShell)+1;
|
||||||
|
if( nShell > coreShell ){
|
||||||
|
if( p > occ ) {
|
||||||
|
printf("%-4d", occ);
|
||||||
|
if( nShell == 0 || nShell == 2 || nShell == 5 || nShell ==6 || nShell == 9 || nShell == 10 || nShell == 15 || nShell == 21){
|
||||||
|
printf("|");
|
||||||
|
}else{
|
||||||
|
printf(",");
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
printf("%-4d", p);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
p = p - occ;
|
||||||
|
nShell++;
|
||||||
|
}while( p > 0 && nShell < 29);
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
printf(" N = %3d || ", n);
|
||||||
|
nShell = 0;
|
||||||
|
do{
|
||||||
|
int occ = TwoJ(nShell)+1;
|
||||||
|
if ( nShell > coreShell ){
|
||||||
|
if( n > occ ) {
|
||||||
|
printf("%-4d", occ);
|
||||||
|
if( nShell == 0 || nShell == 2 || nShell == 5 || nShell ==6 || nShell == 9 || nShell == 10 || nShell == 15 || nShell == 21){
|
||||||
|
printf("|");
|
||||||
|
}else{
|
||||||
|
printf(",");
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
printf("%-4d", n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
n = n - occ;
|
||||||
|
nShell++;
|
||||||
|
}while( n > 0 && nShell < 29);
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
printf("------------------ \n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void Isotope::Print(){
|
||||||
|
|
||||||
|
if (Mass > 0){
|
||||||
|
|
||||||
|
dataSource = massData;
|
||||||
|
|
||||||
|
printf(" using mass data : %s \n", dataSource.c_str());
|
||||||
|
printf(" mass of \e[47m\e[31m%s\e[m nucleus (Z,A)=(%3d,%3d) is \e[47m\e[31m%12.5f\e[m MeV, BE/A=%7.5f MeV\n", Name.c_str(), Z, A, Mass, BEA/1000.);
|
||||||
|
printf(" total BE : %12.5f MeV\n",BEA*A/1000.);
|
||||||
|
printf(" mass in amu : %12.5f u\n",Mass/amu);
|
||||||
|
printf(" mass excess : %12.5f MeV\n", Mass + Z*0.510998950 - A*amu);
|
||||||
|
printf("-------------- Seperation energy \n");
|
||||||
|
printf(" S1p: %8.4f| S1n: %8.4f| S(2H ): %8.4f| S1p1n : %8.4f\n", CalSp(1, 0), CalSp(0, 1), CalSp2(2, 1), CalSp(1, 1));
|
||||||
|
printf(" S2p: %8.4f| S2n: %8.4f| S(3He): %8.4f| S(3H) : %8.4f\n", CalSp(2, 0), CalSp(0, 2), CalSp2(3, 2), CalSp2(3, 1));
|
||||||
|
printf(" S3p: %8.4f| S3n: %8.4f| S(4He): %8.4f|\n", CalSp(3, 0), CalSp(0, 3), CalSp2(4, 2));
|
||||||
|
printf(" S4p: %8.4f| S4n: %8.4f| \n", CalSp(4, 0), CalSp(0, 4));
|
||||||
|
|
||||||
|
}else{
|
||||||
|
printf("Error %6.0f, no nucleus with (Z,A) = (%3d,%3d). \n", Mass, Z, A);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
674
Armory/Armory/LICENSE
Normal file
674
Armory/Armory/LICENSE
Normal file
|
|
@ -0,0 +1,674 @@
|
||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
Version 3, 29 June 2007
|
||||||
|
|
||||||
|
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The GNU General Public License is a free, copyleft license for
|
||||||
|
software and other kinds of works.
|
||||||
|
|
||||||
|
The licenses for most software and other practical works are designed
|
||||||
|
to take away your freedom to share and change the works. By contrast,
|
||||||
|
the GNU General Public License is intended to guarantee your freedom to
|
||||||
|
share and change all versions of a program--to make sure it remains free
|
||||||
|
software for all its users. We, the Free Software Foundation, use the
|
||||||
|
GNU General Public License for most of our software; it applies also to
|
||||||
|
any other work released this way by its authors. You can apply it to
|
||||||
|
your programs, too.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom, not
|
||||||
|
price. Our General Public Licenses are designed to make sure that you
|
||||||
|
have the freedom to distribute copies of free software (and charge for
|
||||||
|
them if you wish), that you receive source code or can get it if you
|
||||||
|
want it, that you can change the software or use pieces of it in new
|
||||||
|
free programs, and that you know you can do these things.
|
||||||
|
|
||||||
|
To protect your rights, we need to prevent others from denying you
|
||||||
|
these rights or asking you to surrender the rights. Therefore, you have
|
||||||
|
certain responsibilities if you distribute copies of the software, or if
|
||||||
|
you modify it: responsibilities to respect the freedom of others.
|
||||||
|
|
||||||
|
For example, if you distribute copies of such a program, whether
|
||||||
|
gratis or for a fee, you must pass on to the recipients the same
|
||||||
|
freedoms that you received. You must make sure that they, too, receive
|
||||||
|
or can get the source code. And you must show them these terms so they
|
||||||
|
know their rights.
|
||||||
|
|
||||||
|
Developers that use the GNU GPL protect your rights with two steps:
|
||||||
|
(1) assert copyright on the software, and (2) offer you this License
|
||||||
|
giving you legal permission to copy, distribute and/or modify it.
|
||||||
|
|
||||||
|
For the developers' and authors' protection, the GPL clearly explains
|
||||||
|
that there is no warranty for this free software. For both users' and
|
||||||
|
authors' sake, the GPL requires that modified versions be marked as
|
||||||
|
changed, so that their problems will not be attributed erroneously to
|
||||||
|
authors of previous versions.
|
||||||
|
|
||||||
|
Some devices are designed to deny users access to install or run
|
||||||
|
modified versions of the software inside them, although the manufacturer
|
||||||
|
can do so. This is fundamentally incompatible with the aim of
|
||||||
|
protecting users' freedom to change the software. The systematic
|
||||||
|
pattern of such abuse occurs in the area of products for individuals to
|
||||||
|
use, which is precisely where it is most unacceptable. Therefore, we
|
||||||
|
have designed this version of the GPL to prohibit the practice for those
|
||||||
|
products. If such problems arise substantially in other domains, we
|
||||||
|
stand ready to extend this provision to those domains in future versions
|
||||||
|
of the GPL, as needed to protect the freedom of users.
|
||||||
|
|
||||||
|
Finally, every program is threatened constantly by software patents.
|
||||||
|
States should not allow patents to restrict development and use of
|
||||||
|
software on general-purpose computers, but in those that do, we wish to
|
||||||
|
avoid the special danger that patents applied to a free program could
|
||||||
|
make it effectively proprietary. To prevent this, the GPL assures that
|
||||||
|
patents cannot be used to render the program non-free.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow.
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
0. Definitions.
|
||||||
|
|
||||||
|
"This License" refers to version 3 of the GNU General Public License.
|
||||||
|
|
||||||
|
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||||
|
works, such as semiconductor masks.
|
||||||
|
|
||||||
|
"The Program" refers to any copyrightable work licensed under this
|
||||||
|
License. Each licensee is addressed as "you". "Licensees" and
|
||||||
|
"recipients" may be individuals or organizations.
|
||||||
|
|
||||||
|
To "modify" a work means to copy from or adapt all or part of the work
|
||||||
|
in a fashion requiring copyright permission, other than the making of an
|
||||||
|
exact copy. The resulting work is called a "modified version" of the
|
||||||
|
earlier work or a work "based on" the earlier work.
|
||||||
|
|
||||||
|
A "covered work" means either the unmodified Program or a work based
|
||||||
|
on the Program.
|
||||||
|
|
||||||
|
To "propagate" a work means to do anything with it that, without
|
||||||
|
permission, would make you directly or secondarily liable for
|
||||||
|
infringement under applicable copyright law, except executing it on a
|
||||||
|
computer or modifying a private copy. Propagation includes copying,
|
||||||
|
distribution (with or without modification), making available to the
|
||||||
|
public, and in some countries other activities as well.
|
||||||
|
|
||||||
|
To "convey" a work means any kind of propagation that enables other
|
||||||
|
parties to make or receive copies. Mere interaction with a user through
|
||||||
|
a computer network, with no transfer of a copy, is not conveying.
|
||||||
|
|
||||||
|
An interactive user interface displays "Appropriate Legal Notices"
|
||||||
|
to the extent that it includes a convenient and prominently visible
|
||||||
|
feature that (1) displays an appropriate copyright notice, and (2)
|
||||||
|
tells the user that there is no warranty for the work (except to the
|
||||||
|
extent that warranties are provided), that licensees may convey the
|
||||||
|
work under this License, and how to view a copy of this License. If
|
||||||
|
the interface presents a list of user commands or options, such as a
|
||||||
|
menu, a prominent item in the list meets this criterion.
|
||||||
|
|
||||||
|
1. Source Code.
|
||||||
|
|
||||||
|
The "source code" for a work means the preferred form of the work
|
||||||
|
for making modifications to it. "Object code" means any non-source
|
||||||
|
form of a work.
|
||||||
|
|
||||||
|
A "Standard Interface" means an interface that either is an official
|
||||||
|
standard defined by a recognized standards body, or, in the case of
|
||||||
|
interfaces specified for a particular programming language, one that
|
||||||
|
is widely used among developers working in that language.
|
||||||
|
|
||||||
|
The "System Libraries" of an executable work include anything, other
|
||||||
|
than the work as a whole, that (a) is included in the normal form of
|
||||||
|
packaging a Major Component, but which is not part of that Major
|
||||||
|
Component, and (b) serves only to enable use of the work with that
|
||||||
|
Major Component, or to implement a Standard Interface for which an
|
||||||
|
implementation is available to the public in source code form. A
|
||||||
|
"Major Component", in this context, means a major essential component
|
||||||
|
(kernel, window system, and so on) of the specific operating system
|
||||||
|
(if any) on which the executable work runs, or a compiler used to
|
||||||
|
produce the work, or an object code interpreter used to run it.
|
||||||
|
|
||||||
|
The "Corresponding Source" for a work in object code form means all
|
||||||
|
the source code needed to generate, install, and (for an executable
|
||||||
|
work) run the object code and to modify the work, including scripts to
|
||||||
|
control those activities. However, it does not include the work's
|
||||||
|
System Libraries, or general-purpose tools or generally available free
|
||||||
|
programs which are used unmodified in performing those activities but
|
||||||
|
which are not part of the work. For example, Corresponding Source
|
||||||
|
includes interface definition files associated with source files for
|
||||||
|
the work, and the source code for shared libraries and dynamically
|
||||||
|
linked subprograms that the work is specifically designed to require,
|
||||||
|
such as by intimate data communication or control flow between those
|
||||||
|
subprograms and other parts of the work.
|
||||||
|
|
||||||
|
The Corresponding Source need not include anything that users
|
||||||
|
can regenerate automatically from other parts of the Corresponding
|
||||||
|
Source.
|
||||||
|
|
||||||
|
The Corresponding Source for a work in source code form is that
|
||||||
|
same work.
|
||||||
|
|
||||||
|
2. Basic Permissions.
|
||||||
|
|
||||||
|
All rights granted under this License are granted for the term of
|
||||||
|
copyright on the Program, and are irrevocable provided the stated
|
||||||
|
conditions are met. This License explicitly affirms your unlimited
|
||||||
|
permission to run the unmodified Program. The output from running a
|
||||||
|
covered work is covered by this License only if the output, given its
|
||||||
|
content, constitutes a covered work. This License acknowledges your
|
||||||
|
rights of fair use or other equivalent, as provided by copyright law.
|
||||||
|
|
||||||
|
You may make, run and propagate covered works that you do not
|
||||||
|
convey, without conditions so long as your license otherwise remains
|
||||||
|
in force. You may convey covered works to others for the sole purpose
|
||||||
|
of having them make modifications exclusively for you, or provide you
|
||||||
|
with facilities for running those works, provided that you comply with
|
||||||
|
the terms of this License in conveying all material for which you do
|
||||||
|
not control copyright. Those thus making or running the covered works
|
||||||
|
for you must do so exclusively on your behalf, under your direction
|
||||||
|
and control, on terms that prohibit them from making any copies of
|
||||||
|
your copyrighted material outside their relationship with you.
|
||||||
|
|
||||||
|
Conveying under any other circumstances is permitted solely under
|
||||||
|
the conditions stated below. Sublicensing is not allowed; section 10
|
||||||
|
makes it unnecessary.
|
||||||
|
|
||||||
|
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||||
|
|
||||||
|
No covered work shall be deemed part of an effective technological
|
||||||
|
measure under any applicable law fulfilling obligations under article
|
||||||
|
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||||
|
similar laws prohibiting or restricting circumvention of such
|
||||||
|
measures.
|
||||||
|
|
||||||
|
When you convey a covered work, you waive any legal power to forbid
|
||||||
|
circumvention of technological measures to the extent such circumvention
|
||||||
|
is effected by exercising rights under this License with respect to
|
||||||
|
the covered work, and you disclaim any intention to limit operation or
|
||||||
|
modification of the work as a means of enforcing, against the work's
|
||||||
|
users, your or third parties' legal rights to forbid circumvention of
|
||||||
|
technological measures.
|
||||||
|
|
||||||
|
4. Conveying Verbatim Copies.
|
||||||
|
|
||||||
|
You may convey verbatim copies of the Program's source code as you
|
||||||
|
receive it, in any medium, provided that you conspicuously and
|
||||||
|
appropriately publish on each copy an appropriate copyright notice;
|
||||||
|
keep intact all notices stating that this License and any
|
||||||
|
non-permissive terms added in accord with section 7 apply to the code;
|
||||||
|
keep intact all notices of the absence of any warranty; and give all
|
||||||
|
recipients a copy of this License along with the Program.
|
||||||
|
|
||||||
|
You may charge any price or no price for each copy that you convey,
|
||||||
|
and you may offer support or warranty protection for a fee.
|
||||||
|
|
||||||
|
5. Conveying Modified Source Versions.
|
||||||
|
|
||||||
|
You may convey a work based on the Program, or the modifications to
|
||||||
|
produce it from the Program, in the form of source code under the
|
||||||
|
terms of section 4, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) The work must carry prominent notices stating that you modified
|
||||||
|
it, and giving a relevant date.
|
||||||
|
|
||||||
|
b) The work must carry prominent notices stating that it is
|
||||||
|
released under this License and any conditions added under section
|
||||||
|
7. This requirement modifies the requirement in section 4 to
|
||||||
|
"keep intact all notices".
|
||||||
|
|
||||||
|
c) You must license the entire work, as a whole, under this
|
||||||
|
License to anyone who comes into possession of a copy. This
|
||||||
|
License will therefore apply, along with any applicable section 7
|
||||||
|
additional terms, to the whole of the work, and all its parts,
|
||||||
|
regardless of how they are packaged. This License gives no
|
||||||
|
permission to license the work in any other way, but it does not
|
||||||
|
invalidate such permission if you have separately received it.
|
||||||
|
|
||||||
|
d) If the work has interactive user interfaces, each must display
|
||||||
|
Appropriate Legal Notices; however, if the Program has interactive
|
||||||
|
interfaces that do not display Appropriate Legal Notices, your
|
||||||
|
work need not make them do so.
|
||||||
|
|
||||||
|
A compilation of a covered work with other separate and independent
|
||||||
|
works, which are not by their nature extensions of the covered work,
|
||||||
|
and which are not combined with it such as to form a larger program,
|
||||||
|
in or on a volume of a storage or distribution medium, is called an
|
||||||
|
"aggregate" if the compilation and its resulting copyright are not
|
||||||
|
used to limit the access or legal rights of the compilation's users
|
||||||
|
beyond what the individual works permit. Inclusion of a covered work
|
||||||
|
in an aggregate does not cause this License to apply to the other
|
||||||
|
parts of the aggregate.
|
||||||
|
|
||||||
|
6. Conveying Non-Source Forms.
|
||||||
|
|
||||||
|
You may convey a covered work in object code form under the terms
|
||||||
|
of sections 4 and 5, provided that you also convey the
|
||||||
|
machine-readable Corresponding Source under the terms of this License,
|
||||||
|
in one of these ways:
|
||||||
|
|
||||||
|
a) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by the
|
||||||
|
Corresponding Source fixed on a durable physical medium
|
||||||
|
customarily used for software interchange.
|
||||||
|
|
||||||
|
b) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by a
|
||||||
|
written offer, valid for at least three years and valid for as
|
||||||
|
long as you offer spare parts or customer support for that product
|
||||||
|
model, to give anyone who possesses the object code either (1) a
|
||||||
|
copy of the Corresponding Source for all the software in the
|
||||||
|
product that is covered by this License, on a durable physical
|
||||||
|
medium customarily used for software interchange, for a price no
|
||||||
|
more than your reasonable cost of physically performing this
|
||||||
|
conveying of source, or (2) access to copy the
|
||||||
|
Corresponding Source from a network server at no charge.
|
||||||
|
|
||||||
|
c) Convey individual copies of the object code with a copy of the
|
||||||
|
written offer to provide the Corresponding Source. This
|
||||||
|
alternative is allowed only occasionally and noncommercially, and
|
||||||
|
only if you received the object code with such an offer, in accord
|
||||||
|
with subsection 6b.
|
||||||
|
|
||||||
|
d) Convey the object code by offering access from a designated
|
||||||
|
place (gratis or for a charge), and offer equivalent access to the
|
||||||
|
Corresponding Source in the same way through the same place at no
|
||||||
|
further charge. You need not require recipients to copy the
|
||||||
|
Corresponding Source along with the object code. If the place to
|
||||||
|
copy the object code is a network server, the Corresponding Source
|
||||||
|
may be on a different server (operated by you or a third party)
|
||||||
|
that supports equivalent copying facilities, provided you maintain
|
||||||
|
clear directions next to the object code saying where to find the
|
||||||
|
Corresponding Source. Regardless of what server hosts the
|
||||||
|
Corresponding Source, you remain obligated to ensure that it is
|
||||||
|
available for as long as needed to satisfy these requirements.
|
||||||
|
|
||||||
|
e) Convey the object code using peer-to-peer transmission, provided
|
||||||
|
you inform other peers where the object code and Corresponding
|
||||||
|
Source of the work are being offered to the general public at no
|
||||||
|
charge under subsection 6d.
|
||||||
|
|
||||||
|
A separable portion of the object code, whose source code is excluded
|
||||||
|
from the Corresponding Source as a System Library, need not be
|
||||||
|
included in conveying the object code work.
|
||||||
|
|
||||||
|
A "User Product" is either (1) a "consumer product", which means any
|
||||||
|
tangible personal property which is normally used for personal, family,
|
||||||
|
or household purposes, or (2) anything designed or sold for incorporation
|
||||||
|
into a dwelling. In determining whether a product is a consumer product,
|
||||||
|
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||||
|
product received by a particular user, "normally used" refers to a
|
||||||
|
typical or common use of that class of product, regardless of the status
|
||||||
|
of the particular user or of the way in which the particular user
|
||||||
|
actually uses, or expects or is expected to use, the product. A product
|
||||||
|
is a consumer product regardless of whether the product has substantial
|
||||||
|
commercial, industrial or non-consumer uses, unless such uses represent
|
||||||
|
the only significant mode of use of the product.
|
||||||
|
|
||||||
|
"Installation Information" for a User Product means any methods,
|
||||||
|
procedures, authorization keys, or other information required to install
|
||||||
|
and execute modified versions of a covered work in that User Product from
|
||||||
|
a modified version of its Corresponding Source. The information must
|
||||||
|
suffice to ensure that the continued functioning of the modified object
|
||||||
|
code is in no case prevented or interfered with solely because
|
||||||
|
modification has been made.
|
||||||
|
|
||||||
|
If you convey an object code work under this section in, or with, or
|
||||||
|
specifically for use in, a User Product, and the conveying occurs as
|
||||||
|
part of a transaction in which the right of possession and use of the
|
||||||
|
User Product is transferred to the recipient in perpetuity or for a
|
||||||
|
fixed term (regardless of how the transaction is characterized), the
|
||||||
|
Corresponding Source conveyed under this section must be accompanied
|
||||||
|
by the Installation Information. But this requirement does not apply
|
||||||
|
if neither you nor any third party retains the ability to install
|
||||||
|
modified object code on the User Product (for example, the work has
|
||||||
|
been installed in ROM).
|
||||||
|
|
||||||
|
The requirement to provide Installation Information does not include a
|
||||||
|
requirement to continue to provide support service, warranty, or updates
|
||||||
|
for a work that has been modified or installed by the recipient, or for
|
||||||
|
the User Product in which it has been modified or installed. Access to a
|
||||||
|
network may be denied when the modification itself materially and
|
||||||
|
adversely affects the operation of the network or violates the rules and
|
||||||
|
protocols for communication across the network.
|
||||||
|
|
||||||
|
Corresponding Source conveyed, and Installation Information provided,
|
||||||
|
in accord with this section must be in a format that is publicly
|
||||||
|
documented (and with an implementation available to the public in
|
||||||
|
source code form), and must require no special password or key for
|
||||||
|
unpacking, reading or copying.
|
||||||
|
|
||||||
|
7. Additional Terms.
|
||||||
|
|
||||||
|
"Additional permissions" are terms that supplement the terms of this
|
||||||
|
License by making exceptions from one or more of its conditions.
|
||||||
|
Additional permissions that are applicable to the entire Program shall
|
||||||
|
be treated as though they were included in this License, to the extent
|
||||||
|
that they are valid under applicable law. If additional permissions
|
||||||
|
apply only to part of the Program, that part may be used separately
|
||||||
|
under those permissions, but the entire Program remains governed by
|
||||||
|
this License without regard to the additional permissions.
|
||||||
|
|
||||||
|
When you convey a copy of a covered work, you may at your option
|
||||||
|
remove any additional permissions from that copy, or from any part of
|
||||||
|
it. (Additional permissions may be written to require their own
|
||||||
|
removal in certain cases when you modify the work.) You may place
|
||||||
|
additional permissions on material, added by you to a covered work,
|
||||||
|
for which you have or can give appropriate copyright permission.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, for material you
|
||||||
|
add to a covered work, you may (if authorized by the copyright holders of
|
||||||
|
that material) supplement the terms of this License with terms:
|
||||||
|
|
||||||
|
a) Disclaiming warranty or limiting liability differently from the
|
||||||
|
terms of sections 15 and 16 of this License; or
|
||||||
|
|
||||||
|
b) Requiring preservation of specified reasonable legal notices or
|
||||||
|
author attributions in that material or in the Appropriate Legal
|
||||||
|
Notices displayed by works containing it; or
|
||||||
|
|
||||||
|
c) Prohibiting misrepresentation of the origin of that material, or
|
||||||
|
requiring that modified versions of such material be marked in
|
||||||
|
reasonable ways as different from the original version; or
|
||||||
|
|
||||||
|
d) Limiting the use for publicity purposes of names of licensors or
|
||||||
|
authors of the material; or
|
||||||
|
|
||||||
|
e) Declining to grant rights under trademark law for use of some
|
||||||
|
trade names, trademarks, or service marks; or
|
||||||
|
|
||||||
|
f) Requiring indemnification of licensors and authors of that
|
||||||
|
material by anyone who conveys the material (or modified versions of
|
||||||
|
it) with contractual assumptions of liability to the recipient, for
|
||||||
|
any liability that these contractual assumptions directly impose on
|
||||||
|
those licensors and authors.
|
||||||
|
|
||||||
|
All other non-permissive additional terms are considered "further
|
||||||
|
restrictions" within the meaning of section 10. If the Program as you
|
||||||
|
received it, or any part of it, contains a notice stating that it is
|
||||||
|
governed by this License along with a term that is a further
|
||||||
|
restriction, you may remove that term. If a license document contains
|
||||||
|
a further restriction but permits relicensing or conveying under this
|
||||||
|
License, you may add to a covered work material governed by the terms
|
||||||
|
of that license document, provided that the further restriction does
|
||||||
|
not survive such relicensing or conveying.
|
||||||
|
|
||||||
|
If you add terms to a covered work in accord with this section, you
|
||||||
|
must place, in the relevant source files, a statement of the
|
||||||
|
additional terms that apply to those files, or a notice indicating
|
||||||
|
where to find the applicable terms.
|
||||||
|
|
||||||
|
Additional terms, permissive or non-permissive, may be stated in the
|
||||||
|
form of a separately written license, or stated as exceptions;
|
||||||
|
the above requirements apply either way.
|
||||||
|
|
||||||
|
8. Termination.
|
||||||
|
|
||||||
|
You may not propagate or modify a covered work except as expressly
|
||||||
|
provided under this License. Any attempt otherwise to propagate or
|
||||||
|
modify it is void, and will automatically terminate your rights under
|
||||||
|
this License (including any patent licenses granted under the third
|
||||||
|
paragraph of section 11).
|
||||||
|
|
||||||
|
However, if you cease all violation of this License, then your
|
||||||
|
license from a particular copyright holder is reinstated (a)
|
||||||
|
provisionally, unless and until the copyright holder explicitly and
|
||||||
|
finally terminates your license, and (b) permanently, if the copyright
|
||||||
|
holder fails to notify you of the violation by some reasonable means
|
||||||
|
prior to 60 days after the cessation.
|
||||||
|
|
||||||
|
Moreover, your license from a particular copyright holder is
|
||||||
|
reinstated permanently if the copyright holder notifies you of the
|
||||||
|
violation by some reasonable means, this is the first time you have
|
||||||
|
received notice of violation of this License (for any work) from that
|
||||||
|
copyright holder, and you cure the violation prior to 30 days after
|
||||||
|
your receipt of the notice.
|
||||||
|
|
||||||
|
Termination of your rights under this section does not terminate the
|
||||||
|
licenses of parties who have received copies or rights from you under
|
||||||
|
this License. If your rights have been terminated and not permanently
|
||||||
|
reinstated, you do not qualify to receive new licenses for the same
|
||||||
|
material under section 10.
|
||||||
|
|
||||||
|
9. Acceptance Not Required for Having Copies.
|
||||||
|
|
||||||
|
You are not required to accept this License in order to receive or
|
||||||
|
run a copy of the Program. Ancillary propagation of a covered work
|
||||||
|
occurring solely as a consequence of using peer-to-peer transmission
|
||||||
|
to receive a copy likewise does not require acceptance. However,
|
||||||
|
nothing other than this License grants you permission to propagate or
|
||||||
|
modify any covered work. These actions infringe copyright if you do
|
||||||
|
not accept this License. Therefore, by modifying or propagating a
|
||||||
|
covered work, you indicate your acceptance of this License to do so.
|
||||||
|
|
||||||
|
10. Automatic Licensing of Downstream Recipients.
|
||||||
|
|
||||||
|
Each time you convey a covered work, the recipient automatically
|
||||||
|
receives a license from the original licensors, to run, modify and
|
||||||
|
propagate that work, subject to this License. You are not responsible
|
||||||
|
for enforcing compliance by third parties with this License.
|
||||||
|
|
||||||
|
An "entity transaction" is a transaction transferring control of an
|
||||||
|
organization, or substantially all assets of one, or subdividing an
|
||||||
|
organization, or merging organizations. If propagation of a covered
|
||||||
|
work results from an entity transaction, each party to that
|
||||||
|
transaction who receives a copy of the work also receives whatever
|
||||||
|
licenses to the work the party's predecessor in interest had or could
|
||||||
|
give under the previous paragraph, plus a right to possession of the
|
||||||
|
Corresponding Source of the work from the predecessor in interest, if
|
||||||
|
the predecessor has it or can get it with reasonable efforts.
|
||||||
|
|
||||||
|
You may not impose any further restrictions on the exercise of the
|
||||||
|
rights granted or affirmed under this License. For example, you may
|
||||||
|
not impose a license fee, royalty, or other charge for exercise of
|
||||||
|
rights granted under this License, and you may not initiate litigation
|
||||||
|
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||||
|
any patent claim is infringed by making, using, selling, offering for
|
||||||
|
sale, or importing the Program or any portion of it.
|
||||||
|
|
||||||
|
11. Patents.
|
||||||
|
|
||||||
|
A "contributor" is a copyright holder who authorizes use under this
|
||||||
|
License of the Program or a work on which the Program is based. The
|
||||||
|
work thus licensed is called the contributor's "contributor version".
|
||||||
|
|
||||||
|
A contributor's "essential patent claims" are all patent claims
|
||||||
|
owned or controlled by the contributor, whether already acquired or
|
||||||
|
hereafter acquired, that would be infringed by some manner, permitted
|
||||||
|
by this License, of making, using, or selling its contributor version,
|
||||||
|
but do not include claims that would be infringed only as a
|
||||||
|
consequence of further modification of the contributor version. For
|
||||||
|
purposes of this definition, "control" includes the right to grant
|
||||||
|
patent sublicenses in a manner consistent with the requirements of
|
||||||
|
this License.
|
||||||
|
|
||||||
|
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||||
|
patent license under the contributor's essential patent claims, to
|
||||||
|
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||||
|
propagate the contents of its contributor version.
|
||||||
|
|
||||||
|
In the following three paragraphs, a "patent license" is any express
|
||||||
|
agreement or commitment, however denominated, not to enforce a patent
|
||||||
|
(such as an express permission to practice a patent or covenant not to
|
||||||
|
sue for patent infringement). To "grant" such a patent license to a
|
||||||
|
party means to make such an agreement or commitment not to enforce a
|
||||||
|
patent against the party.
|
||||||
|
|
||||||
|
If you convey a covered work, knowingly relying on a patent license,
|
||||||
|
and the Corresponding Source of the work is not available for anyone
|
||||||
|
to copy, free of charge and under the terms of this License, through a
|
||||||
|
publicly available network server or other readily accessible means,
|
||||||
|
then you must either (1) cause the Corresponding Source to be so
|
||||||
|
available, or (2) arrange to deprive yourself of the benefit of the
|
||||||
|
patent license for this particular work, or (3) arrange, in a manner
|
||||||
|
consistent with the requirements of this License, to extend the patent
|
||||||
|
license to downstream recipients. "Knowingly relying" means you have
|
||||||
|
actual knowledge that, but for the patent license, your conveying the
|
||||||
|
covered work in a country, or your recipient's use of the covered work
|
||||||
|
in a country, would infringe one or more identifiable patents in that
|
||||||
|
country that you have reason to believe are valid.
|
||||||
|
|
||||||
|
If, pursuant to or in connection with a single transaction or
|
||||||
|
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||||
|
covered work, and grant a patent license to some of the parties
|
||||||
|
receiving the covered work authorizing them to use, propagate, modify
|
||||||
|
or convey a specific copy of the covered work, then the patent license
|
||||||
|
you grant is automatically extended to all recipients of the covered
|
||||||
|
work and works based on it.
|
||||||
|
|
||||||
|
A patent license is "discriminatory" if it does not include within
|
||||||
|
the scope of its coverage, prohibits the exercise of, or is
|
||||||
|
conditioned on the non-exercise of one or more of the rights that are
|
||||||
|
specifically granted under this License. You may not convey a covered
|
||||||
|
work if you are a party to an arrangement with a third party that is
|
||||||
|
in the business of distributing software, under which you make payment
|
||||||
|
to the third party based on the extent of your activity of conveying
|
||||||
|
the work, and under which the third party grants, to any of the
|
||||||
|
parties who would receive the covered work from you, a discriminatory
|
||||||
|
patent license (a) in connection with copies of the covered work
|
||||||
|
conveyed by you (or copies made from those copies), or (b) primarily
|
||||||
|
for and in connection with specific products or compilations that
|
||||||
|
contain the covered work, unless you entered into that arrangement,
|
||||||
|
or that patent license was granted, prior to 28 March 2007.
|
||||||
|
|
||||||
|
Nothing in this License shall be construed as excluding or limiting
|
||||||
|
any implied license or other defenses to infringement that may
|
||||||
|
otherwise be available to you under applicable patent law.
|
||||||
|
|
||||||
|
12. No Surrender of Others' Freedom.
|
||||||
|
|
||||||
|
If conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot convey a
|
||||||
|
covered work so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you may
|
||||||
|
not convey it at all. For example, if you agree to terms that obligate you
|
||||||
|
to collect a royalty for further conveying from those to whom you convey
|
||||||
|
the Program, the only way you could satisfy both those terms and this
|
||||||
|
License would be to refrain entirely from conveying the Program.
|
||||||
|
|
||||||
|
13. Use with the GNU Affero General Public License.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, you have
|
||||||
|
permission to link or combine any covered work with a work licensed
|
||||||
|
under version 3 of the GNU Affero General Public License into a single
|
||||||
|
combined work, and to convey the resulting work. The terms of this
|
||||||
|
License will continue to apply to the part which is the covered work,
|
||||||
|
but the special requirements of the GNU Affero General Public License,
|
||||||
|
section 13, concerning interaction through a network will apply to the
|
||||||
|
combination as such.
|
||||||
|
|
||||||
|
14. Revised Versions of this License.
|
||||||
|
|
||||||
|
The Free Software Foundation may publish revised and/or new versions of
|
||||||
|
the GNU General Public License from time to time. Such new versions will
|
||||||
|
be similar in spirit to the present version, but may differ in detail to
|
||||||
|
address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the
|
||||||
|
Program specifies that a certain numbered version of the GNU General
|
||||||
|
Public License "or any later version" applies to it, you have the
|
||||||
|
option of following the terms and conditions either of that numbered
|
||||||
|
version or of any later version published by the Free Software
|
||||||
|
Foundation. If the Program does not specify a version number of the
|
||||||
|
GNU General Public License, you may choose any version ever published
|
||||||
|
by the Free Software Foundation.
|
||||||
|
|
||||||
|
If the Program specifies that a proxy can decide which future
|
||||||
|
versions of the GNU General Public License can be used, that proxy's
|
||||||
|
public statement of acceptance of a version permanently authorizes you
|
||||||
|
to choose that version for the Program.
|
||||||
|
|
||||||
|
Later license versions may give you additional or different
|
||||||
|
permissions. However, no additional obligations are imposed on any
|
||||||
|
author or copyright holder as a result of your choosing to follow a
|
||||||
|
later version.
|
||||||
|
|
||||||
|
15. Disclaimer of Warranty.
|
||||||
|
|
||||||
|
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||||
|
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||||
|
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||||
|
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||||
|
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||||
|
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
16. Limitation of Liability.
|
||||||
|
|
||||||
|
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||||
|
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||||
|
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||||
|
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||||
|
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||||
|
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||||
|
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||||
|
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||||
|
SUCH DAMAGES.
|
||||||
|
|
||||||
|
17. Interpretation of Sections 15 and 16.
|
||||||
|
|
||||||
|
If the disclaimer of warranty and limitation of liability provided
|
||||||
|
above cannot be given local legal effect according to their terms,
|
||||||
|
reviewing courts shall apply local law that most closely approximates
|
||||||
|
an absolute waiver of all civil liability in connection with the
|
||||||
|
Program, unless a warranty or assumption of liability accompanies a
|
||||||
|
copy of the Program in return for a fee.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Programs
|
||||||
|
|
||||||
|
If you develop a new program, and you want it to be of the greatest
|
||||||
|
possible use to the public, the best way to achieve this is to make it
|
||||||
|
free software which everyone can redistribute and change under these terms.
|
||||||
|
|
||||||
|
To do so, attach the following notices to the program. It is safest
|
||||||
|
to attach them to the start of each source file to most effectively
|
||||||
|
state the exclusion of warranty; and each file should have at least
|
||||||
|
the "copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
|
<one line to give the program's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
If the program does terminal interaction, make it output a short
|
||||||
|
notice like this when it starts in an interactive mode:
|
||||||
|
|
||||||
|
<program> Copyright (C) <year> <name of author>
|
||||||
|
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||||
|
This is free software, and you are welcome to redistribute it
|
||||||
|
under certain conditions; type `show c' for details.
|
||||||
|
|
||||||
|
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||||
|
parts of the General Public License. Of course, your program's commands
|
||||||
|
might be different; for a GUI interface, you would use an "about box".
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or school,
|
||||||
|
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||||
|
For more information on this, and how to apply and follow the GNU GPL, see
|
||||||
|
<https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
The GNU General Public License does not permit incorporating your program
|
||||||
|
into proprietary programs. If your program is a subroutine library, you
|
||||||
|
may consider it more useful to permit linking proprietary applications with
|
||||||
|
the library. If this is what you want to do, use the GNU Lesser General
|
||||||
|
Public License instead of this License. But first, please read
|
||||||
|
<https://www.gnu.org/licenses/why-not-lgpl.html>.
|
||||||
32
Armory/Armory/Makefile
Normal file
32
Armory/Armory/Makefile
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
########################################################################
|
||||||
|
#
|
||||||
|
#
|
||||||
|
#########################################################################
|
||||||
|
|
||||||
|
CC = g++
|
||||||
|
|
||||||
|
#COPTS = -fPIC -DLINUX -O2 -std=c++17 -lpthread
|
||||||
|
COPTS = -fPIC -DLINUX -g -O0 -Wall -std=c++17 -lpthread
|
||||||
|
|
||||||
|
ROOTLIBS = `root-config --cflags --glibs`
|
||||||
|
|
||||||
|
ALL = Mapper EventBuilder#AnasenMS
|
||||||
|
|
||||||
|
#########################################################################
|
||||||
|
|
||||||
|
all : $(ALL)
|
||||||
|
|
||||||
|
clean :
|
||||||
|
/bin/rm -f $(OBJS) $(ALL)
|
||||||
|
|
||||||
|
Mapper : Mapper.cpp ../mapping.h ClassDet.h
|
||||||
|
@echo "--------- making Mapper"
|
||||||
|
$(CC) $(COPTS) -o Mapper Mapper.cpp $(ROOTLIBS)
|
||||||
|
|
||||||
|
# AnasenMS : constant.h Isotope.h ClassTransfer.h ClassSX3.h ClassPW.h ClassAnasen.h anasenMS.cpp
|
||||||
|
# @echo "--------- making ANASEN Monte Carlo"
|
||||||
|
# $(CC) $(COPTS) -o AnasenMS anasenMS.cpp $(ROOTLIBS)
|
||||||
|
|
||||||
|
EventBuilder : EventBuilder.cpp ../ClassData.h fsuReader.h ../Hit.h
|
||||||
|
@echo "--------- making EventBuilder"
|
||||||
|
$(CC) $(COPTS) -o EventBuilder EventBuilder.cpp $(ROOTLIBS)
|
||||||
182
Armory/Armory/Mapper.cpp
Normal file
182
Armory/Armory/Mapper.cpp
Normal file
|
|
@ -0,0 +1,182 @@
|
||||||
|
#include <string>
|
||||||
|
#include <cstdio>
|
||||||
|
|
||||||
|
#include <TROOT.h>
|
||||||
|
#include <TTree.h>
|
||||||
|
#include <TFile.h>
|
||||||
|
#include <TMath.h>
|
||||||
|
#include <TBenchmark.h>
|
||||||
|
|
||||||
|
#include "../mapping.h"
|
||||||
|
#include "ClassDet.h"
|
||||||
|
|
||||||
|
//===============================
|
||||||
|
int main(int argc, char **argv){
|
||||||
|
|
||||||
|
printf("=========================================\n");
|
||||||
|
printf("=== Mapper ===\n");
|
||||||
|
printf("=========================================\n");
|
||||||
|
if (argc != 2) {
|
||||||
|
printf("Incorrect number of arguments:\n");
|
||||||
|
printf("%s [inFile]\n", argv[0]);
|
||||||
|
printf("\n\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
///============= read input
|
||||||
|
std::string inFileName = argv[1];
|
||||||
|
|
||||||
|
PrintMapping();
|
||||||
|
|
||||||
|
TFile * inFile = new TFile(inFileName.c_str(), "READ");
|
||||||
|
TTree * tree = (TTree*) inFile->Get("tree");
|
||||||
|
unsigned long long totnumEntry = tree->GetEntries();
|
||||||
|
|
||||||
|
ULong64_t evID;
|
||||||
|
UInt_t multi;
|
||||||
|
UShort_t sn[MAXMULTI];
|
||||||
|
UShort_t ch[MAXMULTI];
|
||||||
|
UShort_t e[MAXMULTI];
|
||||||
|
UShort_t e2[MAXMULTI];
|
||||||
|
ULong64_t e_t[MAXMULTI];
|
||||||
|
UShort_t e_f[MAXMULTI];
|
||||||
|
|
||||||
|
tree->SetBranchAddress("evID", &evID);
|
||||||
|
tree->SetBranchAddress("multi", &multi);
|
||||||
|
tree->SetBranchAddress("sn", sn);
|
||||||
|
tree->SetBranchAddress("ch", ch);
|
||||||
|
tree->SetBranchAddress("e", e);
|
||||||
|
tree->SetBranchAddress("e2", e2);
|
||||||
|
tree->SetBranchAddress("e_t", e_t);
|
||||||
|
tree->SetBranchAddress("e_f", e_f);
|
||||||
|
|
||||||
|
///================== new tree
|
||||||
|
TString outFileName = inFileName;
|
||||||
|
TString runStr = outFileName;
|
||||||
|
int pos = outFileName.Last('/');
|
||||||
|
pos = outFileName.Index("_", pos+1); // find next "_"
|
||||||
|
runStr.Remove(0, pos+1);
|
||||||
|
runStr.Remove(3);
|
||||||
|
pos = outFileName.Index("_", pos+1); // find next "_"
|
||||||
|
outFileName.Remove(pos); // remove the rest
|
||||||
|
outFileName += "_mapped.root";
|
||||||
|
|
||||||
|
ULong_t eventID;
|
||||||
|
UInt_t run = runStr.Atoi();
|
||||||
|
|
||||||
|
Det sx3;
|
||||||
|
Det qqq;
|
||||||
|
Det pc ;
|
||||||
|
|
||||||
|
printf(" Raw root file : %s\n", inFileName.c_str());
|
||||||
|
printf(" Run : %03d\n", run);
|
||||||
|
printf(" total Entry : %lld \n", totnumEntry);
|
||||||
|
printf(" Out file name : %s \n", outFileName.Data());
|
||||||
|
|
||||||
|
TFile * saveFile = new TFile( outFileName,"RECREATE");
|
||||||
|
TTree * newTree = new TTree("tree","tree");
|
||||||
|
|
||||||
|
|
||||||
|
newTree->Branch("evID", &eventID,"eventID/l");
|
||||||
|
newTree->Branch("run", &run,"run/i");
|
||||||
|
|
||||||
|
newTree->Branch("sx3Multi", &sx3.multi, "sx3Multi/s");
|
||||||
|
newTree->Branch("sx3ID", &sx3.id, "sx3ID[sx3Multi]/s");
|
||||||
|
newTree->Branch("sx3Ch", &sx3.ch, "sx3Ch[sx3Multi]/s");
|
||||||
|
newTree->Branch("sx3E", &sx3.e, "sx3Energy[sx3Multi]/s");
|
||||||
|
newTree->Branch("sx3T", &sx3.t, "sx3Time[sx3Multi]/l");
|
||||||
|
|
||||||
|
newTree->Branch("qqqMulti", &qqq.multi, "qqqMulti/s");
|
||||||
|
newTree->Branch("qqqID", &qqq.id, "qqqID[qqqMulti]/s");
|
||||||
|
newTree->Branch("qqqCh", &qqq.ch, "qqqCh[qqqMulti]/s");
|
||||||
|
newTree->Branch("qqqE", &qqq.e, "qqqEnergy[qqqMulti]/s");
|
||||||
|
newTree->Branch("qqqT", &qqq.t, "qqqTime[qqqMulti]/l");
|
||||||
|
newTree->Branch("qqqSN", &qqq.sn, "qqqSN[qqqMulti]/s");
|
||||||
|
|
||||||
|
newTree->Branch("pcMulti", &pc.multi, "pcMulti/s");
|
||||||
|
newTree->Branch("pcID", &pc.id, "pcID[pcMulti]/s");
|
||||||
|
newTree->Branch("pcCh", &pc.ch, "pcCh[pcMulti]/s");
|
||||||
|
newTree->Branch("pcE", &pc.e, "pcEnergy[pcMulti]/s");
|
||||||
|
newTree->Branch("pcT", &pc.t, "pcTime[pcMulti]/l");
|
||||||
|
|
||||||
|
///================== looping old tree and apply mapping
|
||||||
|
|
||||||
|
//clock
|
||||||
|
// TBenchmark clock;
|
||||||
|
// Bool_t shown;
|
||||||
|
|
||||||
|
for( unsigned long long ev = 0; ev < totnumEntry; ev++){
|
||||||
|
tree->GetEntry(ev);
|
||||||
|
|
||||||
|
eventID = evID;
|
||||||
|
sx3.multi = 0;
|
||||||
|
qqq.multi = 0;
|
||||||
|
pc.multi = 0;
|
||||||
|
|
||||||
|
qqq.Clear();
|
||||||
|
|
||||||
|
for( unsigned int i = 0; i < multi; i++){
|
||||||
|
|
||||||
|
// printf("%10u/%10u| %5d, %2u, %6u, %14llu\n", i, multi, sn[i], ch[i], e[i], e_t[i] );
|
||||||
|
|
||||||
|
//globalCh = digi-ID * nCh(digi-iD) + ch
|
||||||
|
int globalCh = -1;
|
||||||
|
|
||||||
|
for( int j = 0; j < nBd; j++){
|
||||||
|
if( board.at(j) == sn[i]){
|
||||||
|
globalCh = (sn[i] > 1000 ? j * 64 : 7*64 + (j-7) * 16) + ch[i]; //& = number V1740
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( globalCh == -1) printf("ev %llu\n", ev);
|
||||||
|
|
||||||
|
unsigned short ID = mapping[globalCh];
|
||||||
|
|
||||||
|
//=================================== sx3
|
||||||
|
if( ID < 10000 ) {
|
||||||
|
sx3.id[sx3.multi] = ID / 100;
|
||||||
|
sx3.ch[sx3.multi] = ID % 100;
|
||||||
|
sx3.e[sx3.multi] = e[i];
|
||||||
|
sx3.t[sx3.multi] = e_t[i];
|
||||||
|
sx3.multi ++;
|
||||||
|
}
|
||||||
|
|
||||||
|
//=================================== qqq
|
||||||
|
if( 10000 <= ID && ID < 20000 ) {
|
||||||
|
qqq.id[qqq.multi] = (ID - 10000) / 100;
|
||||||
|
qqq.ch[qqq.multi] = (ID - 10000) % 100;
|
||||||
|
qqq.e[qqq.multi] = e[i];
|
||||||
|
qqq.t[qqq.multi] = e_t[i];
|
||||||
|
qqq.sn[qqq.multi] = sn[i];
|
||||||
|
qqq.multi ++;
|
||||||
|
}
|
||||||
|
|
||||||
|
//=================================== pc
|
||||||
|
if( 20000 <= ID && ID < 30000 ) {
|
||||||
|
pc.id[pc.multi] = (ID - 20000) / 100;
|
||||||
|
pc.ch[pc.multi] = (ID - 20000) % 100;
|
||||||
|
pc.e[pc.multi] = e[i];
|
||||||
|
pc.t[pc.multi] = e_t[i];
|
||||||
|
pc.multi ++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
saveFile->cd(); //set focus on this file
|
||||||
|
newTree->Fill();
|
||||||
|
|
||||||
|
if( eventID % 100 == 0 ) printf("%6lu/%6llu [%2d%%]\n\033[A\r", eventID, totnumEntry, TMath::Nint((eventID+1)*100./totnumEntry));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
inFile->Close();
|
||||||
|
|
||||||
|
saveFile->cd(); //set focus on this file
|
||||||
|
newTree->Write();
|
||||||
|
UInt_t eventNumber = newTree->GetEntries();
|
||||||
|
saveFile->Close();
|
||||||
|
printf("-------------- done, %u\n", eventNumber);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
280
Armory/Armory/anasenMS.cpp
Normal file
280
Armory/Armory/anasenMS.cpp
Normal file
|
|
@ -0,0 +1,280 @@
|
||||||
|
#include "TRandom.h"
|
||||||
|
#include "TFile.h"
|
||||||
|
#include "TTree.h"
|
||||||
|
#include "TH1.h"
|
||||||
|
#include "TH2.h"
|
||||||
|
#include "TStyle.h"
|
||||||
|
#include "TCanvas.h"
|
||||||
|
#include "TBenchmark.h"
|
||||||
|
|
||||||
|
#include "ClassTransfer.h"
|
||||||
|
#include "ClassAnasen.h"
|
||||||
|
|
||||||
|
//======== Gerneate light particle based on reaction
|
||||||
|
// find out the CalTrack and the real track
|
||||||
|
// find out the Q-value uncertaintly
|
||||||
|
|
||||||
|
int main(int argc, char **argv){
|
||||||
|
|
||||||
|
printf("=========================================\n");
|
||||||
|
printf("=== ANASEN Monte Carlo ===\n");
|
||||||
|
printf("=========================================\n");
|
||||||
|
|
||||||
|
int numEvent = 1000000;
|
||||||
|
if( argc >= 2 ) numEvent = atoi(argv[1]);
|
||||||
|
|
||||||
|
//Reaction
|
||||||
|
TransferReaction transfer;
|
||||||
|
|
||||||
|
transfer.SetA(24,12, 0);
|
||||||
|
transfer.SetIncidentEnergyAngle(10, 0, 0);
|
||||||
|
transfer.Seta( 4, 2);
|
||||||
|
transfer.Setb( 1, 1);
|
||||||
|
|
||||||
|
//TODO add alpha source
|
||||||
|
|
||||||
|
std::vector<float> ExAList = {0};
|
||||||
|
std::vector<float> ExList = {0, 1, 2};
|
||||||
|
|
||||||
|
double vertexXRange[2] = { -5, 5}; // mm
|
||||||
|
double vertexYRange[2] = { -5, 5};
|
||||||
|
double vertexZRange[2] = { -100, 100};
|
||||||
|
|
||||||
|
double sigmaSX3_W = -1; // mm, < 0 use mid-point
|
||||||
|
double sigmaSX3_L = 3; // mm, < 0 use mid-point
|
||||||
|
double sigmaPW_A = 0; // from 0 to 1.
|
||||||
|
double sigmaPW_C = 0; // from 0 to 1.
|
||||||
|
|
||||||
|
//###################################################
|
||||||
|
|
||||||
|
printf("------------ Vertex :\n");
|
||||||
|
printf("X : %7.2f - %7.2f mm\n", vertexXRange[0], vertexXRange[1]);
|
||||||
|
printf("Y : %7.2f - %7.2f mm\n", vertexYRange[0], vertexYRange[1]);
|
||||||
|
printf("Z : %7.2f - %7.2f mm\n", vertexZRange[0], vertexZRange[1]);
|
||||||
|
printf("------------ Uncertainty :\n");
|
||||||
|
printf(" SX3 horizontal : %.1f\n", sigmaSX3_W);
|
||||||
|
printf(" SX3 vertical : %.1f\n", sigmaSX3_L);
|
||||||
|
printf(" Anode : %.1f mm\n", sigmaPW_A);
|
||||||
|
printf(" Cathode : %.1f mm\n", sigmaPW_C);
|
||||||
|
printf(" num_eve : %d \n",numEvent);
|
||||||
|
transfer.CalReactionConstant();
|
||||||
|
|
||||||
|
int nExA = ExAList.size();
|
||||||
|
int nEx = ExList.size();
|
||||||
|
|
||||||
|
ANASEN * anasen = new ANASEN();
|
||||||
|
SX3 * sx3 = anasen->GetSX3();
|
||||||
|
PW * pw = anasen->GetPW();
|
||||||
|
|
||||||
|
TString saveFileName = "SimAnasen1.root";
|
||||||
|
printf("\e[32m#################################### building Tree in %s\e[0m\n", saveFileName.Data());
|
||||||
|
TFile * saveFile = new TFile(saveFileName, "recreate");
|
||||||
|
TTree * tree = new TTree("tree", "tree");
|
||||||
|
|
||||||
|
double KEA;
|
||||||
|
tree->Branch("beamKEA", &KEA, "beamKEA/D");
|
||||||
|
|
||||||
|
double thetaCM, phiCM;
|
||||||
|
tree->Branch("thetaCM", &thetaCM, "thetaCM/D");
|
||||||
|
tree->Branch("phiCM", &phiCM, "phiCM/D");
|
||||||
|
|
||||||
|
double thetab, phib, Tb;
|
||||||
|
double thetaB, phiB, TB;
|
||||||
|
tree->Branch("thetab", &thetab, "thetab/D");
|
||||||
|
tree->Branch("phib", &phib, "phib/D");
|
||||||
|
tree->Branch("Tb", &Tb, "Tb/D");
|
||||||
|
tree->Branch("thetaB", &thetaB, "thetaB/D");
|
||||||
|
tree->Branch("phiB", &phiB, "phiB/D");
|
||||||
|
tree->Branch("TB", &TB, "TB/D");
|
||||||
|
|
||||||
|
int ExAID;
|
||||||
|
double ExA;
|
||||||
|
tree->Branch("ExAID", &ExAID, "ExAID/I");
|
||||||
|
tree->Branch("ExA", &ExA, "ExA/D");
|
||||||
|
|
||||||
|
int ExID;
|
||||||
|
double Ex;
|
||||||
|
tree->Branch("ExID", &ExID, "ExID/I");
|
||||||
|
tree->Branch("Ex", &Ex, "Ex/D");
|
||||||
|
|
||||||
|
double vertexX, vertexY, vertexZ;
|
||||||
|
tree->Branch("vX", &vertexX, "VertexX/D");
|
||||||
|
tree->Branch("vY", &vertexY, "VertexY/D");
|
||||||
|
tree->Branch("vZ", &vertexZ, "VertexZ/D");
|
||||||
|
|
||||||
|
double sx3X, sx3Y, sx3Z;
|
||||||
|
tree->Branch("sx3X", &sx3X, "sx3X/D");
|
||||||
|
tree->Branch("sx3Y", &sx3Y, "sx3Y/D");
|
||||||
|
tree->Branch("sx3Z", &sx3Z, "sx3Z/D");
|
||||||
|
|
||||||
|
int anodeID[2], cathodeID[2];
|
||||||
|
tree->Branch("aID", anodeID, "anodeID/I");
|
||||||
|
tree->Branch("cID", cathodeID, "cathodeID/I");
|
||||||
|
|
||||||
|
double anodeDist[2], cathodeDist[2];
|
||||||
|
tree->Branch("aDist", anodeDist, "anodeDist/D");
|
||||||
|
tree->Branch("cDist", cathodeDist, "cathodeDist/D");
|
||||||
|
|
||||||
|
int sx3ID, sx3Up, sx3Dn, sx3Bk;
|
||||||
|
double sx3ZFrac;
|
||||||
|
tree->Branch("sx3ID", &sx3ID, "sx3ID/I");
|
||||||
|
tree->Branch("sx3Up", &sx3Up, "sx3Up/I");
|
||||||
|
tree->Branch("sx3Dn", &sx3Dn, "sx3Dn/I");
|
||||||
|
tree->Branch("sx3Bk", &sx3Bk, "sx3Bk/I");
|
||||||
|
tree->Branch("sx3ZFrac", &sx3ZFrac, "sx3ZFrac/D");
|
||||||
|
|
||||||
|
double reTheta, rePhi;
|
||||||
|
tree->Branch("reTheta", &reTheta, "reconstucted_theta/D");
|
||||||
|
tree->Branch("rePhi", &rePhi, "reconstucted_phi/D");
|
||||||
|
|
||||||
|
double reTheta1, rePhi1;
|
||||||
|
tree->Branch("reTheta1", &reTheta1, "reconstucted_theta1/D");
|
||||||
|
tree->Branch("rePhi1", &rePhi1, "reconstucted_phi1/D");
|
||||||
|
|
||||||
|
double z0;
|
||||||
|
tree->Branch("z0", &z0, "reconstucted_Z/D");
|
||||||
|
|
||||||
|
|
||||||
|
//========timer
|
||||||
|
TBenchmark clock;
|
||||||
|
bool shown ;
|
||||||
|
clock.Reset();
|
||||||
|
clock.Start("timer");
|
||||||
|
shown = false;
|
||||||
|
|
||||||
|
//================================= Calculate event
|
||||||
|
for( int i = 0; i < numEvent ; i++){
|
||||||
|
|
||||||
|
ExAID = gRandom->Integer(nExA);
|
||||||
|
ExA = ExAList[ExAID];
|
||||||
|
transfer.SetExA(ExA);
|
||||||
|
|
||||||
|
ExID = gRandom->Integer(nEx);
|
||||||
|
Ex = ExList[ExID];
|
||||||
|
transfer.SetExB(Ex);
|
||||||
|
|
||||||
|
transfer.CalReactionConstant();
|
||||||
|
|
||||||
|
thetaCM = TMath::ACos(2 * gRandom->Rndm() - 1) ;
|
||||||
|
phiCM = (gRandom->Rndm() - 0.5) * TMath::TwoPi();
|
||||||
|
|
||||||
|
//==== Calculate reaction
|
||||||
|
TLorentzVector * output = transfer.Event(thetaCM, phiCM);
|
||||||
|
TLorentzVector Pb = output[2];
|
||||||
|
TLorentzVector PB = output[3];
|
||||||
|
|
||||||
|
thetab = Pb.Theta() * TMath::RadToDeg();
|
||||||
|
thetaB = PB.Theta() * TMath::RadToDeg();
|
||||||
|
|
||||||
|
Tb = Pb.E() - Pb.M();
|
||||||
|
TB = PB.E() - PB.M();
|
||||||
|
|
||||||
|
phib = Pb.Phi() * TMath::RadToDeg();
|
||||||
|
phiB = PB.Phi() * TMath::RadToDeg();
|
||||||
|
|
||||||
|
vertexX = (vertexXRange[1]- vertexXRange[0])*gRandom->Rndm() + vertexXRange[0];
|
||||||
|
vertexY = (vertexYRange[1]- vertexYRange[0])*gRandom->Rndm() + vertexYRange[0];
|
||||||
|
vertexZ = (vertexZRange[1]- vertexZRange[0])*gRandom->Rndm() + vertexZRange[0];
|
||||||
|
|
||||||
|
TVector3 vertex(vertexX, vertexY, vertexZ);
|
||||||
|
|
||||||
|
TVector3 dir(1, 0, 0);
|
||||||
|
dir.SetTheta(thetab * TMath::DegToRad());
|
||||||
|
dir.SetPhi(phib * TMath::DegToRad());
|
||||||
|
|
||||||
|
|
||||||
|
pw->FindWireID(vertex, dir, false);
|
||||||
|
sx3->FindSX3Pos(vertex, dir, false);
|
||||||
|
|
||||||
|
PWHitInfo hitInfo = pw->GetHitInfo();
|
||||||
|
|
||||||
|
anodeID[0] = hitInfo.nearestWire.first;
|
||||||
|
cathodeID[0] = hitInfo.nearestWire.second;
|
||||||
|
anodeID[1] = hitInfo.nextNearestWire.first;
|
||||||
|
cathodeID[1] = hitInfo.nextNearestWire.second;
|
||||||
|
|
||||||
|
anodeDist[0] = hitInfo.nearestDist.first;
|
||||||
|
cathodeDist[0] = hitInfo.nearestDist.second;
|
||||||
|
anodeDist[1] = hitInfo.nextNearestDist.first;
|
||||||
|
cathodeDist[1] = hitInfo.nextNearestDist.second;
|
||||||
|
|
||||||
|
sx3ID = sx3->GetID();
|
||||||
|
if( sx3ID >= 0 ){
|
||||||
|
sx3Up = sx3->GetChUp();
|
||||||
|
sx3Dn = sx3->GetChDn();
|
||||||
|
sx3Bk = sx3->GetChBk();
|
||||||
|
sx3ZFrac = sx3->GetZFrac();
|
||||||
|
|
||||||
|
//Introduce uncertaity
|
||||||
|
// TVector3 hitPos = sx3->GetHitPos();
|
||||||
|
TVector3 hitPos = sx3->GetHitPosWithSigma(sigmaSX3_W, sigmaSX3_L);
|
||||||
|
|
||||||
|
sx3X = hitPos.X();
|
||||||
|
sx3Y = hitPos.Y();
|
||||||
|
sx3Z = hitPos.Z();
|
||||||
|
|
||||||
|
pw->CalTrack(hitPos, anodeID[0], cathodeID[0], false);
|
||||||
|
reTheta = pw->GetTrackTheta() * TMath::RadToDeg();
|
||||||
|
rePhi = pw->GetTrackPhi() * TMath::RadToDeg();
|
||||||
|
|
||||||
|
pw->CalTrack2(hitPos, hitInfo, sigmaPW_A, sigmaPW_C, false);
|
||||||
|
reTheta1 = pw->GetTrackTheta() * TMath::RadToDeg();
|
||||||
|
rePhi1 = pw->GetTrackPhi() * TMath::RadToDeg();
|
||||||
|
|
||||||
|
z0 = pw->GetZ0();
|
||||||
|
|
||||||
|
}else{
|
||||||
|
sx3Up = -1;
|
||||||
|
sx3Dn = -1;
|
||||||
|
sx3Bk = -1;
|
||||||
|
sx3ZFrac = TMath::QuietNaN();
|
||||||
|
|
||||||
|
sx3X = TMath::QuietNaN();
|
||||||
|
sx3Y = TMath::QuietNaN();
|
||||||
|
sx3Z = TMath::QuietNaN();
|
||||||
|
|
||||||
|
// for( int i = 0; i < 12; i++){
|
||||||
|
// sx3Index[i] = -1;
|
||||||
|
// }
|
||||||
|
|
||||||
|
reTheta = TMath::QuietNaN();
|
||||||
|
rePhi = TMath::QuietNaN();
|
||||||
|
|
||||||
|
reTheta1 = TMath::QuietNaN();
|
||||||
|
rePhi1 = TMath::QuietNaN();
|
||||||
|
|
||||||
|
z0 = TMath::QuietNaN();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
tree->Fill();
|
||||||
|
|
||||||
|
//#################################################################### Timer
|
||||||
|
clock.Stop("timer");
|
||||||
|
Double_t time = clock.GetRealTime("timer");
|
||||||
|
clock.Start("timer");
|
||||||
|
|
||||||
|
if ( !shown ) {
|
||||||
|
if (fmod(time, 10) < 1 ){
|
||||||
|
printf( "%10d[%2d%%]| %8.2f sec | expect: %5.1f min \n", i, TMath::Nint((i+1)*100./numEvent), time , numEvent*time/(i+1)/60);
|
||||||
|
shown = 1;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
if (fmod(time, 10) > 9 ){
|
||||||
|
shown = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
tree->Write();
|
||||||
|
int count = tree->GetEntries();
|
||||||
|
saveFile->Close();
|
||||||
|
|
||||||
|
printf("=============== done. saved as %s. count(hit==1) : %d\n", saveFileName.Data(), count);
|
||||||
|
|
||||||
|
delete anasen;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
}
|
||||||
105
Armory/Armory/constant.h
Normal file
105
Armory/Armory/constant.h
Normal file
|
|
@ -0,0 +1,105 @@
|
||||||
|
/***********************************************************************
|
||||||
|
*
|
||||||
|
* This is constant.h, to provide various physical constants.
|
||||||
|
*
|
||||||
|
*-------------------------------------------------------
|
||||||
|
* created by Ryan (Tsz Leung) Tang, Nov-18, 2018
|
||||||
|
* email: goluckyryan@gmail.com
|
||||||
|
* ********************************************************************/
|
||||||
|
|
||||||
|
#ifndef constant
|
||||||
|
#define constant
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
const double pi = acos(-1.0);
|
||||||
|
const double E = 2.718281828459 ;
|
||||||
|
const double hbar_SI = 1.054571628e-34; //Js
|
||||||
|
const double kB = 1.3806504e-23; //JK^-1
|
||||||
|
const double e = 1.602176487e-19; //C
|
||||||
|
const double c_SI = 299792458; //ms^-1
|
||||||
|
const double me_SI = 9.10938215e-31 ; //kg
|
||||||
|
const double mp_SI = 1.672621637e-27 ; //kg
|
||||||
|
const double mn_SI = 1.67492729e-27 ; //kg
|
||||||
|
const double NA = 6.022141e+23 ; //mol^-1
|
||||||
|
|
||||||
|
const double deg2rad = pi/180 ;
|
||||||
|
const double rad2deg = 180/pi ;
|
||||||
|
|
||||||
|
//======================================================================
|
||||||
|
const double amu = 931.49432; // MeV/c^2
|
||||||
|
const double hbarc = 197.326979; // MeV fm;
|
||||||
|
const double c = 299.792458; // mm/ns;
|
||||||
|
const double ee = 1.439964454; // MeV.fm
|
||||||
|
|
||||||
|
//======================================================================
|
||||||
|
double kg2MeV(double m){
|
||||||
|
return m*c_SI*c_SI/e/1e6;
|
||||||
|
}
|
||||||
|
|
||||||
|
double T2Brho(double mass, int Z, int A, double T){
|
||||||
|
//mass in MeV
|
||||||
|
// Z in e
|
||||||
|
// T in MeV/A
|
||||||
|
double gamma = (T*A + mass)/mass;
|
||||||
|
double beta = sqrt(1-1/gamma/gamma);
|
||||||
|
return mass*beta*gamma/Z/c;
|
||||||
|
}
|
||||||
|
|
||||||
|
double Brho2T(double mass, int Z, int A, double Brho){
|
||||||
|
//mass in MeV
|
||||||
|
// Z in e
|
||||||
|
return (sqrt(pow(Brho*Z*c,2)+mass*mass)-mass)/A;
|
||||||
|
}
|
||||||
|
|
||||||
|
double T2beta(double mass, int A, double T){
|
||||||
|
double gamma = 1.0 + T*A/mass;
|
||||||
|
return sqrt(1-1/gamma/gamma);
|
||||||
|
}
|
||||||
|
|
||||||
|
double ev2nm(double eV){
|
||||||
|
// photon energy to nm
|
||||||
|
return hbarc/2/pi/eV;
|
||||||
|
}
|
||||||
|
|
||||||
|
//======================================================================
|
||||||
|
const double mp = kg2MeV(mp_SI);
|
||||||
|
const double mn = kg2MeV(mn_SI);
|
||||||
|
const double hbar = 197.326979;
|
||||||
|
|
||||||
|
|
||||||
|
//======================================================================
|
||||||
|
inline std::vector<std::string> SplitStr(std::string tempLine, std::string splitter, int shift = 0){
|
||||||
|
|
||||||
|
std::vector<std::string> output;
|
||||||
|
|
||||||
|
size_t pos;
|
||||||
|
do{
|
||||||
|
pos = tempLine.find(splitter); /// fine splitter
|
||||||
|
if( pos == 0 ){ ///check if it is splitter again
|
||||||
|
tempLine = tempLine.substr(pos+1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string secStr;
|
||||||
|
if( pos == std::string::npos ){
|
||||||
|
secStr = tempLine;
|
||||||
|
}else{
|
||||||
|
secStr = tempLine.substr(0, pos+shift);
|
||||||
|
tempLine = tempLine.substr(pos+shift);
|
||||||
|
}
|
||||||
|
|
||||||
|
///check if secStr is begin with space
|
||||||
|
while( secStr.substr(0, 1) == " ") secStr = secStr.substr(1);
|
||||||
|
|
||||||
|
///check if secStr is end with space
|
||||||
|
while( secStr.back() == ' ') secStr = secStr.substr(0, secStr.size()-1);
|
||||||
|
|
||||||
|
output.push_back(secStr);
|
||||||
|
///printf(" |%s---\n", secStr.c_str());
|
||||||
|
|
||||||
|
}while(pos != std::string::npos );
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
1270
Armory/ClassData.h
Normal file
1270
Armory/ClassData.h
Normal file
File diff suppressed because it is too large
Load Diff
|
|
@ -14,6 +14,7 @@ public:
|
||||||
unsigned short ch[MAXMULTI];
|
unsigned short ch[MAXMULTI];
|
||||||
unsigned short e[MAXMULTI];
|
unsigned short e[MAXMULTI];
|
||||||
unsigned long long t[MAXMULTI];
|
unsigned long long t[MAXMULTI];
|
||||||
|
unsigned long long tf[MAXMULTI];
|
||||||
|
|
||||||
unsigned short sn[MAXMULTI];
|
unsigned short sn[MAXMULTI];
|
||||||
unsigned short digiCh[MAXMULTI];
|
unsigned short digiCh[MAXMULTI];
|
||||||
|
|
@ -28,6 +29,7 @@ public:
|
||||||
ch[i] = 0;
|
ch[i] = 0;
|
||||||
e[i] = 0;
|
e[i] = 0;
|
||||||
t[i] = 0;
|
t[i] = 0;
|
||||||
|
tf[i] = 0;
|
||||||
index[i] = 0;
|
index[i] = 0;
|
||||||
sn[i] = 0;
|
sn[i] = 0;
|
||||||
digiCh[i] = 0;
|
digiCh[i] = 0;
|
||||||
|
|
@ -38,7 +40,7 @@ public:
|
||||||
void Print(){
|
void Print(){
|
||||||
printf("=============================== multi : %u\n", multi);
|
printf("=============================== multi : %u\n", multi);
|
||||||
for( int i = 0; i < multi; i++) {
|
for( int i = 0; i < multi; i++) {
|
||||||
printf(" %3d | %2d-%-2d(%5d) %5u %15llu \n", i, id[i], ch[i], index[i], e[i], t[i]);
|
printf(" %3d | %2d-%-2d(%5d) %5u %15llu %15llu\n", i, id[i], ch[i], index[i], e[i], t[i], tf[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
683
Armory/ClassPW.h
683
Armory/ClassPW.h
|
|
@ -2,17 +2,21 @@
|
||||||
#define ClassPW_h
|
#define ClassPW_h
|
||||||
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
|
#include <iostream>
|
||||||
#include <TMath.h>
|
#include <TMath.h>
|
||||||
#include <TVector3.h>
|
#include <TVector3.h>
|
||||||
|
#include <TRandom.h>
|
||||||
|
|
||||||
struct PWHitInfo{
|
struct PWHitInfo
|
||||||
std::pair<short, short> nearestWire; // anode, cathode
|
{
|
||||||
|
std::pair<short, short> nearestWire; // anode, cathode
|
||||||
std::pair<double, double> nearestDist; // anode, cathode
|
std::pair<double, double> nearestDist; // anode, cathode
|
||||||
|
|
||||||
std::pair<short, short> nextNearestWire; // anode, cathode
|
std::pair<short, short> nextNearestWire; // anode, cathode
|
||||||
std::pair<double, double> nextNearestDist; // anode, cathode
|
std::pair<double, double> nextNearestDist; // anode, cathode
|
||||||
|
|
||||||
void Clear(){
|
void Clear()
|
||||||
|
{
|
||||||
nearestWire.first = -1;
|
nearestWire.first = -1;
|
||||||
nearestWire.second = -1;
|
nearestWire.second = -1;
|
||||||
nearestDist.first = 999999999;
|
nearestDist.first = 999999999;
|
||||||
|
|
@ -24,71 +28,99 @@ struct PWHitInfo{
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
//!########################################################
|
struct Coord
|
||||||
class PW{ // proportional wire
|
{
|
||||||
public:
|
double x, y, z;
|
||||||
PW(){ ClearHitInfo();};
|
Coord() : x(0), y(0), z(0) {}
|
||||||
~PW(){};
|
Coord(const TVector3 &vec)
|
||||||
|
{
|
||||||
|
x = vec.X(); // TVector3's X() returns the x-coordinate
|
||||||
|
y = vec.Y(); // TVector3's Y() returns the y-coordinate
|
||||||
|
z = vec.Z(); // TVector3's Z() returns the z-coordinate
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
PWHitInfo GetHitInfo() const {return hitInfo;}
|
//! ########################################################
|
||||||
std::pair<short, short> GetNearestID() const {return hitInfo.nearestWire;}
|
class PW
|
||||||
std::pair<double, double> GetNearestDistance() const {return hitInfo.nearestDist;}
|
{ // proportional wire
|
||||||
std::pair<short, short> Get2ndNearestID() const {return hitInfo.nextNearestWire;}
|
public:
|
||||||
std::pair<double, double> Get2ndNearestDistance() const {return hitInfo.nextNearestDist;}
|
PW() { ClearHitInfo(); };
|
||||||
|
~PW() {};
|
||||||
|
|
||||||
TVector3 GetTrackPos() const {return trackPos;}
|
PWHitInfo GetHitInfo() const { return hitInfo; }
|
||||||
TVector3 GetTrackVec() const {return trackVec;}
|
std::pair<short, short> GetNearestID() const { return hitInfo.nearestWire; }
|
||||||
double GetTrackTheta() const {return trackVec.Theta();}
|
std::pair<double, double> GetNearestDistance() const { return hitInfo.nearestDist; }
|
||||||
double GetTrackPhi() const {return trackVec.Phi();}
|
std::pair<short, short> Get2ndNearestID() const { return hitInfo.nextNearestWire; }
|
||||||
|
std::pair<double, double> Get2ndNearestDistance() const { return hitInfo.nextNearestDist; }
|
||||||
|
|
||||||
|
std::vector<std::pair<TVector3, TVector3>> An; // the anode wire position vector in space
|
||||||
|
std::vector<std::pair<TVector3, TVector3>> Ca; // the cathode wire position vector in space
|
||||||
|
|
||||||
|
TVector3 GetTrackPos() const { return trackPos; }
|
||||||
|
TVector3 GetTrackVec() const { return trackVec; }
|
||||||
|
double GetTrackTheta() const { return trackVec.Theta(); }
|
||||||
|
double GetTrackPhi() const { return trackVec.Phi(); }
|
||||||
double GetZ0();
|
double GetZ0();
|
||||||
|
|
||||||
|
Coord Crossover[24][24][2];
|
||||||
|
|
||||||
int GetNumWire() const {return nWire;}
|
inline TVector3 getClosestWirePosAtWirePhi(std::pair<TVector3, TVector3>, double phi);
|
||||||
double GetDeltaAngle() const {return dAngle;}
|
inline std::tuple<std::pair<TVector3, TVector3>, double, double, double> GetPseudoWire(const std::vector<std::tuple<int,double,double>>& cluster, std::string type);
|
||||||
double GetAnodeLength() const {return anodeLength;}
|
|
||||||
double GetCathodeLength() const {return cathodeLength;}
|
|
||||||
TVector3 GetAnodeDn(short id) const {return An[id].first;}
|
|
||||||
TVector3 GetAnodeUp(short id) const {return An[id].second;}
|
|
||||||
TVector3 GetCathodeDn(short id) const {return Ca[id].first;}
|
|
||||||
TVector3 GetCathodeUp(short id) const {return Ca[id].second;}
|
|
||||||
|
|
||||||
TVector3 GetAnodneMid(short id) const {return (An[id].first + An[id].second) * 0.5; }
|
inline std::tuple<TVector3,double,double,double,double,double,double,double>
|
||||||
double GetAnodeTheta(short id) const {return (An[id].first - An[id].second).Theta();}
|
FindCrossoverProperties(const std::vector<std::tuple<int,double,double>>& a_cluster, const std::vector<std::tuple<int,double,double>>& c_cluster);
|
||||||
double GetAnodePhi(short id) const {return (An[id].first - An[id].second).Phi();}
|
|
||||||
|
|
||||||
TVector3 GetCathodneMid(short id) const {return (Ca[id].first + Ca[id].second) * 0.5; }
|
inline std::vector<std::vector<std::tuple<int,double,double>>>
|
||||||
double GetCathodeTheta(short id) const {return (Ca[id].first - Ca[id].second).Theta();}
|
Make_Clusters(std::unordered_map<int,std::tuple<int,double,double>> wireEvents);
|
||||||
double GetCathodePhi(short id) const {return (Ca[id].first - Ca[id].second).Phi();}
|
|
||||||
|
int GetNumWire() const { return nWire; }
|
||||||
|
double GetDeltaAngle() const { return dAngle; }
|
||||||
|
double GetAnodeLength() const { return anodeLength; }
|
||||||
|
double GetCathodeLength() const { return cathodeLength; }
|
||||||
|
TVector3 GetAnodeDn(short id) const { return An[id].first; }
|
||||||
|
TVector3 GetAnodeUp(short id) const { return An[id].second; }
|
||||||
|
TVector3 GetCathodeDn(short id) const { return Ca[id].first; }
|
||||||
|
TVector3 GetCathodeUp(short id) const { return Ca[id].second; }
|
||||||
|
|
||||||
|
TVector3 GetAnodneMid(short id) const { return (An[id].first + An[id].second) * 0.5; }
|
||||||
|
double GetAnodeTheta(short id) const { return (An[id].first - An[id].second).Theta(); }
|
||||||
|
double GetAnodePhi(short id) const { return (An[id].first - An[id].second).Phi(); }
|
||||||
|
inline void PrintGeometry();
|
||||||
|
|
||||||
|
TVector3 GetCathodneMid(short id) const { return (Ca[id].first + Ca[id].second) * 0.5; }
|
||||||
|
double GetCathodeTheta(short id) const { return (Ca[id].first - Ca[id].second).Theta(); }
|
||||||
|
double GetCathodePhi(short id) const { return (Ca[id].first - Ca[id].second).Phi(); }
|
||||||
|
|
||||||
void ClearHitInfo();
|
void ClearHitInfo();
|
||||||
void ConstructGeo();
|
void ConstructGeo(int, int);
|
||||||
void FindWireID(TVector3 pos, TVector3 direction, bool verbose = false);
|
void FindWireID(TVector3 pos, TVector3 direction, bool verbose = false);
|
||||||
void CalTrack(TVector3 sx3Pos, int anodeID, int cathodeID, bool verbose = false);
|
void CalTrack(TVector3 sx3Pos, int anodeID, int cathodeID, bool verbose = false);
|
||||||
void CalTrack2(TVector3 sx3Pos, PWHitInfo hitInfo, double sigmaA = 0, double sigmaC = 0, bool verbose = false);
|
void CalTrack2(TVector3 sx3Pos, TVector3 anodeInt, bool verbose = false);
|
||||||
|
|
||||||
double CircularMean(std::vector<std::pair<int, double>> wireList);
|
void Print()
|
||||||
|
{
|
||||||
|
printf(" The nearest | Anode: %2d(%5.2f) Cathode: %2d(%5.2f)\n", hitInfo.nearestWire.first,
|
||||||
|
hitInfo.nearestDist.first,
|
||||||
|
hitInfo.nearestWire.second,
|
||||||
|
hitInfo.nearestDist.second);
|
||||||
|
|
||||||
void Print(){
|
printf(" The 2nd nearest | Anode: %2d(%5.2f) Cathode: %2d(%5.2f)\n", hitInfo.nextNearestWire.first,
|
||||||
printf(" The nearest | Anode: %2d(%5.2f) Cathode: %2d(%5.2f)\n", hitInfo.nearestWire.first,
|
hitInfo.nextNearestDist.first,
|
||||||
hitInfo.nearestDist.first,
|
hitInfo.nextNearestWire.second,
|
||||||
hitInfo.nearestWire.second,
|
hitInfo.nextNearestDist.second);
|
||||||
hitInfo.nearestDist.second);
|
|
||||||
|
|
||||||
printf(" The 2nd nearest | Anode: %2d(%5.2f) Cathode: %2d(%5.2f)\n", hitInfo.nextNearestWire.first,
|
|
||||||
hitInfo.nextNearestDist.first,
|
|
||||||
hitInfo.nextNearestWire.second,
|
|
||||||
hitInfo.nextNearestDist.second);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
PWHitInfo hitInfo;
|
PWHitInfo hitInfo;
|
||||||
|
|
||||||
TVector3 trackPos;
|
TVector3 trackPos;
|
||||||
TVector3 trackVec;
|
TVector3 trackVec;
|
||||||
|
|
||||||
const int nWire = 24;
|
const int nWire = 24;
|
||||||
const int wireShift = 3;
|
const int wireShift = 4;
|
||||||
const float zLen = 380; //mm
|
//const float zLen = 380; // mm
|
||||||
|
// const float zLen = 348.6; // mm
|
||||||
|
const float zLen = 174.3*2; // mm
|
||||||
const float radiusA = 37;
|
const float radiusA = 37;
|
||||||
const float radiusC = 43;
|
const float radiusC = 43;
|
||||||
|
|
||||||
|
|
@ -96,23 +128,25 @@ private:
|
||||||
double anodeLength;
|
double anodeLength;
|
||||||
double cathodeLength;
|
double cathodeLength;
|
||||||
|
|
||||||
std::vector<std::pair<TVector3,TVector3>> An; // the anode wire position vector in space
|
// std::vector<std::pair<TVector3, TVector3>> An; // the anode wire position vector in space
|
||||||
std::vector<std::pair<TVector3,TVector3>> Ca; // the cathode wire position vector in space
|
// std::vector<std::pair<TVector3, TVector3>> Ca; // the cathode wire position vector in space
|
||||||
|
|
||||||
double Distance(TVector3 a1, TVector3 a2, TVector3 b1, TVector3 b2){
|
double Distance(TVector3 a1, TVector3 a2, TVector3 b1, TVector3 b2)
|
||||||
|
{
|
||||||
TVector3 na = a1 - a2;
|
TVector3 na = a1 - a2;
|
||||||
TVector3 nb = b1 - b2;
|
TVector3 nb = b1 - b2;
|
||||||
TVector3 nd = (na.Cross(nb)).Unit();
|
TVector3 nd = (na.Cross(nb)).Unit();
|
||||||
return TMath::Abs(nd.Dot(a1-b2));
|
return TMath::Abs(nd.Dot(a1 - b2));
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
inline void PW::ClearHitInfo(){
|
inline void PW::ClearHitInfo()
|
||||||
|
{
|
||||||
hitInfo.Clear();
|
hitInfo.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void PW::ConstructGeo(){
|
inline void PW::ConstructGeo(int aoffset=0, int coffset=0)
|
||||||
|
{
|
||||||
|
|
||||||
An.clear();
|
An.clear();
|
||||||
Ca.clear();
|
Ca.clear();
|
||||||
|
|
@ -120,108 +154,458 @@ inline void PW::ConstructGeo(){
|
||||||
std::pair<TVector3, TVector3> p1; // anode
|
std::pair<TVector3, TVector3> p1; // anode
|
||||||
std::pair<TVector3, TVector3> q1; // cathode
|
std::pair<TVector3, TVector3> q1; // cathode
|
||||||
|
|
||||||
//anode and cathode start at pos-Y axis and count in right-Hand
|
double k = TMath::TwoPi()/24.; //48 solder thru holes, wires in every other one
|
||||||
//anode wire shift is right-hand.
|
double offset_a1 = -6*k-4*k;//-5*k-5*k;
|
||||||
//cathode wire shift is left-hand.
|
double offset_c1 = -6*k+k/2.; //correct for a half-turn, 48 holes out of which 24 are used, anodes and cathodes staggered by half a turn. //-5*k-TMath::TwoPi()/48;
|
||||||
|
//std::cerr << "Here!" << std::endl;
|
||||||
|
//#include "../scratch/testing.h"
|
||||||
|
double offset_a2 = offset_a1+wireShift*k;
|
||||||
|
double offset_c2 = offset_c1-wireShift*k;
|
||||||
|
|
||||||
for(int i = 0; i < nWire; i++ ){
|
for (int i = 0; i < nWire; i++)
|
||||||
// Anode rotate right-hand
|
{
|
||||||
p1.first.SetXYZ( radiusA * TMath::Cos( TMath::TwoPi() / nWire * (i) + TMath::PiOver2()),
|
// Anode rotate right-hand coming in towards +z riding with the beam. In this frame, +x is to the right, and +y down
|
||||||
radiusA * TMath::Sin( TMath::TwoPi() / nWire * (i) + TMath::PiOver2()),
|
//updated Feb 2026, Sudarsan B. Photographs indicate that anode wires twist right handed, as one moves from -z to +z with the convention above
|
||||||
zLen/2);
|
//wire indices increase leftward as one moves to +z (hence -k factor), but wires themselves twist rightward - as indicated by offset_a2 being more +ve w.r.t offset_a1
|
||||||
p1.second.SetXYZ( radiusA * TMath::Cos( TMath::TwoPi() / nWire * (i + wireShift) + TMath::PiOver2()),
|
//'First' is -z locus, 'second' is +z locus
|
||||||
radiusA * TMath::Sin( TMath::TwoPi() / nWire * (i + wireShift) + TMath::PiOver2()),
|
p1.first.SetXYZ(radiusA * TMath::Cos(-k*i + offset_a1),
|
||||||
-zLen/2);
|
radiusA * TMath::Sin(-k*i + offset_a1),
|
||||||
|
-zLen / 2);
|
||||||
|
p1.second.SetXYZ(radiusA * TMath::Cos(-k*i + offset_a2),
|
||||||
|
radiusA * TMath::Sin(-k*i + offset_a2),
|
||||||
|
+zLen / 2);
|
||||||
|
|
||||||
|
// Cathodes twist left-hand as indicated by offset_c2 being more negative than offset_c1, under the same system, while wires increase rightward (hence +k factor)
|
||||||
|
q1.first.SetXYZ(radiusC * TMath::Cos(k*i + offset_c1),
|
||||||
|
radiusC * TMath::Sin(k*i + offset_c1),
|
||||||
|
-zLen / 2);
|
||||||
|
q1.second.SetXYZ(radiusC * TMath::Cos(k*i + offset_c2),
|
||||||
|
radiusC * TMath::Sin(k*i + offset_c2),
|
||||||
|
zLen / 2);
|
||||||
An.push_back(p1);
|
An.push_back(p1);
|
||||||
|
|
||||||
// Cathod rotate left-hand
|
|
||||||
q1.first.SetXYZ( radiusC * TMath::Cos( TMath::TwoPi() / nWire * (i) + TMath::PiOver2()),
|
|
||||||
radiusC * TMath::Sin( TMath::TwoPi() / nWire * (i) + TMath::PiOver2()),
|
|
||||||
zLen/2);
|
|
||||||
q1.second.SetXYZ( radiusC * TMath::Cos( TMath::TwoPi() / nWire * (i - wireShift) + TMath::PiOver2()),
|
|
||||||
radiusC * TMath::Sin( TMath::TwoPi() / nWire * (i - wireShift) + TMath::PiOver2()),
|
|
||||||
-zLen/2);
|
|
||||||
Ca.push_back(q1);
|
Ca.push_back(q1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Calculate Crossover Geometry ONCE
|
||||||
|
TVector3 a, c, diff;
|
||||||
|
double a2, ac, c2, adiff, cdiff, denom, alpha;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < An.size(); i++)
|
||||||
|
{
|
||||||
|
//a = An[i].first - An[i].second;
|
||||||
|
a = An[i].second - An[i].first;
|
||||||
|
for (size_t j = 0; j < Ca.size(); j++)
|
||||||
|
{
|
||||||
|
c = Ca[j].second- Ca[j].first;
|
||||||
|
diff = An[i].second - Ca[j].second;
|
||||||
|
a2 = a.Dot(a);
|
||||||
|
c2 = c.Dot(c);
|
||||||
|
ac = a.Dot(c);
|
||||||
|
adiff = a.Dot(diff);
|
||||||
|
cdiff = c.Dot(diff);
|
||||||
|
denom = a2 * c2 - ac * ac;
|
||||||
|
alpha = (ac * cdiff - c2 * adiff) / denom;
|
||||||
|
|
||||||
|
Crossover[i][j][0].x = An[i].second.X() + alpha * a.X();
|
||||||
|
Crossover[i][j][0].y = An[i].second.Y() + alpha * a.Y();
|
||||||
|
Crossover[i][j][0].z = An[i].second.Z() + alpha * a.Z();
|
||||||
|
|
||||||
|
if(Crossover[i][j][0].z < -190 || Crossover[i][j][0].z > 190) {
|
||||||
|
//std::cout << "Weird crossover but ok" << std::endl;
|
||||||
|
}
|
||||||
|
if ( (i+j)%24 == 12 || Crossover[i][j][0].z < -190 || Crossover[i][j][0].z > 190) {
|
||||||
|
Crossover[i][j][0].z = 9999999;
|
||||||
|
//std::cout << "Weird crossover" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
Crossover[i][j][1].x = alpha;
|
||||||
|
Crossover[i][j][1].y = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
dAngle = wireShift * TMath::TwoPi() / nWire;
|
dAngle = wireShift * TMath::TwoPi() / nWire;
|
||||||
anodeLength = TMath::Sqrt( zLen*zLen + TMath::Power(2* radiusA * TMath::Sin(dAngle/2),2) );
|
anodeLength = TMath::Sqrt(zLen * zLen + TMath::Power(2 * radiusA * TMath::Sin(dAngle / 2), 2));
|
||||||
cathodeLength = TMath::Sqrt( zLen*zLen + TMath::Power(2* radiusC * TMath::Sin(dAngle/2),2) );
|
cathodeLength = TMath::Sqrt(zLen * zLen + TMath::Power(2 * radiusC * TMath::Sin(dAngle / 2), 2)); //chord length subtending an angle alpha is 2rsin(alpha/2)
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void PW::FindWireID(TVector3 pos, TVector3 direction, bool verbose ){
|
inline void PW::PrintGeometry() {
|
||||||
|
for (size_t i = 0; i < An.size(); i++)
|
||||||
|
{
|
||||||
|
for (size_t j = 0; j < Ca.size(); j++) {
|
||||||
|
if ( Crossover[i][j][0].z < -190 || Crossover[i][j][0].z > 190) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << i << ", " << j << ", " << Crossover[i][j][0].x << ", " << Crossover[i][j][0].y << ", " << Crossover[i][j][0].z << ", " << Crossover[i][j][1].x << ", "
|
||||||
|
<< An[i].first.X() << ", "
|
||||||
|
<< An[i].first.Y() << ", "
|
||||||
|
<< An[i].first.Z() << ", "
|
||||||
|
|
||||||
|
<< Ca[j].first.X() << ", "
|
||||||
|
<< Ca[j].first.Y() << ", "
|
||||||
|
<< Ca[j].first.Z() << ", "
|
||||||
|
|
||||||
|
<< An[i].second.X() << ", "
|
||||||
|
<< An[i].second.Y() << ", "
|
||||||
|
<< An[i].second.Z() << ", "
|
||||||
|
|
||||||
|
<< Ca[j].second.X() << ", "
|
||||||
|
<< Ca[j].second.Y() << ", "
|
||||||
|
<< Ca[j].second.Z()
|
||||||
|
<< std::endl;
|
||||||
|
}
|
||||||
|
std::cout << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline TVector3 PW::getClosestWirePosAtWirePhi(std::pair<TVector3, TVector3> awire, double phi) //Faster function
|
||||||
|
{
|
||||||
|
const TVector3& a1 = awire.first;
|
||||||
|
const TVector3& a2 = awire.second;
|
||||||
|
const double s = TMath::Sin(phi), c = TMath::Cos(phi);
|
||||||
|
const double dx = a2.X() - a1.X(), dy = a2.Y() - a1.Y();
|
||||||
|
const double t = (a1.Y()*c - a1.X()*s) / (dx*s - dy*c); // denom != 0: wires always twist
|
||||||
|
|
||||||
|
auto nearerEndpoint = [&]() -> TVector3 {
|
||||||
|
auto dphi = [&](const TVector3& p) {
|
||||||
|
return TMath::Abs(TVector2::Phi_mpi_pi(phi - p.Phi()));
|
||||||
|
};
|
||||||
|
return dphi(a1) <= dphi(a2) ? a1 : a2;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (t < 0.0 || t > 1.0)
|
||||||
|
return nearerEndpoint();
|
||||||
|
|
||||||
|
const TVector3 hit = a1 + t * (a2 - a1);
|
||||||
|
if (hit.X()*c + hit.Y()*s <= 0.0) // wrong half-plane (anti-phi side)
|
||||||
|
return nearerEndpoint();
|
||||||
|
|
||||||
|
return hit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*inline TVector3 PW::getClosestWirePosAtWirePhi(std::pair<TVector3, TVector3> awire, double sx3phi_radian) {
|
||||||
|
// 1. Get wire geometry
|
||||||
|
TVector3 a1 = awire.first; // Top of the wire
|
||||||
|
TVector3 a2 = awire.second; // Bottom of the wire
|
||||||
|
TVector3 wireVec = a2 - a1; // Vector pointing down the wire
|
||||||
|
|
||||||
|
// Variables to track our minimums during the scan
|
||||||
|
double min_delta_phi = 9999.0;
|
||||||
|
double best_t = -1.0;
|
||||||
|
TVector3 best_pcz_intersect;
|
||||||
|
|
||||||
|
// 2. THE SCAN: Walk down the wire in 1000 tiny steps
|
||||||
|
// (For a 380mm wire, this is checking every 0.38 mm)
|
||||||
|
int num_steps = 1000;
|
||||||
|
for (int i = 0; i <= num_steps; ++i)
|
||||||
|
{
|
||||||
|
double t_test = (double)i / num_steps; // Ranges from 0.0 to 1.0
|
||||||
|
TVector3 test_pt = a1 + t_test * wireVec; // The 3D point at this step
|
||||||
|
|
||||||
|
// Calculate absolute Delta Phi between Si hit and this specific point on the wire
|
||||||
|
if(TMath::IsNaN(sx3phi_radian-test_pt.Phi())) {
|
||||||
|
//std::cout << "Moo" << std::endl;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
double dPhi = TMath::Abs(TVector2::Phi_mpi_pi(sx3phi_radian - test_pt.Phi())); //Phi_mpi_pi just puts the angle in the range -180 to 180
|
||||||
|
//std::cout << "Yee" << std::endl;
|
||||||
|
|
||||||
|
// If this is the smallest Delta Phi we've seen so far, save it!
|
||||||
|
if (dPhi < min_delta_phi)
|
||||||
|
{
|
||||||
|
min_delta_phi = dPhi;
|
||||||
|
best_t = t_test;
|
||||||
|
best_pcz_intersect = test_pt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return best_pcz_intersect;
|
||||||
|
}*/
|
||||||
|
|
||||||
|
|
||||||
|
inline std::vector<std::vector<std::tuple<int,double,double>>>
|
||||||
|
PW::Make_Clusters(std::unordered_map<int,std::tuple<int,double,double>> wireEvents) {
|
||||||
|
std::vector<std::vector<std::tuple<int,double,double>>> wireClusters;
|
||||||
|
std::vector<std::tuple<int,double,double>> wireCluster;
|
||||||
|
//TODO: Write a macro once, call it twice
|
||||||
|
int wirecount=0;
|
||||||
|
while(wirecount < 24) {
|
||||||
|
if(wireEvents.find(wirecount)==wireEvents.end()) {
|
||||||
|
wirecount++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
wireCluster.clear();
|
||||||
|
int ctr2=wirecount;
|
||||||
|
do {
|
||||||
|
wireCluster.emplace_back(wireEvents[ctr2]);
|
||||||
|
ctr2+=1;
|
||||||
|
if(ctr2==24 || ctr2-wirecount == 7) break; //loose logic, needs to be looked at.
|
||||||
|
} while(wireEvents.find(ctr2)!=wireEvents.end());
|
||||||
|
wireClusters.push_back(std::move(wireCluster));
|
||||||
|
wirecount = ctr2; //we already dealt with wires until the last value of ctr2
|
||||||
|
}
|
||||||
|
|
||||||
|
if(wireClusters.size() > 1) { //Deal with wraparound if required
|
||||||
|
auto first_cluster = wireClusters.front(); //front and back provide references to the elements themselves. less copy, can modify etc
|
||||||
|
auto last_cluster = wireClusters.back();
|
||||||
|
if(std::get<0>(last_cluster.back())==23 && std::get<0>(first_cluster.front())==0) {
|
||||||
|
last_cluster.insert(last_cluster.end(),first_cluster.begin(),first_cluster.end());
|
||||||
|
}
|
||||||
|
wireClusters.erase(wireClusters.begin()); //canonically, erase() needs an iterator, hence begin() not front()
|
||||||
|
//TODO: Can also deal with 'gaps' of missing wires similarly. end of one segment and beginning of another segment will be separated by missing wire --> combine the two
|
||||||
|
//TODO: Also needs some development regarding the time-correlation. Don't put wires in the same cluster if they aren't time coincident
|
||||||
|
}
|
||||||
|
return wireClusters;
|
||||||
|
|
||||||
|
/*if(aClusters.size()>1 || cClusters.size() > 1) {
|
||||||
|
std::cout << " ============== " << std::endl;
|
||||||
|
}
|
||||||
|
if(aClusters.size()>1 && cClusters.size() >=1) {
|
||||||
|
std::cout << aClusters.size() << " new anode clusters ----> " << std::endl;
|
||||||
|
int cc=1;
|
||||||
|
for(auto ac : aClusters) {
|
||||||
|
std::cout << " Cluster " << cc << std::endl;
|
||||||
|
double first_ts = std::get<2>(ac.at(0));
|
||||||
|
for(auto item : ac) {
|
||||||
|
std::cout << " \t" << std::get<0>(item) << " " << std::get<1>(item) << " " << std::get<2>(item)-first_ts << std::endl;
|
||||||
|
}
|
||||||
|
std::cout << " ------" << std::endl;
|
||||||
|
cc++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(cClusters.size()>=1 ) {
|
||||||
|
std::cout << cClusters.size() << " new cathode clusters ----> " << std::endl;
|
||||||
|
int cc=1;
|
||||||
|
for(auto ac : cClusters) {
|
||||||
|
std::cout << " Cluster " << cc << std::endl;
|
||||||
|
double first_ts = std::get<2>(ac.at(0));
|
||||||
|
for(auto item : ac) {
|
||||||
|
std::cout << " \t" << std::get<0>(item) << " " << std::get<1>(item) << " " << std::get<2>(item)-first_ts << std::endl;
|
||||||
|
}
|
||||||
|
std::cout << " ------" << std::endl;
|
||||||
|
cc++;
|
||||||
|
}
|
||||||
|
} */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* inline TVector3 getRawCrossover(int anodeIndex, int cathodeIndex1, int cathodeIndex2, double cathodeE1, double cathodeE2) {
|
||||||
|
* return (Crossover[anodeIndex][cathodeIndex1][0]*cathodeE1 + Crossover[anodeIndex][cathodeIndex2][0]*cathodeE2)/(cathodeE1+cathodeE2);
|
||||||
|
* }
|
||||||
|
*
|
||||||
|
* */
|
||||||
|
inline std::tuple<std::pair<TVector3, TVector3>, double, double, double>
|
||||||
|
PW::GetPseudoWire(const std::vector<std::tuple<int,double,double>>& cluster, std::string type) {
|
||||||
|
std::pair<TVector3,TVector3> avgvec = std::pair(TVector3(0,0,0),TVector3(0,0,0));
|
||||||
|
double sumEnergy = 0;
|
||||||
|
double maxEnergy = 0;
|
||||||
|
double tsMaxEnergy = 0;
|
||||||
|
if(type=="ANODE") {
|
||||||
|
//if(cluster.size()>1) std::cout << " -------anodes" << std::endl;
|
||||||
|
for( auto wire : cluster) {
|
||||||
|
avgvec.first += std::get<1>(wire)*TVector3(An.at(std::get<0>(wire)).first.X(), An.at(std::get<0>(wire)).first.Y(), 0) ;
|
||||||
|
avgvec.second += std::get<1>(wire)*TVector3(An.at(std::get<0>(wire)).second.X(), An.at(std::get<0>(wire)).second.Y(), 0);
|
||||||
|
sumEnergy += std::get<1>(wire);
|
||||||
|
if(std::get<1>(wire) > maxEnergy) {
|
||||||
|
maxEnergy = std::get<1>(wire);
|
||||||
|
tsMaxEnergy = std::get<2>(wire);
|
||||||
|
}
|
||||||
|
/*if(cluster.size()>1) {
|
||||||
|
std::cout << "\t\t ch:" << std::get<0>(wire) << " " << std::get<1>(wire) << " " << std::get<2>(wire) << std::endl;
|
||||||
|
std::cout << "\t\t w1(r,phi,z):" << An.at(std::get<0>(wire)).first.Perp() << " " << An.at(std::get<0>(wire)).first.Phi()*180/M_PI << " " << An.at(std::get<0>(wire)).first.Z() << std::endl;
|
||||||
|
std::cout << "\t\t w2(r,phi,z):" << An.at(std::get<0>(wire)).second.Perp() << " " << An.at(std::get<0>(wire)).second.Phi()*180/M_PI << " " << An.at(std::get<0>(wire)).second.Z() << std::endl;
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
avgvec.first = avgvec.first*(1.0/sumEnergy);
|
||||||
|
avgvec.second = avgvec.second*(1.0/sumEnergy);
|
||||||
|
double phi1 = avgvec.first.Phi();
|
||||||
|
double phi2 = avgvec.second.Phi();
|
||||||
|
avgvec.first.SetXYZ(radiusA*TMath::Cos(phi1), radiusA*TMath::Sin(phi1), -zLen/2);
|
||||||
|
avgvec.second.SetXYZ(radiusA*TMath::Cos(phi2), radiusA*TMath::Sin(phi2), zLen/2);
|
||||||
|
/*if(cluster.size()>1) {
|
||||||
|
std::cout << "\t\t avg1(r,phi,z):" << avgvec.first.Perp() << " " << avgvec.first.Phi()*180/M_PI << " " << avgvec.first.Z() << std::endl;
|
||||||
|
std::cout << "\t\t avg2(r,phi,z):" << avgvec.second.Perp() << " " << avgvec.second.Phi()*180/M_PI << " " << avgvec.second.Z() << std::endl;
|
||||||
|
}*/
|
||||||
|
} else if(type =="CATHODE") {
|
||||||
|
for( auto wire : cluster) {
|
||||||
|
avgvec.first += std::get<1>(wire)*TVector3(Ca.at(std::get<0>(wire)).first.X(), Ca.at(std::get<0>(wire)).first.Y(), 0) ;
|
||||||
|
avgvec.second += std::get<1>(wire)*TVector3(Ca.at(std::get<0>(wire)).second.X(), Ca.at(std::get<0>(wire)).second.Y(), 0);
|
||||||
|
sumEnergy += std::get<1>(wire);
|
||||||
|
if(std::get<1>(wire) > maxEnergy) {
|
||||||
|
maxEnergy = std::get<1>(wire);
|
||||||
|
tsMaxEnergy = std::get<2>(wire);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
avgvec.first = avgvec.first*(1.0/sumEnergy);
|
||||||
|
avgvec.second = avgvec.second*(1.0/sumEnergy);
|
||||||
|
double phi1 = avgvec.first.Phi();
|
||||||
|
double phi2 = avgvec.second.Phi();
|
||||||
|
avgvec.first.SetXYZ(radiusC*TMath::Cos(phi1), radiusC*TMath::Sin(phi1), -zLen/2);
|
||||||
|
avgvec.second.SetXYZ(radiusC*TMath::Cos(phi2), radiusC*TMath::Sin(phi2), zLen/2);
|
||||||
|
}
|
||||||
|
return std::tuple(avgvec, sumEnergy, maxEnergy, tsMaxEnergy);
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <TGraph.h>
|
||||||
|
|
||||||
|
double FastEval(TGraph* graph, double x) {
|
||||||
|
Double_t* x_arr = graph->GetX();
|
||||||
|
Double_t* y_arr = graph->GetY();
|
||||||
|
Int_t n = graph->GetN();
|
||||||
|
|
||||||
|
// Ensure array is sorted before using binary search
|
||||||
|
auto it = std::lower_bound(x_arr, x_arr + n, x);
|
||||||
|
|
||||||
|
if (it == x_arr) return y_arr[0];
|
||||||
|
if (it == x_arr + n) return y_arr[n - 1];
|
||||||
|
|
||||||
|
int idx = std::distance(x_arr, it);
|
||||||
|
double x1 = x_arr[idx - 1];
|
||||||
|
double x2 = x_arr[idx];
|
||||||
|
double y1 = y_arr[idx - 1];
|
||||||
|
double y2 = y_arr[idx];
|
||||||
|
|
||||||
|
// Linear interpolation
|
||||||
|
return y1 + (x - x1) * (y2 - y1) / (x2 - x1);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline std::tuple<TVector3,double,double,double,double,double,double,double> PW::FindCrossoverProperties(const std::vector<std::tuple<int,double,double>>& a_cluster,
|
||||||
|
const std::vector<std::tuple<int,double,double>>& c_cluster) {
|
||||||
|
//std::pair<TVector3, TVector3> apwire = GetPseudoWire(a_cluster,"ANODE",anodeSumE);
|
||||||
|
//std::pair<TVector3, TVector3> cpwire = GetPseudoWire(c_cluster,"CATHODE",cathodeSumE);
|
||||||
|
auto [apwire, apSumE, apMaxE, apTSMaxE] = GetPseudoWire(a_cluster,"ANODE");
|
||||||
|
auto [cpwire, cpSumE, cpMaxE, cpTSMaxE] = GetPseudoWire(c_cluster,"CATHODE");
|
||||||
|
|
||||||
|
TVector3 crossover;
|
||||||
|
crossover.Clear();
|
||||||
|
TVector3 a, c, diff;
|
||||||
|
double a2, ac, c2, adiff, cdiff, denom, alpha=0;
|
||||||
|
|
||||||
|
if(apSumE && cpSumE) {
|
||||||
|
a = apwire.first - apwire.second;
|
||||||
|
c = cpwire.first - cpwire.second;
|
||||||
|
diff = apwire.first- cpwire.first;
|
||||||
|
a2 = a.Dot(a);
|
||||||
|
c2 = c.Dot(c);
|
||||||
|
ac = a.Dot(c);
|
||||||
|
adiff = a.Dot(diff);
|
||||||
|
cdiff = c.Dot(diff);
|
||||||
|
denom = a2 * c2 - ac * ac;
|
||||||
|
alpha = (ac * cdiff - c2 * adiff) / denom;
|
||||||
|
crossover = apwire.first + alpha*a;
|
||||||
|
if(crossover.z() < -190 || crossover.Z() > 190 ) {
|
||||||
|
alpha = 9999999;
|
||||||
|
apSumE=-1; cpSumE=-1;
|
||||||
|
apMaxE=-1; cpMaxE=-1;
|
||||||
|
apTSMaxE=-1; cpTSMaxE=-1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//std::cout << apSumE << " " << cpSumE << " " << " " << crossover.Perp() << std::endl;
|
||||||
|
return std::tuple(crossover,alpha,apSumE,cpSumE,apMaxE,cpMaxE,apTSMaxE,cpTSMaxE);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void PW::FindWireID(TVector3 pos, TVector3 direction, bool verbose)
|
||||||
|
{
|
||||||
|
|
||||||
hitInfo.Clear();
|
hitInfo.Clear();
|
||||||
double phi = direction.Phi();
|
double phi = direction.Phi();
|
||||||
|
|
||||||
for( int i = 0; i < nWire; i++){
|
for (int i = 0; i < nWire; i++)
|
||||||
|
{
|
||||||
|
|
||||||
double disA = 99999999;
|
double disA = 99999999;
|
||||||
double phiS = An[i].first.Phi() - TMath::PiOver4();
|
double phiS = An[i].first.Phi() - TMath::PiOver4();
|
||||||
double phiL = An[i].second.Phi() + TMath::PiOver4();
|
double phiL = An[i].second.Phi() + TMath::PiOver4();
|
||||||
// printf("A%2d: %f %f | %f\n", i, phiS * TMath::RadToDeg(), phiL * TMath::RadToDeg(), phi * TMath::RadToDeg());
|
// printf("A%2d: %f %f | %f\n", i, phiS * TMath::RadToDeg(), phiL * TMath::RadToDeg(), phi * TMath::RadToDeg());
|
||||||
if( phi > 0 && phiS > phiL ) phiL = phiL + TMath::TwoPi();
|
if (phi > 0 && phiS > phiL)
|
||||||
if( phi < 0 && phiS > phiL ) phiS = phiS - TMath::TwoPi();
|
phiL = phiL + TMath::TwoPi();
|
||||||
|
if (phi < 0 && phiS > phiL)
|
||||||
|
phiS = phiS - TMath::TwoPi();
|
||||||
|
|
||||||
if( phiS < phi && phi < phiL) {
|
if (phiS < phi && phi < phiL)
|
||||||
disA = Distance( pos, pos + direction, An[i].first, An[i].second);
|
{
|
||||||
if( disA < hitInfo.nearestDist.first ){
|
disA = Distance(pos, pos + direction, An[i].first, An[i].second);
|
||||||
|
if (disA < hitInfo.nearestDist.first)
|
||||||
|
{
|
||||||
hitInfo.nearestDist.first = disA;
|
hitInfo.nearestDist.first = disA;
|
||||||
hitInfo.nearestWire.first = i;
|
hitInfo.nearestWire.first = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
double disC = 99999999;
|
double disC = 99999999;
|
||||||
phiS = Ca[i].second.Phi()- TMath::PiOver4();
|
phiS = Ca[i].second.Phi() - TMath::PiOver4();
|
||||||
phiL = Ca[i].first.Phi() + TMath::PiOver4();
|
phiL = Ca[i].first.Phi() + TMath::PiOver4();
|
||||||
// printf("C%2d: %f %f\n", i, phiS * TMath::RadToDeg(), phiL * TMath::RadToDeg());
|
// printf("C%2d: %f %f\n", i, phiS * TMath::RadToDeg(), phiL * TMath::RadToDeg());
|
||||||
if( phi > 0 && phiS > phiL ) phiL = phiL + TMath::TwoPi();
|
if (phi > 0 && phiS > phiL)
|
||||||
if( phi < 0 && phiS > phiL ) phiS = phiS - TMath::TwoPi();
|
phiL = phiL + TMath::TwoPi();
|
||||||
|
if (phi < 0 && phiS > phiL)
|
||||||
|
phiS = phiS - TMath::TwoPi();
|
||||||
|
|
||||||
if(phiS < phi && phi < phiL) {
|
if (phiS < phi && phi < phiL)
|
||||||
disC = Distance( pos, pos + direction, Ca[i].first, Ca[i].second);
|
{
|
||||||
if( disC < hitInfo.nearestDist.second ){
|
disC = Distance(pos, pos + direction, Ca[i].first, Ca[i].second);
|
||||||
|
if (disC < hitInfo.nearestDist.second)
|
||||||
|
{
|
||||||
hitInfo.nearestDist.second = disC;
|
hitInfo.nearestDist.second = disC;
|
||||||
hitInfo.nearestWire.second = i;
|
hitInfo.nearestWire.second = i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(verbose) printf(" %2d | %8.2f, %8.2f\n", i, disA, disC);
|
if (verbose)
|
||||||
|
printf(" %2d | %8.2f, %8.2f\n", i, disA, disC);
|
||||||
}
|
}
|
||||||
|
|
||||||
//==== find the 2nd nearest wire
|
//==== find the 2nd nearest wire
|
||||||
short anode1 = hitInfo.nearestWire.first;
|
short anode1 = hitInfo.nearestWire.first;
|
||||||
short aaa1 = anode1 - 1; if( aaa1 < 0 ) aaa1 += nWire;
|
short aaa1 = anode1 - 1;
|
||||||
short aaa2 = (anode1 + 1) % nWire;
|
if (aaa1 < 0)
|
||||||
|
aaa1 += nWire;
|
||||||
|
short aaa2 = (anode1 + 1) % nWire;
|
||||||
|
|
||||||
double haha1 = Distance( pos, pos + direction, An[aaa1].first, An[aaa1].second);
|
double haha1 = Distance(pos, pos + direction, An[aaa1].first, An[aaa1].second);
|
||||||
double haha2 = Distance( pos, pos + direction, An[aaa2].first, An[aaa2].second);
|
double haha2 = Distance(pos, pos + direction, An[aaa2].first, An[aaa2].second);
|
||||||
if( haha1 < haha2){
|
if (haha1 < haha2)
|
||||||
|
{
|
||||||
hitInfo.nextNearestWire.first = aaa1;
|
hitInfo.nextNearestWire.first = aaa1;
|
||||||
hitInfo.nextNearestDist.first = haha1;
|
hitInfo.nextNearestDist.first = haha1;
|
||||||
}else{
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
hitInfo.nextNearestWire.first = aaa2;
|
hitInfo.nextNearestWire.first = aaa2;
|
||||||
hitInfo.nextNearestDist.first = haha2;
|
hitInfo.nextNearestDist.first = haha2;
|
||||||
}
|
}
|
||||||
|
|
||||||
short cathode1 = hitInfo.nearestWire.second;
|
short cathode1 = hitInfo.nearestWire.second;
|
||||||
short ccc1 = cathode1 - 1; if( ccc1 < 0 ) ccc1 += nWire;
|
short ccc1 = cathode1 - 1;
|
||||||
short ccc2 = (cathode1 + 1) % nWire;
|
if (ccc1 < 0)
|
||||||
|
ccc1 += nWire;
|
||||||
|
short ccc2 = (cathode1 + 1) % nWire;
|
||||||
|
|
||||||
haha1 = Distance( pos, pos + direction, Ca[ccc1].first, Ca[ccc1].second);
|
haha1 = Distance(pos, pos + direction, Ca[ccc1].first, Ca[ccc1].second);
|
||||||
haha2 = Distance( pos, pos + direction, Ca[ccc2].first, Ca[ccc2].second);
|
haha2 = Distance(pos, pos + direction, Ca[ccc2].first, Ca[ccc2].second);
|
||||||
if( haha1 < haha2){
|
if (haha1 < haha2)
|
||||||
|
{
|
||||||
hitInfo.nextNearestWire.second = ccc1;
|
hitInfo.nextNearestWire.second = ccc1;
|
||||||
hitInfo.nextNearestDist.second = haha1;
|
hitInfo.nextNearestDist.second = haha1;
|
||||||
}else{
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
hitInfo.nextNearestWire.second = ccc2;
|
hitInfo.nextNearestWire.second = ccc2;
|
||||||
hitInfo.nextNearestDist.second = haha2;
|
hitInfo.nextNearestDist.second = haha2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if( verbose ) Print();
|
if (verbose)
|
||||||
|
Print();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void PW::CalTrack(TVector3 sx3Pos, int anodeID, int cathodeID, bool verbose){
|
inline void PW::CalTrack(TVector3 sx3Pos, int anodeID, int cathodeID, bool verbose)
|
||||||
|
{
|
||||||
|
|
||||||
trackPos = sx3Pos;
|
trackPos = sx3Pos;
|
||||||
|
|
||||||
|
|
@ -231,72 +615,49 @@ inline void PW::CalTrack(TVector3 sx3Pos, int anodeID, int cathodeID, bool verbo
|
||||||
// if the handiness of anode and cathode revered, it should be n2 cross n1
|
// if the handiness of anode and cathode revered, it should be n2 cross n1
|
||||||
trackVec = (n2.Cross(n1)).Unit();
|
trackVec = (n2.Cross(n1)).Unit();
|
||||||
|
|
||||||
if( verbose ) printf("Theta, Phi = %f, %f \n", trackVec.Theta() *TMath::RadToDeg(), trackVec.Phi()*TMath::RadToDeg());
|
if (verbose)
|
||||||
|
printf("Theta, Phi = %f, %f \n", trackVec.Theta() * TMath::RadToDeg(), trackVec.Phi() * TMath::RadToDeg());
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void PW::CalTrack2(TVector3 sx3Pos, PWHitInfo hitInfo, double sigmaA, double sigmaC, bool verbose){
|
|
||||||
|
|
||||||
trackPos = sx3Pos;
|
inline void PW::CalTrack2(TVector3 siPos, TVector3 anodeInt, bool verbose)
|
||||||
|
{
|
||||||
|
|
||||||
double p1 = TMath::Abs(hitInfo.nearestDist.first + gRandom->Gaus(0, sigmaA));
|
double mx, my;
|
||||||
double p2 = TMath::Abs(hitInfo.nextNearestDist.first + gRandom->Gaus(0, sigmaA));
|
double z;
|
||||||
double fracA = p1 / (p1 + p2);
|
mx = siPos.X() / (siPos.X() - anodeInt.X());
|
||||||
short anodeID1 = hitInfo.nearestWire.first;
|
my = siPos.Y() / (siPos.Y() - anodeInt.Y());
|
||||||
short anodeID2 = hitInfo.nextNearestWire.first;
|
z=siPos.Z() + mx * (anodeInt.Z() - siPos.Z());
|
||||||
TVector3 shiftA1 = (An[anodeID2].first - An[anodeID1].first) * fracA;
|
// if (mx == my)
|
||||||
TVector3 shiftA2 = (An[anodeID2].second - An[anodeID1].second) * fracA;
|
{
|
||||||
|
trackVec=TVector3(0,0,z);
|
||||||
double q1 = TMath::Abs(hitInfo.nearestDist.second + gRandom->Gaus(0, sigmaC));
|
}
|
||||||
double q2 = TMath::Abs(hitInfo.nextNearestDist.second + gRandom->Gaus(0, sigmaC));
|
|
||||||
double fracC = q1 / (q1 + q2);
|
|
||||||
short cathodeID1 = hitInfo.nearestWire.second;
|
|
||||||
short cathodeID2 = hitInfo.nextNearestWire.second;
|
|
||||||
TVector3 shiftC1 = (Ca[cathodeID2].first - Ca[cathodeID1].first) * fracC;
|
|
||||||
TVector3 shiftC2 = (Ca[cathodeID2].second - Ca[cathodeID1].second) * fracC;
|
|
||||||
|
|
||||||
TVector3 a1 = An[anodeID1].first + shiftA1;
|
|
||||||
TVector3 a2 = An[anodeID1].second + shiftA2;
|
|
||||||
|
|
||||||
TVector3 c1 = Ca[cathodeID1].first + shiftC1;
|
|
||||||
TVector3 c2 = Ca[cathodeID1].second + shiftC2;
|
|
||||||
|
|
||||||
TVector3 n1 = (a1 - a2).Cross((sx3Pos - a2)).Unit();
|
|
||||||
TVector3 n2 = (c1 - c2).Cross((sx3Pos - c2)).Unit();
|
|
||||||
|
|
||||||
// if the handiness of anode and cathode revered, it should be n2 cross n1
|
|
||||||
trackVec = (n2.Cross(n1)).Unit();
|
|
||||||
|
|
||||||
if( verbose ) printf("Theta, Phi = %f, %f \n", trackVec.Theta() *TMath::RadToDeg(), trackVec.Phi()*TMath::RadToDeg());
|
|
||||||
|
|
||||||
|
if (verbose)
|
||||||
|
printf("X slope = %f and Y slope = %f \n", mx, my);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline double PW::GetZ0(){
|
/*inline TVector3 PW::CalTrack3(TVector3 siPos, TVector3 anodeInt, bool verbose)
|
||||||
|
{
|
||||||
|
|
||||||
|
TVector3 v = anodeInt-siPos;
|
||||||
|
double t_minimum = -1.0*(siPos.X()*v.X()+siPos.Y()*v.Y())/(v.X()*v.X()+v.Y()*v.Y());
|
||||||
|
TVector3 vector_closest_to_z = siPos + t_minimum*v;
|
||||||
|
|
||||||
|
return vector_closest_to_z;
|
||||||
|
if (verbose)
|
||||||
|
printf("X slope = %f and Y slope = %f \n", mx, my);
|
||||||
|
}*/
|
||||||
|
|
||||||
|
inline double PW::GetZ0()
|
||||||
|
{
|
||||||
|
|
||||||
double x = trackPos.X();
|
double x = trackPos.X();
|
||||||
double y = trackPos.Y();
|
double y = trackPos.Y();
|
||||||
double rho = TMath::Sqrt(x*x + y*y);
|
double rho = TMath::Sqrt(x * x + y * y);
|
||||||
double theta = trackVec.Theta();
|
double theta = trackVec.Theta();
|
||||||
|
|
||||||
return trackPos.Z() - rho / TMath::Tan(theta);
|
|
||||||
|
|
||||||
|
return trackVec.Z();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline double PW::CircularMean(std::vector<std::pair<int, double>> wireList){
|
#endif
|
||||||
|
|
||||||
//use unit vector, wireID start from Zero
|
|
||||||
double xCom = 0, yCom = 0;
|
|
||||||
for( size_t i = 0; i < wireList.size() ; i++){
|
|
||||||
xCom += TMath::Cos(TMath::TwoPi() * wireList[i].first / nWire) * wireList[i].second;
|
|
||||||
yCom += TMath::Sin(TMath::TwoPi() * wireList[i].first / nWire) * wireList[i].second;
|
|
||||||
}
|
|
||||||
|
|
||||||
//calculate the angle of the summed unit vectors
|
|
||||||
double angle = TMath::ATan2(yCom, xCom);
|
|
||||||
if( angle < 0 ) angle += TMath::TwoPi(); // convert the angle from 0 to 2 pi
|
|
||||||
|
|
||||||
return angle/ TMath::TwoPi() * nWire;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
|
||||||
491
Armory/ClassPW.h.Questionable.Feb2026
Normal file
491
Armory/ClassPW.h.Questionable.Feb2026
Normal file
|
|
@ -0,0 +1,491 @@
|
||||||
|
#ifndef ClassPW_h
|
||||||
|
#define ClassPW_h
|
||||||
|
|
||||||
|
#include <cstdio>
|
||||||
|
#include <iostream>
|
||||||
|
#include <TMath.h>
|
||||||
|
#include <TVector3.h>
|
||||||
|
#include <TRandom.h>
|
||||||
|
|
||||||
|
struct PWHitInfo
|
||||||
|
{
|
||||||
|
std::pair<short, short> nearestWire; // anode, cathode
|
||||||
|
std::pair<double, double> nearestDist; // anode, cathode
|
||||||
|
|
||||||
|
std::pair<short, short> nextNearestWire; // anode, cathode
|
||||||
|
std::pair<double, double> nextNearestDist; // anode, cathode
|
||||||
|
|
||||||
|
void Clear()
|
||||||
|
{
|
||||||
|
nearestWire.first = -1;
|
||||||
|
nearestWire.second = -1;
|
||||||
|
nearestDist.first = 999999999;
|
||||||
|
nearestDist.second = 999999999;
|
||||||
|
nextNearestWire.first = -1;
|
||||||
|
nextNearestWire.second = -1;
|
||||||
|
nextNearestDist.first = 999999999;
|
||||||
|
nextNearestDist.second = 999999999;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Coord
|
||||||
|
{
|
||||||
|
float x, y, z;
|
||||||
|
Coord() : x(0), y(0), z(0) {}
|
||||||
|
Coord(const TVector3 &vec)
|
||||||
|
{
|
||||||
|
x = vec.X(); // TVector3's X() returns the x-coordinate
|
||||||
|
y = vec.Y(); // TVector3's Y() returns the y-coordinate
|
||||||
|
z = vec.Z(); // TVector3's Z() returns the z-coordinate
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//! ########################################################
|
||||||
|
class PW
|
||||||
|
{ // proportional wire
|
||||||
|
public:
|
||||||
|
PW() { ClearHitInfo(); };
|
||||||
|
~PW() {};
|
||||||
|
|
||||||
|
PWHitInfo GetHitInfo() const { return hitInfo; }
|
||||||
|
std::pair<short, short> GetNearestID() const { return hitInfo.nearestWire; }
|
||||||
|
std::pair<double, double> GetNearestDistance() const { return hitInfo.nearestDist; }
|
||||||
|
std::pair<short, short> Get2ndNearestID() const { return hitInfo.nextNearestWire; }
|
||||||
|
std::pair<double, double> Get2ndNearestDistance() const { return hitInfo.nextNearestDist; }
|
||||||
|
|
||||||
|
std::vector<std::pair<TVector3, TVector3>> An; // the anode wire position vector in space
|
||||||
|
std::vector<std::pair<TVector3, TVector3>> Ca; // the cathode wire position vector in space
|
||||||
|
|
||||||
|
TVector3 GetTrackPos() const { return trackPos; }
|
||||||
|
TVector3 GetTrackVec() const { return trackVec; }
|
||||||
|
double GetTrackTheta() const { return trackVec.Theta(); }
|
||||||
|
double GetTrackPhi() const { return trackVec.Phi(); }
|
||||||
|
double GetZ0();
|
||||||
|
|
||||||
|
inline std::tuple<std::pair<TVector3, TVector3>, double, double, double> GetPseudoWire(const std::vector<std::tuple<int,double,double>>& cluster, std::string type);
|
||||||
|
|
||||||
|
inline std::tuple<TVector3,double,double,double,double,double,double,double>
|
||||||
|
FindCrossoverProperties(const std::vector<std::tuple<int,double,double>>& a_cluster, const std::vector<std::tuple<int,double,double>>& c_cluster);
|
||||||
|
|
||||||
|
inline std::vector<std::vector<std::tuple<int,double,double>>>
|
||||||
|
Make_Clusters(std::unordered_map<int,std::tuple<int,double,double>> wireEvents);
|
||||||
|
|
||||||
|
int GetNumWire() const { return nWire; }
|
||||||
|
double GetDeltaAngle() const { return dAngle; }
|
||||||
|
double GetAnodeLength() const { return anodeLength; }
|
||||||
|
double GetCathodeLength() const { return cathodeLength; }
|
||||||
|
TVector3 GetAnodeDn(short id) const { return An[id].first; }
|
||||||
|
TVector3 GetAnodeUp(short id) const { return An[id].second; }
|
||||||
|
TVector3 GetCathodeDn(short id) const { return Ca[id].first; }
|
||||||
|
TVector3 GetCathodeUp(short id) const { return Ca[id].second; }
|
||||||
|
|
||||||
|
TVector3 GetAnodneMid(short id) const { return (An[id].first + An[id].second) * 0.5; }
|
||||||
|
double GetAnodeTheta(short id) const { return (An[id].first - An[id].second).Theta(); }
|
||||||
|
double GetAnodePhi(short id) const { return (An[id].first - An[id].second).Phi(); }
|
||||||
|
|
||||||
|
TVector3 GetCathodneMid(short id) const { return (Ca[id].first + Ca[id].second) * 0.5; }
|
||||||
|
double GetCathodeTheta(short id) const { return (Ca[id].first - Ca[id].second).Theta(); }
|
||||||
|
double GetCathodePhi(short id) const { return (Ca[id].first - Ca[id].second).Phi(); }
|
||||||
|
|
||||||
|
void ClearHitInfo();
|
||||||
|
void ConstructGeo();
|
||||||
|
void FindWireID(TVector3 pos, TVector3 direction, bool verbose = false);
|
||||||
|
void CalTrack(TVector3 sx3Pos, int anodeID, int cathodeID, bool verbose = false);
|
||||||
|
void CalTrack2(TVector3 sx3Pos, TVector3 anodeInt, bool verbose = false);
|
||||||
|
|
||||||
|
void Print()
|
||||||
|
{
|
||||||
|
printf(" The nearest | Anode: %2d(%5.2f) Cathode: %2d(%5.2f)\n", hitInfo.nearestWire.first,
|
||||||
|
hitInfo.nearestDist.first,
|
||||||
|
hitInfo.nearestWire.second,
|
||||||
|
hitInfo.nearestDist.second);
|
||||||
|
|
||||||
|
printf(" The 2nd nearest | Anode: %2d(%5.2f) Cathode: %2d(%5.2f)\n", hitInfo.nextNearestWire.first,
|
||||||
|
hitInfo.nextNearestDist.first,
|
||||||
|
hitInfo.nextNearestWire.second,
|
||||||
|
hitInfo.nextNearestDist.second);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
PWHitInfo hitInfo;
|
||||||
|
|
||||||
|
TVector3 trackPos;
|
||||||
|
TVector3 trackVec;
|
||||||
|
|
||||||
|
const int nWire = 24;
|
||||||
|
const int wireShift = 3;
|
||||||
|
//const float zLen = 380; // mm
|
||||||
|
const float zLen = 348.6; // mm
|
||||||
|
const float radiusA = 37;
|
||||||
|
const float radiusC = 43;
|
||||||
|
|
||||||
|
double dAngle;
|
||||||
|
double anodeLength;
|
||||||
|
double cathodeLength;
|
||||||
|
|
||||||
|
// std::vector<std::pair<TVector3, TVector3>> An; // the anode wire position vector in space
|
||||||
|
// std::vector<std::pair<TVector3, TVector3>> Ca; // the cathode wire position vector in space
|
||||||
|
|
||||||
|
double Distance(TVector3 a1, TVector3 a2, TVector3 b1, TVector3 b2)
|
||||||
|
{
|
||||||
|
TVector3 na = a1 - a2;
|
||||||
|
TVector3 nb = b1 - b2;
|
||||||
|
TVector3 nd = (na.Cross(nb)).Unit();
|
||||||
|
return TMath::Abs(nd.Dot(a1 - b2));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
inline void PW::ClearHitInfo()
|
||||||
|
{
|
||||||
|
hitInfo.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void PW::ConstructGeo()
|
||||||
|
{
|
||||||
|
|
||||||
|
An.clear();
|
||||||
|
Ca.clear();
|
||||||
|
|
||||||
|
std::pair<TVector3, TVector3> p1; // anode
|
||||||
|
std::pair<TVector3, TVector3> q1; // cathode
|
||||||
|
|
||||||
|
// anode and cathode start at pos-Y axis and count in right-Hand
|
||||||
|
// anode wire shift is right-hand.
|
||||||
|
// cathode wire shift is left-hand.
|
||||||
|
|
||||||
|
for (int i = 0; i < nWire; i++)
|
||||||
|
{
|
||||||
|
// Anode rotate right-hand
|
||||||
|
//updated Feb 2026, Sudarsan B
|
||||||
|
p1.first.SetXYZ(radiusA * TMath::Cos(TMath::TwoPi() / nWire * (i) + TMath::PiOver2()),
|
||||||
|
radiusA * TMath::Sin(TMath::TwoPi() / nWire * (i) + TMath::PiOver2()),
|
||||||
|
zLen / 2);
|
||||||
|
p1.second.SetXYZ(radiusA * TMath::Cos(TMath::TwoPi() / nWire * (i + wireShift) + TMath::PiOver2()),
|
||||||
|
radiusA * TMath::Sin(TMath::TwoPi() / nWire * (i + wireShift) + TMath::PiOver2()),
|
||||||
|
-zLen / 2);
|
||||||
|
An.push_back(p1);
|
||||||
|
|
||||||
|
// Cathod rotate left-hand with the 3 wire offset accounted for (+1 from the calculated offset from the PC coincidence spectrum)
|
||||||
|
q1.first.SetXYZ(radiusC * TMath::Cos(TMath::TwoPi() / nWire * (i + wireShift + 1) + TMath::PiOver2()),
|
||||||
|
radiusC * TMath::Sin(TMath::TwoPi() / nWire * (i + wireShift + 1) + TMath::PiOver2()),
|
||||||
|
zLen / 2);
|
||||||
|
q1.second.SetXYZ(radiusC * TMath::Cos(TMath::TwoPi() / nWire * (i + 1) + TMath::PiOver2()),
|
||||||
|
radiusC * TMath::Sin(TMath::TwoPi() / nWire * (i + 1) + TMath::PiOver2()),
|
||||||
|
-zLen / 2);
|
||||||
|
Ca.push_back(q1);
|
||||||
|
}
|
||||||
|
// correcting for the fact that the order of the cathode wires is reversed
|
||||||
|
std::reverse(Ca.begin(), Ca.end());
|
||||||
|
// adjusting for the 3 wire offset, the rbegin and rend are used as the rotation of the wires is done in the opposite direction i.e. 1,2,3 -> 3,1,2
|
||||||
|
// NOT NECESSARY ANY MORE, HAS BEEN IMCORPORATED INTO THE WIREOFFSET IN THE BEGINNING
|
||||||
|
// std::rotate(Ca.rbegin(), Ca.rbegin() + 4, Ca.rend());
|
||||||
|
|
||||||
|
dAngle = wireShift * TMath::TwoPi() / nWire;
|
||||||
|
anodeLength = TMath::Sqrt(zLen * zLen + TMath::Power(2 * radiusA * TMath::Sin(dAngle / 2), 2));
|
||||||
|
cathodeLength = TMath::Sqrt(zLen * zLen + TMath::Power(2 * radiusC * TMath::Sin(dAngle / 2), 2)); //chord length subtending an angle alpha is 2rsin(alpha/2)
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::vector<std::vector<std::tuple<int,double,double>>>
|
||||||
|
PW::Make_Clusters(std::unordered_map<int,std::tuple<int,double,double>> wireEvents) {
|
||||||
|
std::vector<std::vector<std::tuple<int,double,double>>> wireClusters;
|
||||||
|
std::vector<std::tuple<int,double,double>> wireCluster;
|
||||||
|
//TODO: Write a macro once, call it twice
|
||||||
|
int wirecount=0;
|
||||||
|
while(wirecount < 24) {
|
||||||
|
if(wireEvents.find(wirecount)==wireEvents.end()) {
|
||||||
|
wirecount++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
wireCluster.clear();
|
||||||
|
int ctr2=wirecount;
|
||||||
|
do {
|
||||||
|
wireCluster.emplace_back(wireEvents[ctr2]);
|
||||||
|
ctr2+=1;
|
||||||
|
if(ctr2==24 || ctr2-wirecount == 7) break; //loose logic, needs to be looked at.
|
||||||
|
} while(wireEvents.find(ctr2)!=wireEvents.end());
|
||||||
|
wireClusters.push_back(std::move(wireCluster));
|
||||||
|
wirecount = ctr2; //we already dealt with wires until the last value of ctr2
|
||||||
|
}
|
||||||
|
|
||||||
|
if(wireClusters.size() > 1) { //Deal with wraparound if required
|
||||||
|
auto first_cluster = wireClusters.front(); //front and back provide references to the elements themselves. less copy, can modify etc
|
||||||
|
auto last_cluster = wireClusters.back();
|
||||||
|
if(std::get<0>(last_cluster.back())==23 && std::get<0>(first_cluster.front())==0) {
|
||||||
|
last_cluster.insert(last_cluster.end(),first_cluster.begin(),first_cluster.end());
|
||||||
|
}
|
||||||
|
wireClusters.erase(wireClusters.begin()); //canonically, erase() needs an iterator, hence begin() not front()
|
||||||
|
//TODO: Can also deal with 'gaps' of missing wires similarly. end of one segment and beginning of another segment will be separated by missing wire --> combine the two
|
||||||
|
//TODO: Also needs some development regarding the time-correlation. Don't put wires in the same cluster if they aren't time coincident
|
||||||
|
}
|
||||||
|
return wireClusters;
|
||||||
|
|
||||||
|
/*if(aClusters.size()>1 || cClusters.size() > 1) {
|
||||||
|
std::cout << " ============== " << std::endl;
|
||||||
|
}
|
||||||
|
if(aClusters.size()>1 && cClusters.size() >=1) {
|
||||||
|
std::cout << aClusters.size() << " new anode clusters ----> " << std::endl;
|
||||||
|
int cc=1;
|
||||||
|
for(auto ac : aClusters) {
|
||||||
|
std::cout << " Cluster " << cc << std::endl;
|
||||||
|
double first_ts = std::get<2>(ac.at(0));
|
||||||
|
for(auto item : ac) {
|
||||||
|
std::cout << " \t" << std::get<0>(item) << " " << std::get<1>(item) << " " << std::get<2>(item)-first_ts << std::endl;
|
||||||
|
}
|
||||||
|
std::cout << " ------" << std::endl;
|
||||||
|
cc++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(cClusters.size()>=1 ) {
|
||||||
|
std::cout << cClusters.size() << " new cathode clusters ----> " << std::endl;
|
||||||
|
int cc=1;
|
||||||
|
for(auto ac : cClusters) {
|
||||||
|
std::cout << " Cluster " << cc << std::endl;
|
||||||
|
double first_ts = std::get<2>(ac.at(0));
|
||||||
|
for(auto item : ac) {
|
||||||
|
std::cout << " \t" << std::get<0>(item) << " " << std::get<1>(item) << " " << std::get<2>(item)-first_ts << std::endl;
|
||||||
|
}
|
||||||
|
std::cout << " ------" << std::endl;
|
||||||
|
cc++;
|
||||||
|
}
|
||||||
|
} */
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::tuple<std::pair<TVector3, TVector3>, double, double, double>
|
||||||
|
PW::GetPseudoWire(const std::vector<std::tuple<int,double,double>>& cluster, std::string type) {
|
||||||
|
std::pair<TVector3,TVector3> avgvec = std::pair(TVector3(0,0,0),TVector3(0,0,0));
|
||||||
|
double sumEnergy = 0;
|
||||||
|
double maxEnergy = 0;
|
||||||
|
double tsMaxEnergy = 0;
|
||||||
|
if(type=="ANODE") {
|
||||||
|
//if(cluster.size()>1) std::cout << " -------anodes" << std::endl;
|
||||||
|
for( auto wire : cluster) {
|
||||||
|
avgvec.first += std::get<1>(wire)*TVector3(An.at(std::get<0>(wire)).first.X(), An.at(std::get<0>(wire)).first.Y(), 0) ;
|
||||||
|
avgvec.second += std::get<1>(wire)*TVector3(An.at(std::get<0>(wire)).second.X(), An.at(std::get<0>(wire)).second.Y(), 0);
|
||||||
|
sumEnergy += std::get<1>(wire);
|
||||||
|
if(std::get<1>(wire) > maxEnergy) {
|
||||||
|
maxEnergy = std::get<1>(wire);
|
||||||
|
tsMaxEnergy = std::get<2>(wire);
|
||||||
|
}
|
||||||
|
/*if(cluster.size()>1) {
|
||||||
|
std::cout << "\t\t ch:" << std::get<0>(wire) << " " << std::get<1>(wire) << " " << std::get<2>(wire) << std::endl;
|
||||||
|
std::cout << "\t\t w1(r,phi,z):" << An.at(std::get<0>(wire)).first.Perp() << " " << An.at(std::get<0>(wire)).first.Phi()*180/M_PI << " " << An.at(std::get<0>(wire)).first.Z() << std::endl;
|
||||||
|
std::cout << "\t\t w2(r,phi,z):" << An.at(std::get<0>(wire)).second.Perp() << " " << An.at(std::get<0>(wire)).second.Phi()*180/M_PI << " " << An.at(std::get<0>(wire)).second.Z() << std::endl;
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
avgvec.first = avgvec.first*(1.0/sumEnergy);
|
||||||
|
avgvec.second = avgvec.second*(1.0/sumEnergy);
|
||||||
|
double phi1 = avgvec.first.Phi();
|
||||||
|
double phi2 = avgvec.second.Phi();
|
||||||
|
avgvec.first.SetXYZ(radiusA*TMath::Cos(phi1), radiusA*TMath::Sin(phi1), zLen/2);
|
||||||
|
avgvec.second.SetXYZ(radiusA*TMath::Cos(phi2), radiusA*TMath::Sin(phi2), -zLen/2);
|
||||||
|
/*if(cluster.size()>1) {
|
||||||
|
std::cout << "\t\t avg1(r,phi,z):" << avgvec.first.Perp() << " " << avgvec.first.Phi()*180/M_PI << " " << avgvec.first.Z() << std::endl;
|
||||||
|
std::cout << "\t\t avg2(r,phi,z):" << avgvec.second.Perp() << " " << avgvec.second.Phi()*180/M_PI << " " << avgvec.second.Z() << std::endl;
|
||||||
|
}*/
|
||||||
|
} else if(type =="CATHODE") {
|
||||||
|
for( auto wire : cluster) {
|
||||||
|
avgvec.first += std::get<1>(wire)*TVector3(Ca.at(std::get<0>(wire)).first.X(), Ca.at(std::get<0>(wire)).first.Y(), 0) ;
|
||||||
|
avgvec.second += std::get<1>(wire)*TVector3(Ca.at(std::get<0>(wire)).second.X(), Ca.at(std::get<0>(wire)).second.Y(), 0);
|
||||||
|
sumEnergy += std::get<1>(wire);
|
||||||
|
if(std::get<1>(wire) > maxEnergy) {
|
||||||
|
maxEnergy = std::get<1>(wire);
|
||||||
|
tsMaxEnergy = std::get<2>(wire);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
avgvec.first = avgvec.first*(1.0/sumEnergy);
|
||||||
|
avgvec.second = avgvec.second*(1.0/sumEnergy);
|
||||||
|
double phi1 = avgvec.first.Phi();
|
||||||
|
double phi2 = avgvec.second.Phi();
|
||||||
|
avgvec.first.SetXYZ(radiusC*TMath::Cos(phi1), radiusC*TMath::Sin(phi1), zLen/2);
|
||||||
|
avgvec.second.SetXYZ(radiusC*TMath::Cos(phi2), radiusC*TMath::Sin(phi2), -zLen/2);
|
||||||
|
}
|
||||||
|
return std::tuple(avgvec, sumEnergy, maxEnergy, tsMaxEnergy);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::tuple<TVector3,double,double,double,double,double,double,double> PW::FindCrossoverProperties(const std::vector<std::tuple<int,double,double>>& a_cluster,
|
||||||
|
const std::vector<std::tuple<int,double,double>>& c_cluster) {
|
||||||
|
//std::pair<TVector3, TVector3> apwire = GetPseudoWire(a_cluster,"ANODE",anodeSumE);
|
||||||
|
//std::pair<TVector3, TVector3> cpwire = GetPseudoWire(c_cluster,"CATHODE",cathodeSumE);
|
||||||
|
auto [apwire, apSumE, apMaxE, apTSMaxE] = GetPseudoWire(a_cluster,"ANODE");
|
||||||
|
auto [cpwire, cpSumE, cpMaxE, cpTSMaxE] = GetPseudoWire(c_cluster,"CATHODE");
|
||||||
|
|
||||||
|
TVector3 crossover;
|
||||||
|
crossover.Clear();
|
||||||
|
TVector3 a, c, diff;
|
||||||
|
double a2, ac, c2, adiff, cdiff, denom, alpha=0;
|
||||||
|
|
||||||
|
if(apSumE && cpSumE) {
|
||||||
|
a = apwire.first - apwire.second;
|
||||||
|
c = cpwire.first - cpwire.second;
|
||||||
|
diff = apwire.first - cpwire.first;
|
||||||
|
a2 = a.Dot(a);
|
||||||
|
c2 = c.Dot(c);
|
||||||
|
ac = a.Dot(c);
|
||||||
|
adiff = a.Dot(diff);
|
||||||
|
cdiff = c.Dot(diff);
|
||||||
|
denom = a2 * c2 - ac * ac;
|
||||||
|
alpha = (ac * cdiff - c2 * adiff) / denom;
|
||||||
|
crossover = apwire.first + alpha*a;
|
||||||
|
if(crossover.z() < -190 || crossover.Z() > 190 ) {
|
||||||
|
alpha = 9999999;
|
||||||
|
apSumE=-1; cpSumE=-1;
|
||||||
|
apMaxE=-1; cpMaxE=-1;
|
||||||
|
apTSMaxE=-1; cpTSMaxE=-1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//std::cout << apSumE << " " << cpSumE << " " << " " << crossover.Perp() << std::endl;
|
||||||
|
return std::tuple(crossover,alpha,apSumE,cpSumE,apMaxE,cpMaxE,apTSMaxE,cpTSMaxE);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void PW::FindWireID(TVector3 pos, TVector3 direction, bool verbose)
|
||||||
|
{
|
||||||
|
|
||||||
|
hitInfo.Clear();
|
||||||
|
double phi = direction.Phi();
|
||||||
|
|
||||||
|
for (int i = 0; i < nWire; i++)
|
||||||
|
{
|
||||||
|
|
||||||
|
double disA = 99999999;
|
||||||
|
double phiS = An[i].first.Phi() - TMath::PiOver4();
|
||||||
|
double phiL = An[i].second.Phi() + TMath::PiOver4();
|
||||||
|
// printf("A%2d: %f %f | %f\n", i, phiS * TMath::RadToDeg(), phiL * TMath::RadToDeg(), phi * TMath::RadToDeg());
|
||||||
|
if (phi > 0 && phiS > phiL)
|
||||||
|
phiL = phiL + TMath::TwoPi();
|
||||||
|
if (phi < 0 && phiS > phiL)
|
||||||
|
phiS = phiS - TMath::TwoPi();
|
||||||
|
|
||||||
|
if (phiS < phi && phi < phiL)
|
||||||
|
{
|
||||||
|
disA = Distance(pos, pos + direction, An[i].first, An[i].second);
|
||||||
|
if (disA < hitInfo.nearestDist.first)
|
||||||
|
{
|
||||||
|
hitInfo.nearestDist.first = disA;
|
||||||
|
hitInfo.nearestWire.first = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
double disC = 99999999;
|
||||||
|
phiS = Ca[i].second.Phi() - TMath::PiOver4();
|
||||||
|
phiL = Ca[i].first.Phi() + TMath::PiOver4();
|
||||||
|
// printf("C%2d: %f %f\n", i, phiS * TMath::RadToDeg(), phiL * TMath::RadToDeg());
|
||||||
|
if (phi > 0 && phiS > phiL)
|
||||||
|
phiL = phiL + TMath::TwoPi();
|
||||||
|
if (phi < 0 && phiS > phiL)
|
||||||
|
phiS = phiS - TMath::TwoPi();
|
||||||
|
|
||||||
|
if (phiS < phi && phi < phiL)
|
||||||
|
{
|
||||||
|
disC = Distance(pos, pos + direction, Ca[i].first, Ca[i].second);
|
||||||
|
if (disC < hitInfo.nearestDist.second)
|
||||||
|
{
|
||||||
|
hitInfo.nearestDist.second = disC;
|
||||||
|
hitInfo.nearestWire.second = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (verbose)
|
||||||
|
printf(" %2d | %8.2f, %8.2f\n", i, disA, disC);
|
||||||
|
}
|
||||||
|
|
||||||
|
//==== find the 2nd nearest wire
|
||||||
|
short anode1 = hitInfo.nearestWire.first;
|
||||||
|
short aaa1 = anode1 - 1;
|
||||||
|
if (aaa1 < 0)
|
||||||
|
aaa1 += nWire;
|
||||||
|
short aaa2 = (anode1 + 1) % nWire;
|
||||||
|
|
||||||
|
double haha1 = Distance(pos, pos + direction, An[aaa1].first, An[aaa1].second);
|
||||||
|
double haha2 = Distance(pos, pos + direction, An[aaa2].first, An[aaa2].second);
|
||||||
|
if (haha1 < haha2)
|
||||||
|
{
|
||||||
|
hitInfo.nextNearestWire.first = aaa1;
|
||||||
|
hitInfo.nextNearestDist.first = haha1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hitInfo.nextNearestWire.first = aaa2;
|
||||||
|
hitInfo.nextNearestDist.first = haha2;
|
||||||
|
}
|
||||||
|
|
||||||
|
short cathode1 = hitInfo.nearestWire.second;
|
||||||
|
short ccc1 = cathode1 - 1;
|
||||||
|
if (ccc1 < 0)
|
||||||
|
ccc1 += nWire;
|
||||||
|
short ccc2 = (cathode1 + 1) % nWire;
|
||||||
|
|
||||||
|
haha1 = Distance(pos, pos + direction, Ca[ccc1].first, Ca[ccc1].second);
|
||||||
|
haha2 = Distance(pos, pos + direction, Ca[ccc2].first, Ca[ccc2].second);
|
||||||
|
if (haha1 < haha2)
|
||||||
|
{
|
||||||
|
hitInfo.nextNearestWire.second = ccc1;
|
||||||
|
hitInfo.nextNearestDist.second = haha1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hitInfo.nextNearestWire.second = ccc2;
|
||||||
|
hitInfo.nextNearestDist.second = haha2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (verbose)
|
||||||
|
Print();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void PW::CalTrack(TVector3 sx3Pos, int anodeID, int cathodeID, bool verbose)
|
||||||
|
{
|
||||||
|
|
||||||
|
trackPos = sx3Pos;
|
||||||
|
|
||||||
|
TVector3 n1 = (An[anodeID].first - An[anodeID].second).Cross((sx3Pos - An[anodeID].second)).Unit();
|
||||||
|
TVector3 n2 = (Ca[cathodeID].first - Ca[cathodeID].second).Cross((sx3Pos - Ca[cathodeID].second)).Unit();
|
||||||
|
|
||||||
|
// if the handiness of anode and cathode revered, it should be n2 cross n1
|
||||||
|
trackVec = (n2.Cross(n1)).Unit();
|
||||||
|
|
||||||
|
if (verbose)
|
||||||
|
printf("Theta, Phi = %f, %f \n", trackVec.Theta() * TMath::RadToDeg(), trackVec.Phi() * TMath::RadToDeg());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void PW::CalTrack2(TVector3 siPos, TVector3 anodeInt, bool verbose)
|
||||||
|
{
|
||||||
|
|
||||||
|
double mx, my;
|
||||||
|
double z;
|
||||||
|
mx = siPos.X() / (siPos.X() - anodeInt.X());
|
||||||
|
my = siPos.Y() / (siPos.Y() - anodeInt.Y());
|
||||||
|
z=siPos.Z() + mx * (anodeInt.Z() - siPos.Z());
|
||||||
|
// if (mx == my)
|
||||||
|
{
|
||||||
|
trackVec=TVector3(0,0,z);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (verbose)
|
||||||
|
printf("X slope = %f and Y slope = %f \n", mx, my);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*inline TVector3 PW::CalTrack3(TVector3 siPos, TVector3 anodeInt, bool verbose)
|
||||||
|
{
|
||||||
|
|
||||||
|
TVector3 v = anodeInt-siPos;
|
||||||
|
double t_minimum = -1.0*(siPos.X()*v.X()+siPos.Y()*v.Y())/(v.X()*v.X()+v.Y()*v.Y());
|
||||||
|
TVector3 vector_closest_to_z = siPos + t_minimum*v;
|
||||||
|
|
||||||
|
return vector_closest_to_z;
|
||||||
|
if (verbose)
|
||||||
|
printf("X slope = %f and Y slope = %f \n", mx, my);
|
||||||
|
}*/
|
||||||
|
|
||||||
|
inline double PW::GetZ0()
|
||||||
|
{
|
||||||
|
|
||||||
|
double x = trackPos.X();
|
||||||
|
double y = trackPos.Y();
|
||||||
|
double rho = TMath::Sqrt(x * x + y * y);
|
||||||
|
double theta = trackVec.Theta();
|
||||||
|
|
||||||
|
return trackVec.Z();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
489
Armory/ClassPW.h.modified
Normal file
489
Armory/ClassPW.h.modified
Normal file
|
|
@ -0,0 +1,489 @@
|
||||||
|
#ifndef ClassPW_h
|
||||||
|
#define ClassPW_h
|
||||||
|
|
||||||
|
#include <cstdio>
|
||||||
|
#include <iostream>
|
||||||
|
#include <TMath.h>
|
||||||
|
#include <TVector3.h>
|
||||||
|
#include <TRandom.h>
|
||||||
|
|
||||||
|
struct PWHitInfo
|
||||||
|
{
|
||||||
|
std::pair<short, short> nearestWire; // anode, cathode
|
||||||
|
std::pair<double, double> nearestDist; // anode, cathode
|
||||||
|
|
||||||
|
std::pair<short, short> nextNearestWire; // anode, cathode
|
||||||
|
std::pair<double, double> nextNearestDist; // anode, cathode
|
||||||
|
|
||||||
|
void Clear()
|
||||||
|
{
|
||||||
|
nearestWire.first = -1;
|
||||||
|
nearestWire.second = -1;
|
||||||
|
nearestDist.first = 999999999;
|
||||||
|
nearestDist.second = 999999999;
|
||||||
|
nextNearestWire.first = -1;
|
||||||
|
nextNearestWire.second = -1;
|
||||||
|
nextNearestDist.first = 999999999;
|
||||||
|
nextNearestDist.second = 999999999;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Coord
|
||||||
|
{
|
||||||
|
float x, y, z;
|
||||||
|
Coord() : x(0), y(0), z(0) {}
|
||||||
|
Coord(const TVector3 &vec)
|
||||||
|
{
|
||||||
|
x = vec.X(); // TVector3's X() returns the x-coordinate
|
||||||
|
y = vec.Y(); // TVector3's Y() returns the y-coordinate
|
||||||
|
z = vec.Z(); // TVector3's Z() returns the z-coordinate
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//! ########################################################
|
||||||
|
class PW
|
||||||
|
{ // proportional wire
|
||||||
|
public:
|
||||||
|
PW() { ClearHitInfo(); };
|
||||||
|
~PW() {};
|
||||||
|
|
||||||
|
PWHitInfo GetHitInfo() const { return hitInfo; }
|
||||||
|
std::pair<short, short> GetNearestID() const { return hitInfo.nearestWire; }
|
||||||
|
std::pair<double, double> GetNearestDistance() const { return hitInfo.nearestDist; }
|
||||||
|
std::pair<short, short> Get2ndNearestID() const { return hitInfo.nextNearestWire; }
|
||||||
|
std::pair<double, double> Get2ndNearestDistance() const { return hitInfo.nextNearestDist; }
|
||||||
|
|
||||||
|
std::vector<std::pair<TVector3, TVector3>> An; // the anode wire position vector in space
|
||||||
|
std::vector<std::pair<TVector3, TVector3>> Ca; // the cathode wire position vector in space
|
||||||
|
|
||||||
|
TVector3 GetTrackPos() const { return trackPos; }
|
||||||
|
TVector3 GetTrackVec() const { return trackVec; }
|
||||||
|
double GetTrackTheta() const { return trackVec.Theta(); }
|
||||||
|
double GetTrackPhi() const { return trackVec.Phi(); }
|
||||||
|
double GetZ0();
|
||||||
|
|
||||||
|
inline std::tuple<std::pair<TVector3, TVector3>, double, double, double> GetPseudoWire(const std::vector<std::tuple<int,double,double>>& cluster, std::string type);
|
||||||
|
|
||||||
|
inline std::tuple<TVector3,double,double,double,double,double,double,double>
|
||||||
|
FindCrossoverProperties(const std::vector<std::tuple<int,double,double>>& a_cluster, const std::vector<std::tuple<int,double,double>>& c_cluster);
|
||||||
|
|
||||||
|
inline std::vector<std::vector<std::tuple<int,double,double>>>
|
||||||
|
Make_Clusters(std::unordered_map<int,std::tuple<int,double,double>> wireEvents);
|
||||||
|
|
||||||
|
int GetNumWire() const { return nWire; }
|
||||||
|
double GetDeltaAngle() const { return dAngle; }
|
||||||
|
double GetAnodeLength() const { return anodeLength; }
|
||||||
|
double GetCathodeLength() const { return cathodeLength; }
|
||||||
|
TVector3 GetAnodeDn(short id) const { return An[id].first; }
|
||||||
|
TVector3 GetAnodeUp(short id) const { return An[id].second; }
|
||||||
|
TVector3 GetCathodeDn(short id) const { return Ca[id].first; }
|
||||||
|
TVector3 GetCathodeUp(short id) const { return Ca[id].second; }
|
||||||
|
|
||||||
|
TVector3 GetAnodneMid(short id) const { return (An[id].first + An[id].second) * 0.5; }
|
||||||
|
double GetAnodeTheta(short id) const { return (An[id].first - An[id].second).Theta(); }
|
||||||
|
double GetAnodePhi(short id) const { return (An[id].first - An[id].second).Phi(); }
|
||||||
|
|
||||||
|
TVector3 GetCathodneMid(short id) const { return (Ca[id].first + Ca[id].second) * 0.5; }
|
||||||
|
double GetCathodeTheta(short id) const { return (Ca[id].first - Ca[id].second).Theta(); }
|
||||||
|
double GetCathodePhi(short id) const { return (Ca[id].first - Ca[id].second).Phi(); }
|
||||||
|
|
||||||
|
void ClearHitInfo();
|
||||||
|
void ConstructGeo();
|
||||||
|
void FindWireID(TVector3 pos, TVector3 direction, bool verbose = false);
|
||||||
|
void CalTrack(TVector3 sx3Pos, int anodeID, int cathodeID, bool verbose = false);
|
||||||
|
void CalTrack2(TVector3 sx3Pos, TVector3 anodeInt, bool verbose = false);
|
||||||
|
|
||||||
|
void Print()
|
||||||
|
{
|
||||||
|
printf(" The nearest | Anode: %2d(%5.2f) Cathode: %2d(%5.2f)\n", hitInfo.nearestWire.first,
|
||||||
|
hitInfo.nearestDist.first,
|
||||||
|
hitInfo.nearestWire.second,
|
||||||
|
hitInfo.nearestDist.second);
|
||||||
|
|
||||||
|
printf(" The 2nd nearest | Anode: %2d(%5.2f) Cathode: %2d(%5.2f)\n", hitInfo.nextNearestWire.first,
|
||||||
|
hitInfo.nextNearestDist.first,
|
||||||
|
hitInfo.nextNearestWire.second,
|
||||||
|
hitInfo.nextNearestDist.second);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
PWHitInfo hitInfo;
|
||||||
|
|
||||||
|
TVector3 trackPos;
|
||||||
|
TVector3 trackVec;
|
||||||
|
|
||||||
|
const int nWire = 24;
|
||||||
|
const int wireShift = 3;
|
||||||
|
//const float zLen = 380; // mm
|
||||||
|
const float zLen = 348.6; // mm
|
||||||
|
const float radiusA = 37;
|
||||||
|
const float radiusC = 43;
|
||||||
|
|
||||||
|
double dAngle;
|
||||||
|
double anodeLength;
|
||||||
|
double cathodeLength;
|
||||||
|
|
||||||
|
// std::vector<std::pair<TVector3, TVector3>> An; // the anode wire position vector in space
|
||||||
|
// std::vector<std::pair<TVector3, TVector3>> Ca; // the cathode wire position vector in space
|
||||||
|
|
||||||
|
double Distance(TVector3 a1, TVector3 a2, TVector3 b1, TVector3 b2)
|
||||||
|
{
|
||||||
|
TVector3 na = a1 - a2;
|
||||||
|
TVector3 nb = b1 - b2;
|
||||||
|
TVector3 nd = (na.Cross(nb)).Unit();
|
||||||
|
return TMath::Abs(nd.Dot(a1 - b2));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
inline void PW::ClearHitInfo()
|
||||||
|
{
|
||||||
|
hitInfo.Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void PW::ConstructGeo()
|
||||||
|
{
|
||||||
|
|
||||||
|
An.clear();
|
||||||
|
Ca.clear();
|
||||||
|
|
||||||
|
std::pair<TVector3, TVector3> p1; // anode
|
||||||
|
std::pair<TVector3, TVector3> q1; // cathode
|
||||||
|
|
||||||
|
double k = TMath::TwoPi()/24.; //48 solder thru holes, wires in every other one
|
||||||
|
double offset_a1 = -6*k-3*k;
|
||||||
|
double offset_c1 = -3*k - TMath::TwoPi()/48; //correct for a half-turn
|
||||||
|
double offset_a2 = offset_a1+3*k;
|
||||||
|
double offset_c2 = offset_c1-3*k;
|
||||||
|
|
||||||
|
for (int i = 0; i < nWire; i++)
|
||||||
|
{
|
||||||
|
// Anode rotate right-hand coming in towards +z riding with the beam. In this frame, +x is to the right, and +y down
|
||||||
|
//updated Feb 2026, Sudarsan B. Photographs indicate that anode wires twist right handed, as one moves from -z to +z with the convention above
|
||||||
|
//'First' is -z locus, 'second' is +z locus
|
||||||
|
p1.first.SetXYZ(radiusA * TMath::Cos(-k*i + offset_a1),
|
||||||
|
radiusA * TMath::Sin(-k*i + offset_a1),
|
||||||
|
-zLen / 2);
|
||||||
|
p1.second.SetXYZ(radiusA * TMath::Cos(-k*i + offset_a2),
|
||||||
|
radiusA * TMath::Sin(-k*i + offset_a2),
|
||||||
|
+zLen / 2);
|
||||||
|
|
||||||
|
// Cathodes rotate left-hand, under the same system. k is positive
|
||||||
|
q1.first.SetXYZ(radiusC * TMath::Cos(k*i + offset_c1),
|
||||||
|
radiusC * TMath::Sin(k*i + offset_c1),
|
||||||
|
-zLen / 2);
|
||||||
|
q1.second.SetXYZ(radiusC * TMath::Cos(k*i + offset_c2),
|
||||||
|
radiusC * TMath::Sin(k*i + offset_c2),
|
||||||
|
zLen / 2);
|
||||||
|
An.push_back(p1);
|
||||||
|
Ca.push_back(q1);
|
||||||
|
}
|
||||||
|
|
||||||
|
dAngle = wireShift * TMath::TwoPi() / nWire;
|
||||||
|
anodeLength = TMath::Sqrt(zLen * zLen + TMath::Power(2 * radiusA * TMath::Sin(dAngle / 2), 2));
|
||||||
|
cathodeLength = TMath::Sqrt(zLen * zLen + TMath::Power(2 * radiusC * TMath::Sin(dAngle / 2), 2)); //chord length subtending an angle alpha is 2rsin(alpha/2)
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::vector<std::vector<std::tuple<int,double,double>>>
|
||||||
|
PW::Make_Clusters(std::unordered_map<int,std::tuple<int,double,double>> wireEvents) {
|
||||||
|
std::vector<std::vector<std::tuple<int,double,double>>> wireClusters;
|
||||||
|
std::vector<std::tuple<int,double,double>> wireCluster;
|
||||||
|
//TODO: Write a macro once, call it twice
|
||||||
|
int wirecount=0;
|
||||||
|
while(wirecount < 24) {
|
||||||
|
if(wireEvents.find(wirecount)==wireEvents.end()) {
|
||||||
|
wirecount++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
wireCluster.clear();
|
||||||
|
int ctr2=wirecount;
|
||||||
|
do {
|
||||||
|
wireCluster.emplace_back(wireEvents[ctr2]);
|
||||||
|
ctr2+=1;
|
||||||
|
if(ctr2==24 || ctr2-wirecount == 7) break; //loose logic, needs to be looked at.
|
||||||
|
} while(wireEvents.find(ctr2)!=wireEvents.end());
|
||||||
|
wireClusters.push_back(std::move(wireCluster));
|
||||||
|
wirecount = ctr2; //we already dealt with wires until the last value of ctr2
|
||||||
|
}
|
||||||
|
|
||||||
|
if(wireClusters.size() > 1) { //Deal with wraparound if required
|
||||||
|
auto first_cluster = wireClusters.front(); //front and back provide references to the elements themselves. less copy, can modify etc
|
||||||
|
auto last_cluster = wireClusters.back();
|
||||||
|
if(std::get<0>(last_cluster.back())==23 && std::get<0>(first_cluster.front())==0) {
|
||||||
|
last_cluster.insert(last_cluster.end(),first_cluster.begin(),first_cluster.end());
|
||||||
|
}
|
||||||
|
wireClusters.erase(wireClusters.begin()); //canonically, erase() needs an iterator, hence begin() not front()
|
||||||
|
//TODO: Can also deal with 'gaps' of missing wires similarly. end of one segment and beginning of another segment will be separated by missing wire --> combine the two
|
||||||
|
//TODO: Also needs some development regarding the time-correlation. Don't put wires in the same cluster if they aren't time coincident
|
||||||
|
}
|
||||||
|
return wireClusters;
|
||||||
|
|
||||||
|
/*if(aClusters.size()>1 || cClusters.size() > 1) {
|
||||||
|
std::cout << " ============== " << std::endl;
|
||||||
|
}
|
||||||
|
if(aClusters.size()>1 && cClusters.size() >=1) {
|
||||||
|
std::cout << aClusters.size() << " new anode clusters ----> " << std::endl;
|
||||||
|
int cc=1;
|
||||||
|
for(auto ac : aClusters) {
|
||||||
|
std::cout << " Cluster " << cc << std::endl;
|
||||||
|
double first_ts = std::get<2>(ac.at(0));
|
||||||
|
for(auto item : ac) {
|
||||||
|
std::cout << " \t" << std::get<0>(item) << " " << std::get<1>(item) << " " << std::get<2>(item)-first_ts << std::endl;
|
||||||
|
}
|
||||||
|
std::cout << " ------" << std::endl;
|
||||||
|
cc++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(cClusters.size()>=1 ) {
|
||||||
|
std::cout << cClusters.size() << " new cathode clusters ----> " << std::endl;
|
||||||
|
int cc=1;
|
||||||
|
for(auto ac : cClusters) {
|
||||||
|
std::cout << " Cluster " << cc << std::endl;
|
||||||
|
double first_ts = std::get<2>(ac.at(0));
|
||||||
|
for(auto item : ac) {
|
||||||
|
std::cout << " \t" << std::get<0>(item) << " " << std::get<1>(item) << " " << std::get<2>(item)-first_ts << std::endl;
|
||||||
|
}
|
||||||
|
std::cout << " ------" << std::endl;
|
||||||
|
cc++;
|
||||||
|
}
|
||||||
|
} */
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::tuple<std::pair<TVector3, TVector3>, double, double, double>
|
||||||
|
PW::GetPseudoWire(const std::vector<std::tuple<int,double,double>>& cluster, std::string type) {
|
||||||
|
std::pair<TVector3,TVector3> avgvec = std::pair(TVector3(0,0,0),TVector3(0,0,0));
|
||||||
|
double sumEnergy = 0;
|
||||||
|
double maxEnergy = 0;
|
||||||
|
double tsMaxEnergy = 0;
|
||||||
|
if(type=="ANODE") {
|
||||||
|
//if(cluster.size()>1) std::cout << " -------anodes" << std::endl;
|
||||||
|
for( auto wire : cluster) {
|
||||||
|
avgvec.first += std::get<1>(wire)*TVector3(An.at(std::get<0>(wire)).first.X(), An.at(std::get<0>(wire)).first.Y(), 0) ;
|
||||||
|
avgvec.second += std::get<1>(wire)*TVector3(An.at(std::get<0>(wire)).second.X(), An.at(std::get<0>(wire)).second.Y(), 0);
|
||||||
|
sumEnergy += std::get<1>(wire);
|
||||||
|
if(std::get<1>(wire) > maxEnergy) {
|
||||||
|
maxEnergy = std::get<1>(wire);
|
||||||
|
tsMaxEnergy = std::get<2>(wire);
|
||||||
|
}
|
||||||
|
/*if(cluster.size()>1) {
|
||||||
|
std::cout << "\t\t ch:" << std::get<0>(wire) << " " << std::get<1>(wire) << " " << std::get<2>(wire) << std::endl;
|
||||||
|
std::cout << "\t\t w1(r,phi,z):" << An.at(std::get<0>(wire)).first.Perp() << " " << An.at(std::get<0>(wire)).first.Phi()*180/M_PI << " " << An.at(std::get<0>(wire)).first.Z() << std::endl;
|
||||||
|
std::cout << "\t\t w2(r,phi,z):" << An.at(std::get<0>(wire)).second.Perp() << " " << An.at(std::get<0>(wire)).second.Phi()*180/M_PI << " " << An.at(std::get<0>(wire)).second.Z() << std::endl;
|
||||||
|
}*/
|
||||||
|
}
|
||||||
|
avgvec.first = avgvec.first*(1.0/sumEnergy);
|
||||||
|
avgvec.second = avgvec.second*(1.0/sumEnergy);
|
||||||
|
double phi1 = avgvec.first.Phi();
|
||||||
|
double phi2 = avgvec.second.Phi();
|
||||||
|
avgvec.first.SetXYZ(radiusA*TMath::Cos(phi1), radiusA*TMath::Sin(phi1), -zLen/2);
|
||||||
|
avgvec.second.SetXYZ(radiusA*TMath::Cos(phi2), radiusA*TMath::Sin(phi2), zLen/2);
|
||||||
|
/*if(cluster.size()>1) {
|
||||||
|
std::cout << "\t\t avg1(r,phi,z):" << avgvec.first.Perp() << " " << avgvec.first.Phi()*180/M_PI << " " << avgvec.first.Z() << std::endl;
|
||||||
|
std::cout << "\t\t avg2(r,phi,z):" << avgvec.second.Perp() << " " << avgvec.second.Phi()*180/M_PI << " " << avgvec.second.Z() << std::endl;
|
||||||
|
}*/
|
||||||
|
} else if(type =="CATHODE") {
|
||||||
|
for( auto wire : cluster) {
|
||||||
|
avgvec.first += std::get<1>(wire)*TVector3(Ca.at(std::get<0>(wire)).first.X(), Ca.at(std::get<0>(wire)).first.Y(), 0) ;
|
||||||
|
avgvec.second += std::get<1>(wire)*TVector3(Ca.at(std::get<0>(wire)).second.X(), Ca.at(std::get<0>(wire)).second.Y(), 0);
|
||||||
|
sumEnergy += std::get<1>(wire);
|
||||||
|
if(std::get<1>(wire) > maxEnergy) {
|
||||||
|
maxEnergy = std::get<1>(wire);
|
||||||
|
tsMaxEnergy = std::get<2>(wire);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
avgvec.first = avgvec.first*(1.0/sumEnergy);
|
||||||
|
avgvec.second = avgvec.second*(1.0/sumEnergy);
|
||||||
|
double phi1 = avgvec.first.Phi();
|
||||||
|
double phi2 = avgvec.second.Phi();
|
||||||
|
avgvec.first.SetXYZ(radiusC*TMath::Cos(phi1), radiusC*TMath::Sin(phi1), -zLen/2);
|
||||||
|
avgvec.second.SetXYZ(radiusC*TMath::Cos(phi2), radiusC*TMath::Sin(phi2), zLen/2);
|
||||||
|
}
|
||||||
|
return std::tuple(avgvec, sumEnergy, maxEnergy, tsMaxEnergy);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::tuple<TVector3,double,double,double,double,double,double,double> PW::FindCrossoverProperties(const std::vector<std::tuple<int,double,double>>& a_cluster,
|
||||||
|
const std::vector<std::tuple<int,double,double>>& c_cluster) {
|
||||||
|
//std::pair<TVector3, TVector3> apwire = GetPseudoWire(a_cluster,"ANODE",anodeSumE);
|
||||||
|
//std::pair<TVector3, TVector3> cpwire = GetPseudoWire(c_cluster,"CATHODE",cathodeSumE);
|
||||||
|
auto [apwire, apSumE, apMaxE, apTSMaxE] = GetPseudoWire(a_cluster,"ANODE");
|
||||||
|
auto [cpwire, cpSumE, cpMaxE, cpTSMaxE] = GetPseudoWire(c_cluster,"CATHODE");
|
||||||
|
|
||||||
|
TVector3 crossover;
|
||||||
|
crossover.Clear();
|
||||||
|
TVector3 a, c, diff;
|
||||||
|
double a2, ac, c2, adiff, cdiff, denom, alpha=0;
|
||||||
|
|
||||||
|
if(apSumE && cpSumE) {
|
||||||
|
a = apwire.first - apwire.second;
|
||||||
|
c = cpwire.first - cpwire.second;
|
||||||
|
diff = apwire.first - cpwire.first;
|
||||||
|
a2 = a.Dot(a);
|
||||||
|
c2 = c.Dot(c);
|
||||||
|
ac = a.Dot(c);
|
||||||
|
adiff = a.Dot(diff);
|
||||||
|
cdiff = c.Dot(diff);
|
||||||
|
denom = a2 * c2 - ac * ac;
|
||||||
|
alpha = (ac * cdiff - c2 * adiff) / denom;
|
||||||
|
crossover = apwire.first + alpha*a;
|
||||||
|
if(crossover.z() < -190 || crossover.Z() > 190 ) {
|
||||||
|
alpha = 9999999;
|
||||||
|
apSumE=-1; cpSumE=-1;
|
||||||
|
apMaxE=-1; cpMaxE=-1;
|
||||||
|
apTSMaxE=-1; cpTSMaxE=-1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//std::cout << apSumE << " " << cpSumE << " " << " " << crossover.Perp() << std::endl;
|
||||||
|
return std::tuple(crossover,alpha,apSumE,cpSumE,apMaxE,cpMaxE,apTSMaxE,cpTSMaxE);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void PW::FindWireID(TVector3 pos, TVector3 direction, bool verbose)
|
||||||
|
{
|
||||||
|
|
||||||
|
hitInfo.Clear();
|
||||||
|
double phi = direction.Phi();
|
||||||
|
|
||||||
|
for (int i = 0; i < nWire; i++)
|
||||||
|
{
|
||||||
|
|
||||||
|
double disA = 99999999;
|
||||||
|
double phiS = An[i].first.Phi() - TMath::PiOver4();
|
||||||
|
double phiL = An[i].second.Phi() + TMath::PiOver4();
|
||||||
|
// printf("A%2d: %f %f | %f\n", i, phiS * TMath::RadToDeg(), phiL * TMath::RadToDeg(), phi * TMath::RadToDeg());
|
||||||
|
if (phi > 0 && phiS > phiL)
|
||||||
|
phiL = phiL + TMath::TwoPi();
|
||||||
|
if (phi < 0 && phiS > phiL)
|
||||||
|
phiS = phiS - TMath::TwoPi();
|
||||||
|
|
||||||
|
if (phiS < phi && phi < phiL)
|
||||||
|
{
|
||||||
|
disA = Distance(pos, pos + direction, An[i].first, An[i].second);
|
||||||
|
if (disA < hitInfo.nearestDist.first)
|
||||||
|
{
|
||||||
|
hitInfo.nearestDist.first = disA;
|
||||||
|
hitInfo.nearestWire.first = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
double disC = 99999999;
|
||||||
|
phiS = Ca[i].second.Phi() - TMath::PiOver4();
|
||||||
|
phiL = Ca[i].first.Phi() + TMath::PiOver4();
|
||||||
|
// printf("C%2d: %f %f\n", i, phiS * TMath::RadToDeg(), phiL * TMath::RadToDeg());
|
||||||
|
if (phi > 0 && phiS > phiL)
|
||||||
|
phiL = phiL + TMath::TwoPi();
|
||||||
|
if (phi < 0 && phiS > phiL)
|
||||||
|
phiS = phiS - TMath::TwoPi();
|
||||||
|
|
||||||
|
if (phiS < phi && phi < phiL)
|
||||||
|
{
|
||||||
|
disC = Distance(pos, pos + direction, Ca[i].first, Ca[i].second);
|
||||||
|
if (disC < hitInfo.nearestDist.second)
|
||||||
|
{
|
||||||
|
hitInfo.nearestDist.second = disC;
|
||||||
|
hitInfo.nearestWire.second = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (verbose)
|
||||||
|
printf(" %2d | %8.2f, %8.2f\n", i, disA, disC);
|
||||||
|
}
|
||||||
|
|
||||||
|
//==== find the 2nd nearest wire
|
||||||
|
short anode1 = hitInfo.nearestWire.first;
|
||||||
|
short aaa1 = anode1 - 1;
|
||||||
|
if (aaa1 < 0)
|
||||||
|
aaa1 += nWire;
|
||||||
|
short aaa2 = (anode1 + 1) % nWire;
|
||||||
|
|
||||||
|
double haha1 = Distance(pos, pos + direction, An[aaa1].first, An[aaa1].second);
|
||||||
|
double haha2 = Distance(pos, pos + direction, An[aaa2].first, An[aaa2].second);
|
||||||
|
if (haha1 < haha2)
|
||||||
|
{
|
||||||
|
hitInfo.nextNearestWire.first = aaa1;
|
||||||
|
hitInfo.nextNearestDist.first = haha1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hitInfo.nextNearestWire.first = aaa2;
|
||||||
|
hitInfo.nextNearestDist.first = haha2;
|
||||||
|
}
|
||||||
|
|
||||||
|
short cathode1 = hitInfo.nearestWire.second;
|
||||||
|
short ccc1 = cathode1 - 1;
|
||||||
|
if (ccc1 < 0)
|
||||||
|
ccc1 += nWire;
|
||||||
|
short ccc2 = (cathode1 + 1) % nWire;
|
||||||
|
|
||||||
|
haha1 = Distance(pos, pos + direction, Ca[ccc1].first, Ca[ccc1].second);
|
||||||
|
haha2 = Distance(pos, pos + direction, Ca[ccc2].first, Ca[ccc2].second);
|
||||||
|
if (haha1 < haha2)
|
||||||
|
{
|
||||||
|
hitInfo.nextNearestWire.second = ccc1;
|
||||||
|
hitInfo.nextNearestDist.second = haha1;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
hitInfo.nextNearestWire.second = ccc2;
|
||||||
|
hitInfo.nextNearestDist.second = haha2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (verbose)
|
||||||
|
Print();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void PW::CalTrack(TVector3 sx3Pos, int anodeID, int cathodeID, bool verbose)
|
||||||
|
{
|
||||||
|
|
||||||
|
trackPos = sx3Pos;
|
||||||
|
|
||||||
|
TVector3 n1 = (An[anodeID].first - An[anodeID].second).Cross((sx3Pos - An[anodeID].second)).Unit();
|
||||||
|
TVector3 n2 = (Ca[cathodeID].first - Ca[cathodeID].second).Cross((sx3Pos - Ca[cathodeID].second)).Unit();
|
||||||
|
|
||||||
|
// if the handiness of anode and cathode revered, it should be n2 cross n1
|
||||||
|
trackVec = (n2.Cross(n1)).Unit();
|
||||||
|
|
||||||
|
if (verbose)
|
||||||
|
printf("Theta, Phi = %f, %f \n", trackVec.Theta() * TMath::RadToDeg(), trackVec.Phi() * TMath::RadToDeg());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void PW::CalTrack2(TVector3 siPos, TVector3 anodeInt, bool verbose)
|
||||||
|
{
|
||||||
|
|
||||||
|
double mx, my;
|
||||||
|
double z;
|
||||||
|
mx = siPos.X() / (siPos.X() - anodeInt.X());
|
||||||
|
my = siPos.Y() / (siPos.Y() - anodeInt.Y());
|
||||||
|
z=siPos.Z() + mx * (anodeInt.Z() - siPos.Z());
|
||||||
|
// if (mx == my)
|
||||||
|
{
|
||||||
|
trackVec=TVector3(0,0,z);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (verbose)
|
||||||
|
printf("X slope = %f and Y slope = %f \n", mx, my);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*inline TVector3 PW::CalTrack3(TVector3 siPos, TVector3 anodeInt, bool verbose)
|
||||||
|
{
|
||||||
|
|
||||||
|
TVector3 v = anodeInt-siPos;
|
||||||
|
double t_minimum = -1.0*(siPos.X()*v.X()+siPos.Y()*v.Y())/(v.X()*v.X()+v.Y()*v.Y());
|
||||||
|
TVector3 vector_closest_to_z = siPos + t_minimum*v;
|
||||||
|
|
||||||
|
return vector_closest_to_z;
|
||||||
|
if (verbose)
|
||||||
|
printf("X slope = %f and Y slope = %f \n", mx, my);
|
||||||
|
}*/
|
||||||
|
|
||||||
|
inline double PW::GetZ0()
|
||||||
|
{
|
||||||
|
|
||||||
|
double x = trackPos.X();
|
||||||
|
double y = trackPos.Y();
|
||||||
|
double rho = TMath::Sqrt(x * x + y * y);
|
||||||
|
double theta = trackVec.Theta();
|
||||||
|
|
||||||
|
return trackVec.Z();
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
416
Armory/HistPlotter.h
Normal file
416
Armory/HistPlotter.h
Normal file
|
|
@ -0,0 +1,416 @@
|
||||||
|
#ifndef HISTPLOTTER_H
|
||||||
|
#define HISTPLOTTER_H
|
||||||
|
#include <TCanvas.h>
|
||||||
|
#include <TROOT.h>
|
||||||
|
#include <TSystem.h>
|
||||||
|
#include <TStyle.h>
|
||||||
|
#include <iostream>
|
||||||
|
#include <TFile.h>
|
||||||
|
#include <TMemFile.h>
|
||||||
|
#include <TH1.h>
|
||||||
|
#include <TH2.h>
|
||||||
|
#include <TCutG.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <utility>
|
||||||
|
#include <fstream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <unordered_map>
|
||||||
|
#include <set>
|
||||||
|
#include <TGraphErrors.h>
|
||||||
|
|
||||||
|
class HistPlotter {
|
||||||
|
private:
|
||||||
|
long long barrier_count, barrier_limit; //meant to keep track of how often to call FillN() on histograms
|
||||||
|
enum {TFILE, TMEMFILE} filetype;
|
||||||
|
std::unordered_map<std::string,TObject*> oMap; //!< Maps std::string to all TH1, TH2 objects in the class
|
||||||
|
std::unordered_map<std::string,TObject*> cutsMap; //!< Maps std::string to TCutG objects held by the class
|
||||||
|
std::set<std::string> folderList; //!< List of all folder names used to nest objects
|
||||||
|
std::unordered_map<TObject*,std::string> foldersForObjects; //!< Map that returns the folder corresponding to the object whose pointer is specified
|
||||||
|
TFile *ofile=nullptr; //!< TFile pointer for the output file
|
||||||
|
TMemFile *omfile=nullptr; //!< TFile pointer for the output memfile
|
||||||
|
|
||||||
|
//Caches to permit FillN() calls
|
||||||
|
std::unordered_map<std::string, std::vector<double>> onedimcache;
|
||||||
|
std::unordered_map<std::string, std::pair<std::vector<double>, std::vector<double>>> twodimcache;
|
||||||
|
inline void FillN_All_Histograms();
|
||||||
|
public:
|
||||||
|
HistPlotter(std::string outfile, std::string type);
|
||||||
|
inline void FlushToDisk(int integral); //!< Writes all objects to file before closing, nesting objects in folders as is found necessary
|
||||||
|
inline void PrintObjects(); //!< Dump objects to std::cout for inspection
|
||||||
|
inline void ReadCuts(std::string);
|
||||||
|
inline TCutG* FindCut(std::string cut) {
|
||||||
|
return static_cast<TCutG*>(cutsMap.at(cut));
|
||||||
|
}
|
||||||
|
inline void set_barrier_limit(long long limit) { barrier_limit = limit; }
|
||||||
|
inline void barrier_increment() {
|
||||||
|
barrier_count++;
|
||||||
|
if(barrier_count == barrier_limit) {
|
||||||
|
FillN_All_Histograms();
|
||||||
|
barrier_count=0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*! \fn void FindCut()
|
||||||
|
\brief
|
||||||
|
- Searches for a cut by name 'cut' in the internal list of cuts 'cutsMap'. Ugly fails (via unresolved at()) if such a cut isn't found.
|
||||||
|
\param filename - name of the plainxtext file containing the cut file locations and identifiers
|
||||||
|
\return Pointer to the TCutG object that matches the name. Very useful to use this as plotter.FindCut("protonbarrelpid")->IsInside(deltaE, E) for instance.
|
||||||
|
*/
|
||||||
|
|
||||||
|
inline void SetNewTitle(std::string name, std::string title) {
|
||||||
|
auto result = oMap.find(name); //result is an iterator
|
||||||
|
if(result==oMap.end()) return; //no warnings, could be changed in future
|
||||||
|
else
|
||||||
|
static_cast<TNamed*>(oMap.at(name))->SetTitle(title.c_str()); // set new title
|
||||||
|
}
|
||||||
|
|
||||||
|
//Smart functions that create a new histogram if it doesn't exist.
|
||||||
|
inline void FillGraph(const std::string &name, float valuex, float valuey, float errx=0, float erry=0);
|
||||||
|
inline void Fill1D(const std::string& name,int nbinsx, float xlow, float xhigh, float value);
|
||||||
|
inline void Fill2D(const std::string& name,int nbinsx, float xlow, float xhigh
|
||||||
|
,int nbinsy, float ylow, float yhigh, float valuex, float valuey);
|
||||||
|
inline void Fill1D(const std::string& name,int nbinsx, float xlow, float xhigh, float value, const std::string& folder);
|
||||||
|
inline void Fill2D(const std::string& name,int nbinsx, float xlow, float xhigh
|
||||||
|
,int nbinsy, float ylow, float yhigh, float valuex, float valuey, const std::string& folder);
|
||||||
|
//TObject* findObject(std::string key);
|
||||||
|
};
|
||||||
|
|
||||||
|
HistPlotter::HistPlotter(std::string outfile, std::string type="") {
|
||||||
|
/*!
|
||||||
|
\brief Constructor. Opens a TFile instance with the specified filename
|
||||||
|
\param outfile : std::string that holds the desired output ROOT filename
|
||||||
|
\return None
|
||||||
|
*/
|
||||||
|
if(type=="" || type == "TFILE") {
|
||||||
|
ofile = new TFile(outfile.c_str(),"recreate");
|
||||||
|
filetype = TFILE;
|
||||||
|
} else if(type =="TMEMFILE") {
|
||||||
|
omfile = new TMemFile(outfile.c_str(),"recreate");
|
||||||
|
filetype=TMEMFILE;
|
||||||
|
} else {
|
||||||
|
std::cout << "Unknown type "<< type << " specified for HistPlotter (use \"TFILE\" or \"TMEMFILE\"), using default \"TFILE\" " << std::endl;
|
||||||
|
ofile = new TFile(outfile.c_str(),"recreate");
|
||||||
|
filetype = TFILE;
|
||||||
|
}
|
||||||
|
barrier_count=0;
|
||||||
|
barrier_limit=1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HistPlotter::FillN_All_Histograms() {
|
||||||
|
for(auto it=oMap.begin(); it!=oMap.end(); it++ ) {
|
||||||
|
//it->first is std::string 'name', it->second is the TObject
|
||||||
|
if(it->second->InheritsFrom("TH1F")) {
|
||||||
|
//FillN(size, array-of-doubles, array-of-weights); //we set array-of-weights to (1,1,1,.. (size)
|
||||||
|
static_cast<TH1F*>(it->second)->FillN(onedimcache[it->first].size(), //size
|
||||||
|
onedimcache[it->first].data(), //array
|
||||||
|
std::vector<double>(onedimcache[it->first].size(),1.0).data()); //weight of ones
|
||||||
|
onedimcache[it->first].clear();
|
||||||
|
} else if(it->second->InheritsFrom("TH2F")) {
|
||||||
|
//FillN(size, array-of-doubles, array-of-weights); //we set array-of-weights to (1,1,1,.. (size))
|
||||||
|
static_cast<TH2F*>(it->second)->FillN(twodimcache[it->first].first.size(), //size
|
||||||
|
twodimcache[it->first].first.data(), //x array
|
||||||
|
twodimcache[it->first].second.data(), //y array
|
||||||
|
std::vector<double>(twodimcache[it->first].first.size(),1.0).data()); //weight of ones
|
||||||
|
twodimcache[it->first].first.clear();
|
||||||
|
twodimcache[it->first].second.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::cout << "." << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HistPlotter::FlushToDisk(int min_integral=0) {
|
||||||
|
/*! \fn void FlushToDisk()
|
||||||
|
\brief Function that can be used at any point to exit smoothly by saving all ROOT objects in memory
|
||||||
|
to the output file before closing it. Obeys the binding of histograms to separate folders, if so specified.
|
||||||
|
\return No return -- void
|
||||||
|
*/
|
||||||
|
if(filetype==TMEMFILE && omfile) {
|
||||||
|
std::cout << "Not flushing a TMemfile .. exiting .." << std::endl;
|
||||||
|
delete omfile;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(ofile->IsZombie() || !ofile) {
|
||||||
|
std::cerr << "Output file is zombie, finishing up without writing to disk!" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
FillN_All_Histograms();
|
||||||
|
for(auto it=oMap.begin(); it!=oMap.end(); it++ ) {
|
||||||
|
//omap maps: name(first) to object address(second).
|
||||||
|
// foldersForObjects maps: object address(first) to foldername(second)
|
||||||
|
auto result = foldersForObjects.find(it->second); //returns <TObject* histogram,std::string foldername> pair if found
|
||||||
|
if(result!=foldersForObjects.end()) { //we try to create folder if needed and cd to it
|
||||||
|
ofile->mkdir(result->second.c_str(),"",kTRUE); // args: name, title, returnExistingDirectory
|
||||||
|
ofile->cd(result->second.c_str());
|
||||||
|
} else {
|
||||||
|
ofile->cd(); //toplevel for all default histograms. Default setting
|
||||||
|
}
|
||||||
|
if(((TH1F*)it->second)->Integral()>min_integral)
|
||||||
|
it->second->Write();
|
||||||
|
}
|
||||||
|
|
||||||
|
//Create a directory for all cuts, and save all cuts in them
|
||||||
|
ofile->mkdir("gCUTS","",kTRUE);
|
||||||
|
ofile->cd("gCUTS");
|
||||||
|
for(auto it=cutsMap.begin(); it!=cutsMap.end(); it++) {
|
||||||
|
(static_cast<TNamed*>(it->second))->SetName(it->first.c_str());
|
||||||
|
it->second->Write();
|
||||||
|
}
|
||||||
|
ofile->Close();
|
||||||
|
std::cout << "Wrote " << oMap.size() << " histograms to TFile " << std::string(ofile->GetName()) << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void HistPlotter::FillGraph(const std::string& name, float valuex, float valuey, float errx, float erry) {
|
||||||
|
/*! \fn void FillGraph()
|
||||||
|
\brief
|
||||||
|
- Creates a TGraphError in memory with name 'name' if it doesn't exist, and fills it with valuex, valuey
|
||||||
|
- Writes present state to disk and fails with return value -1 if the name clashes with another object that's not of type TGraph*
|
||||||
|
|
||||||
|
\param name name of the TGraph
|
||||||
|
\param valuex The xvalue
|
||||||
|
\param valuey The yvalue
|
||||||
|
\param errx The x error
|
||||||
|
\param erry The y error
|
||||||
|
\return No return void
|
||||||
|
*/
|
||||||
|
auto result = oMap.find(name);
|
||||||
|
if(result==oMap.end()) {
|
||||||
|
TGraphErrors *tempG = new TGraphErrors();
|
||||||
|
tempG->SetName(name.c_str());
|
||||||
|
oMap.insert(std::make_pair(name,static_cast<TObject*>(tempG)));
|
||||||
|
}
|
||||||
|
if(!oMap.at(name)->InheritsFrom("TGraphErrors")) {
|
||||||
|
std::cerr << "Object " << name << " refers to something other than a TGraph*, not filling it hence!" << std::endl;
|
||||||
|
std::cerr << "Abort.." << std::endl;
|
||||||
|
FlushToDisk();
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
// static_cast<TGraphErrors*>(oMap.at(name))->AddPointError(valuex,valuey,errx,erry);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HistPlotter::Fill1D(const std::string& name, int nbinsx, float xlow, float xhigh, float value) {
|
||||||
|
/*! \fn void Fill1D()
|
||||||
|
\brief
|
||||||
|
- Creates a TH1F in memory with name 'name' if it doesn't exist, and fills it with valuex, valuey
|
||||||
|
- Writes present state to disk and fails with return value -1 if the name clashes with another object that's not of type TH1*
|
||||||
|
|
||||||
|
\param name name of the TH1F histogram
|
||||||
|
\param nbinsx Number of bins in the histogram
|
||||||
|
\param xlow Lower limit on x-axis
|
||||||
|
\param xhigh Upper limit on x-axis
|
||||||
|
\param value The bin corresponding to value in (nbinsx, xlow, xhigh) is incremented by 1
|
||||||
|
\return No return void
|
||||||
|
*/
|
||||||
|
auto result = oMap.find(name); //result is an iterator
|
||||||
|
if(result==oMap.end()) {
|
||||||
|
TH1F* temp1D = new TH1F(name.c_str(), name.c_str(), nbinsx, xlow, xhigh);
|
||||||
|
oMap.insert(std::make_pair(name,static_cast<TObject*>(temp1D)));
|
||||||
|
onedimcache.insert(std::make_pair(name, std::vector<double>()));
|
||||||
|
onedimcache[name].reserve(16384);
|
||||||
|
} else if(foldersForObjects.find(oMap.at(name))!=foldersForObjects.end()) { //shouldn't have a folder associated with it
|
||||||
|
std::cerr << "Object " << name << " already registered at " << foldersForObjects[oMap[name]] << ", choose a different name for the histogram to be stored in toplevel .." << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Check if the string 'name' maps to a 1D hist. If there's any other object by this name raise issue
|
||||||
|
if(!oMap.at(name)->InheritsFrom("TH1F")) {
|
||||||
|
std::cerr << "Object " << name << " refers to something other than a TH1*, not filling it hence!" << std::endl;
|
||||||
|
std::cerr << "Abort.." << std::endl;
|
||||||
|
FlushToDisk();
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
onedimcache[name].emplace_back(value);
|
||||||
|
//static_cast<TH1F*>(oMap.at(name))->Fill(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HistPlotter::Fill1D(const std::string& name, int nbinsx, float xlow, float xhigh, float value, const std::string& foldername) {
|
||||||
|
/*! \fn void Fill1D()
|
||||||
|
\brief
|
||||||
|
- Creates a TH1F in memory with name 'name' if it doesn't exist, and fills it with valuex, valuey
|
||||||
|
- Writes present state to disk and fails with return value -1 if the name clashes with another object that's not of type TH1*
|
||||||
|
- Remembers the foldername this particular histogram maps to, if provided. If not, defaults to toplevel.
|
||||||
|
|
||||||
|
\param name name of the TH1F histogram
|
||||||
|
\param nbinsx Number of bins in the histogram
|
||||||
|
\param xlow Lower limit on x-axis
|
||||||
|
\param xhigh Upper limit on x-axis
|
||||||
|
\param value The bin corresponding to value in (nbinsx, xlow, xhigh) is incremented by 1
|
||||||
|
\param foldername Name of the folder to put this histogram into. Defaults to toplevel if left empty
|
||||||
|
\return No return -- void
|
||||||
|
*/
|
||||||
|
|
||||||
|
auto result = oMap.find(name); //result is an iterator
|
||||||
|
if(result==oMap.end()) {
|
||||||
|
TH1F* temp1D = new TH1F(name.c_str(), name.c_str(), nbinsx, xlow, xhigh);
|
||||||
|
oMap.insert(std::make_pair(name,static_cast<TObject*>(temp1D)));
|
||||||
|
onedimcache.insert(std::make_pair(name, std::vector<double>()));
|
||||||
|
onedimcache[name].reserve(16384);
|
||||||
|
if(foldername!="") {
|
||||||
|
if(folderList.find(foldername)==folderList.end()) {
|
||||||
|
folderList.insert(foldername);
|
||||||
|
}
|
||||||
|
foldersForObjects.insert(std::make_pair(static_cast<TObject*>(temp1D),foldername));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//object is present in map, but we enforce unique names
|
||||||
|
//it must already have a folder attached to it
|
||||||
|
if(foldersForObjects.find(oMap.at(name))==foldersForObjects.end()) {
|
||||||
|
std::cerr << "Object " << name << " already registered at toplevel, choose a different name for the histogram to be stored in " << foldername << " folder .." << std::endl;
|
||||||
|
} else if(foldersForObjects[oMap[name]]!=foldername) {
|
||||||
|
std::cerr << "Object " << name << " already registered at " << foldersForObjects[oMap[name]] << ", choose a different name for the histogram to be stored in " << foldername << " folder .." << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//Check if the string 'name' maps to a 1D hist. If there's any other object by this name raise issue
|
||||||
|
if(!oMap.at(name)->InheritsFrom("TH1F")) {
|
||||||
|
std::cerr << "Object " << name << " refers to something other than a TH1*, not filling it hence!" << std::endl;
|
||||||
|
std::cerr << "Abort.." << std::endl;
|
||||||
|
FlushToDisk();
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
onedimcache[name].emplace_back(value);
|
||||||
|
//static_cast<TH1F*>(oMap.at(name))->Fill(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HistPlotter::Fill2D(const std::string& name, int nbinsx, float xlow, float xhigh, int nbinsy, float ylow, float yhigh, float valuex, float valuey) {
|
||||||
|
/*! \fn void Fill2D()
|
||||||
|
\brief
|
||||||
|
- Creates a TH2F in memory with name 'name' if it doesn't exist, and fills it with valuex, valuey
|
||||||
|
- Writes present state to disk and fails with return value -1 if the name clashes with another object that's not of type TH2*
|
||||||
|
\param name name of the TH1F histogram
|
||||||
|
\param nbinsx Number of xbins in the histogram
|
||||||
|
\param xlow Lower limit on x-axis
|
||||||
|
\param xhigh Upper limit on x-axis
|
||||||
|
\param nbinsy Number of ybins in the histogram
|
||||||
|
\param ylow Lower limit on y-axis
|
||||||
|
\param yhigh Upper limit on y-axis
|
||||||
|
\param valuex
|
||||||
|
\param valuey The bin corresponding to (valuex, valuey) in (nbinsx, xlow, xhigh, ybinsx, ylow, yhigh) is incremented by 1
|
||||||
|
\return No return -- void
|
||||||
|
*/
|
||||||
|
|
||||||
|
auto result = oMap.find(name); //result is an iterator
|
||||||
|
if(result==oMap.end()) {
|
||||||
|
TH2F* temp2D = new TH2F(name.c_str(), name.c_str(), nbinsx, xlow, xhigh, nbinsy, ylow, yhigh);
|
||||||
|
oMap.insert(std::make_pair(name,static_cast<TObject*>(temp2D)));
|
||||||
|
twodimcache.insert(std::make_pair(name, std::make_pair(std::vector<double>(),std::vector<double>())));
|
||||||
|
twodimcache[name].first.reserve(16384);
|
||||||
|
twodimcache[name].second.reserve(16384);
|
||||||
|
} else if(foldersForObjects.find(oMap.at(name))!=foldersForObjects.end()) { //shouldn't have a folder associated with it
|
||||||
|
std::cerr << "Object " << name << " already registered at " << foldersForObjects[oMap[name]] << ", choose a different name for the histogram to be stored in toplevel .." << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Check if the string 'name' maps to a 1D hist. If there's any other object by this name raise issue
|
||||||
|
if(!oMap.at(name)->InheritsFrom("TH2F")) {
|
||||||
|
std::cerr << "Object " << name << " refers to something other than a TH2*, not filling it hence!" << std::endl;
|
||||||
|
std::cerr << "Abort.." << std::endl;
|
||||||
|
FlushToDisk();
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
twodimcache[name].first.emplace_back(valuex);
|
||||||
|
twodimcache[name].second.emplace_back(valuey);
|
||||||
|
//static_cast<TH2F*>(oMap.at(name))->Fill(valuex,valuey);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HistPlotter::Fill2D(const std::string& name, int nbinsx, float xlow, float xhigh, int nbinsy, float ylow, float yhigh, float valuex, float valuey, const std::string& foldername) {
|
||||||
|
/*! \fn void Fill2D()
|
||||||
|
\brief
|
||||||
|
- Creates a TH2F in memory with name 'name' if it doesn't exist, and fills it with valuex, valuey
|
||||||
|
- Writes present state to disk and fails with return value -1 if the name clashes with another object that's not of type TH2*
|
||||||
|
- Remembers the foldername this particular histogram maps to, if provided. If not defaults to toplevel
|
||||||
|
|
||||||
|
\param name name of the TH1F histogram
|
||||||
|
\param nbinsx Number of xbins in the histogram
|
||||||
|
\param xlow Lower limit on x-axis
|
||||||
|
\param xhigh Upper limit on x-axis
|
||||||
|
\param nbinsy Number of ybins in the histogram
|
||||||
|
\param ylow Lower limit on y-axis
|
||||||
|
\param yhigh Upper limit on y-axis
|
||||||
|
\param valuex
|
||||||
|
\param valuey The bin corresponding to (valuex, valuey) in (nbinsx, xlow, xhigh, ybinsx, ylow, yhigh) is incremented by 1
|
||||||
|
\param foldername Name of the folder to put this histogram into. Defaults to toplevel if left empty
|
||||||
|
\return No return -- void
|
||||||
|
*/
|
||||||
|
|
||||||
|
auto result = oMap.find(name); //result is an iterator
|
||||||
|
if(result==oMap.end()) {
|
||||||
|
TH2F* temp2D = new TH2F(name.c_str(), name.c_str(), nbinsx, xlow, xhigh, nbinsy, ylow, yhigh);
|
||||||
|
oMap.insert(std::make_pair(name,static_cast<TObject*>(temp2D)));
|
||||||
|
twodimcache.insert(std::make_pair(name, std::make_pair(std::vector<double>(),std::vector<double>())));
|
||||||
|
twodimcache[name].first.reserve(16384);
|
||||||
|
twodimcache[name].second.reserve(16384);
|
||||||
|
if(foldername!="") {
|
||||||
|
if(folderList.find(foldername)==folderList.end()) {
|
||||||
|
folderList.insert(foldername);
|
||||||
|
}
|
||||||
|
foldersForObjects.insert(std::make_pair(static_cast<TObject*>(temp2D),foldername));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
//object is present in map, but we enforce unique names
|
||||||
|
//it must already have a folder attached to it
|
||||||
|
if(foldersForObjects.find(oMap.at(name))==foldersForObjects.end()) {
|
||||||
|
std::cerr << "Object " << name << " already registered at toplevel, choose a different name for the histogram to be stored in " << foldername << " folder .." << std::endl;
|
||||||
|
} else if(foldersForObjects[oMap.at(name)]!=foldername) {
|
||||||
|
std::cerr << "Object " << name << " already registered at " << foldersForObjects[oMap[name]] << ", choose a different name for the histogram to be stored in " << foldername << " folder .." << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//Check if the string 'name' maps to a 1D hist. If there's any other object by this name raise issue
|
||||||
|
if(!oMap.at(name)->InheritsFrom("TH2F")) {
|
||||||
|
std::cerr << "Object " << name << " refers to something other than a TH2*, not filling it hence!" << std::endl;
|
||||||
|
std::cerr << "Abort.." << std::endl;
|
||||||
|
FlushToDisk();
|
||||||
|
exit(-1);
|
||||||
|
}
|
||||||
|
twodimcache[name].first.emplace_back(valuex);
|
||||||
|
twodimcache[name].second.emplace_back(valuey);
|
||||||
|
//static_cast<TH2F*>(oMap.at(name))->Fill(valuex,valuey);
|
||||||
|
}
|
||||||
|
|
||||||
|
void HistPlotter::ReadCuts(std::string filename) {
|
||||||
|
/*! \fn void ReadCuts()
|
||||||
|
\brief Reads a list of cuts from a file. The file must have the format below, two columns
|
||||||
|
- Column#1 - path to a file that contains a single TCutG object named "CUTG", the default name in ROOT.
|
||||||
|
- Column#2 - The identifier name you plan to use in the code, like 'protonbarrelpid' or something, that will be searched by FindCut()
|
||||||
|
\param filename name of the plainxtext file containing the cut file locations and identifiers
|
||||||
|
\return No return -- void
|
||||||
|
*/
|
||||||
|
|
||||||
|
std::ifstream infile;
|
||||||
|
infile.open(filename);
|
||||||
|
std::string cutfilename, cutname;
|
||||||
|
for(std::string line; std::getline(infile, line); ) {
|
||||||
|
if(line.size()!=0 && line[0]=='#')
|
||||||
|
; //don't do anything with '#' lines
|
||||||
|
else {
|
||||||
|
std::stringstream ss(line);
|
||||||
|
ss>>cutfilename>>cutname;
|
||||||
|
|
||||||
|
TFile f(cutfilename.c_str());
|
||||||
|
if(f.IsZombie()) {
|
||||||
|
std::cerr << "Cannot open cutfile " << cutfilename << " .. skipping.." << std::endl;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
TCutG *cut = (TCutG*)(f.Get("CUTG"));
|
||||||
|
cutsMap.insert(std::make_pair(cutname,static_cast<TObject*>(cut)));
|
||||||
|
f.Close();
|
||||||
|
} //else
|
||||||
|
}//for loop
|
||||||
|
infile.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
void HistPlotter::PrintObjects() {
|
||||||
|
/*
|
||||||
|
void PrintObjects()
|
||||||
|
Prints the contents of the unordered_maps oMap and cutsMap to facilitate debugging
|
||||||
|
|
||||||
|
*/
|
||||||
|
std::cout << "Type | Name " << std::endl;
|
||||||
|
std::cout << "---- | --------------------- " << std::endl;
|
||||||
|
for(auto it=oMap.begin(); it!=oMap.end(); it++ ) {
|
||||||
|
std::cout << it->second->ClassName() << " | "<< it->first << std::endl;
|
||||||
|
}
|
||||||
|
for(auto it=cutsMap.begin(); it!=cutsMap.end(); it++ ) {
|
||||||
|
std::cout << it->second->ClassName() << " | "<< it->first << std::endl;
|
||||||
|
}
|
||||||
|
std::cout << "---- | --------------------- " << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
52
Armory/Hit.h
Normal file
52
Armory/Hit.h
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
#ifndef Hit_H
|
||||||
|
#define Hit_H
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
class Hit{
|
||||||
|
public:
|
||||||
|
unsigned short sn;
|
||||||
|
uint8_t ch;
|
||||||
|
unsigned short energy;
|
||||||
|
unsigned short energy2;
|
||||||
|
unsigned long long timestamp;
|
||||||
|
unsigned short fineTime;
|
||||||
|
bool pileUp;
|
||||||
|
|
||||||
|
unsigned short traceLength;
|
||||||
|
std::vector<short> trace;
|
||||||
|
|
||||||
|
Hit(){
|
||||||
|
Clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Clear(){
|
||||||
|
sn = 0;
|
||||||
|
ch = 0;
|
||||||
|
energy = 0;
|
||||||
|
energy2 = 0;
|
||||||
|
timestamp = 0;
|
||||||
|
fineTime = 0;
|
||||||
|
traceLength = 0;
|
||||||
|
pileUp = false;
|
||||||
|
trace.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Print(){
|
||||||
|
printf("(%5d, %2d) %6d %16llu, %6d, %d, %5ld\n", sn, ch, energy, timestamp, fineTime, pileUp, trace.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrintTrace(){
|
||||||
|
for( unsigned short i = 0; i < traceLength; i++){
|
||||||
|
printf("%3u | %6d \n", i, trace[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Define operator< for sorting
|
||||||
|
bool operator<(const Hit& other) const {
|
||||||
|
return timestamp < other.timestamp;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
111
Armory/Kinematics.cpp
Normal file
111
Armory/Kinematics.cpp
Normal file
|
|
@ -0,0 +1,111 @@
|
||||||
|
#include "Kinematics.h"
|
||||||
|
//#include "elastcaller.h"
|
||||||
|
//double Kinematics::getQval(double m1, double m2, double m3, double t1, double t3, double angle3)
|
||||||
|
double Kinematics::getExc(double t3, double angle3)
|
||||||
|
/*
|
||||||
|
\brief Follows convention in Marion, 2013: (1 - beam, 2- target, 3-ejectile, 4-recoil)
|
||||||
|
|
||||||
|
m1 is beam, (typically heavy nucleus)
|
||||||
|
m2 is 'd', (light target)
|
||||||
|
m3 is 'p', (light ejectile mass)
|
||||||
|
t1 is beam kinetic energy,
|
||||||
|
\param t3 lab-kinetic-energy in MeV
|
||||||
|
\param angle3 lab-angle in deg of detected proton (if d,p) or other charged particle
|
||||||
|
\return Excitation energy of the heavy-recoil nucleus in MeV
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
double m1 = m_A;
|
||||||
|
double m2 = m_d;
|
||||||
|
double m3 = m_p;
|
||||||
|
double m4 = m_B;
|
||||||
|
double t1 = E_beam;
|
||||||
|
//t1 = slowitdown("75Ga",t1,"1(12C)2(2H)",1.2);
|
||||||
|
|
||||||
|
m1 *= u_MeV;
|
||||||
|
m2 *= u_MeV;
|
||||||
|
m3 *= u_MeV;
|
||||||
|
m4 *= u_MeV;
|
||||||
|
|
||||||
|
double e1 = m1 + t1;
|
||||||
|
double e3 = m3 + t3;
|
||||||
|
ET = t1 + m1 + m2;
|
||||||
|
double p1 = TMath::Sqrt(t1*t1 + 2*m1*t1);
|
||||||
|
double p3 = TMath::Sqrt(t3*t3 + 2*m3*t3);
|
||||||
|
double cosTheta = TMath::Cos(angle3*TMath::Pi()/180.);
|
||||||
|
// return m1+m2-m3-TMath::Sqrt(m1*m1 + m2*m2 + m3*m3 + 2.*m2*e1 - 2.*e3*(e1+m2)+ 2.*p1*p3*cosTheta);
|
||||||
|
double Q = m1+m2-m3-TMath::Sqrt(m1*m1 + m2*m2 + m3*m3 + 2.*m2*e1 - 2.*e3*(e1+m2)+ 2.*p1*p3*cosTheta);
|
||||||
|
|
||||||
|
Qx = Q;
|
||||||
|
T4 = ET - e3 - (m1+m2-m3-Q);
|
||||||
|
//T4 = slowitdown("75Ga",T4,"1(12C)2(2H)",1.2);
|
||||||
|
P4 = TMath::Sqrt(T4*T4 + 2*m4*T4);
|
||||||
|
|
||||||
|
//this angle will not be affected by eloss
|
||||||
|
theta4 = (180./M_PI)*TMath::ASin((p3/P4)*TMath::Sin(angle3*M_PI/180.));
|
||||||
|
|
||||||
|
// T4-=16.5; //eloss in about 1.4 mg CD2
|
||||||
|
// T4-=15.5; //eloss in 1.35 mg CD2 //TODO: actually degrade recoil/ejectiles in target
|
||||||
|
// T4-=14.1; //eloss in about 1.2 mg CD2
|
||||||
|
// T4-=31.7; //eloss in 2.7 mg CD2
|
||||||
|
|
||||||
|
//recalculate everything other than angle with lowered Kinetic energy
|
||||||
|
P4 = TMath::Sqrt(T4*T4 + 2*m4*T4);
|
||||||
|
gamma4 = T4/m4+1.;
|
||||||
|
beta4 = TMath::Sqrt(1. - 1./(gamma4*gamma4));
|
||||||
|
//beta4 = TMath::Sqrt((P4*P4)/(P4*P4 + m4*m4));
|
||||||
|
theta4 = (180./M_PI)*TMath::ASin((p3/P4)*TMath::Sin(angle3*M_PI/180.));
|
||||||
|
|
||||||
|
return Q0 - Q;//Q0 = Q + Exc
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
double Kinematics::getBeta4(double t3, double angle3)
|
||||||
|
/*
|
||||||
|
\brief Follows convention in Marion, 2013: (1 - beam, 2- target, 3-ejectile, 4-recoil)
|
||||||
|
|
||||||
|
m1 is beam, (typically heavy nucleus)
|
||||||
|
m2 is 'd', (light target)
|
||||||
|
m3 is 'p', (light ejectile mass)
|
||||||
|
t1 is beam kinetic energy,
|
||||||
|
\param t3 lab-kinetic-energy in MeV
|
||||||
|
\param angle3 lab-angle in deg of detected proton (if d,p) or other charged particle
|
||||||
|
\return doppler-shift beta (=v/c) of the heavy-recoil nucleus, calls getExc() to fill the value
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
getExc(t3, angle3);
|
||||||
|
return beta4;
|
||||||
|
}
|
||||||
|
|
||||||
|
double Kinematics::getBrho(double t3, double angle3, double charge_state) {
|
||||||
|
/*
|
||||||
|
\brief Follows convention in Marion, 2013: (1 - beam, 2- target, 3-ejectile, 4-recoil)
|
||||||
|
|
||||||
|
m1 is beam, (typically heavy nucleus)
|
||||||
|
m2 is 'd', (light target)
|
||||||
|
m3 is 'p', (light ejectile mass)
|
||||||
|
t1 is beam kinetic energy,
|
||||||
|
\param t3 lab-kinetic-energy in MeV
|
||||||
|
\param angle3 lab-angle in deg of detected proton (if d,p) or other charged particle
|
||||||
|
\param charge_state charge state of the intended nucleus, in units of elementary charge (= +1 for H+, +2 for He2+ etc).
|
||||||
|
\return b-rho value, generated from P4*3.3359e-3/charge_state where P4 is 4momentum of heavy-recoil calculated from orruba kinematics
|
||||||
|
*/
|
||||||
|
getExc(t3,angle3);
|
||||||
|
return P4*3.3359e-3/charge_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
double Kinematics::getTheta4(double t3, double angle3) {
|
||||||
|
/*
|
||||||
|
\brief Follows convention in Marion, 2013: (1 - beam, 2- target, 3-ejectile, 4-recoil)
|
||||||
|
|
||||||
|
m1 is beam, (typically heavy nucleus)
|
||||||
|
m2 is 'd', (light target)
|
||||||
|
m3 is 'p', (light ejectile mass)
|
||||||
|
t1 is beam kinetic energy,
|
||||||
|
\param t3 lab-kinetic-energy in MeV
|
||||||
|
\param angle3 lab-angle in deg of detected proton (if d,p) or other charged particle
|
||||||
|
\param charge_state charge state of the intended nucleus, in units of elementary charge (= +1 for H+, +2 for He2+ etc).
|
||||||
|
\return lab theta value of heavy recoil in degrees
|
||||||
|
*/
|
||||||
|
getExc(t3,angle3);
|
||||||
|
return theta4;
|
||||||
|
}
|
||||||
209
Armory/Kinematics.h
Normal file
209
Armory/Kinematics.h
Normal file
|
|
@ -0,0 +1,209 @@
|
||||||
|
#ifndef KINEMATICS_H
|
||||||
|
#define KINEMATICS_H
|
||||||
|
#include <TMath.h>
|
||||||
|
#include <iostream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <string>
|
||||||
|
#include <TVector3.h>
|
||||||
|
const double u_MeV = 931.49410372; //u in MeV
|
||||||
|
|
||||||
|
class Kinematics {
|
||||||
|
public:
|
||||||
|
/*
|
||||||
|
A(d,p)B is used as template, with A being beam, and p being ejectile.
|
||||||
|
Always, make m3 the thing you detect, and m1 the beam
|
||||||
|
*/
|
||||||
|
double m_A, m_d, m_p, m_B;
|
||||||
|
double E_beam;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @{ \name List of funny impossible default values
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* \brief Default values used for all the physics values
|
||||||
|
*/
|
||||||
|
double Q0=-9999, Qx=-9999;
|
||||||
|
double P4=-9999, E4=-9999, T4=-9999; //heavy recoil momentum, totE, KE
|
||||||
|
double P3=-9999, E3=-9999, T3=-9999; //light recoil
|
||||||
|
double ET=-9999;
|
||||||
|
double gamma4=-9999, beta4=-9999, theta4=-9999; //theta=heavy-recoil lab angle
|
||||||
|
double brho=-9999;
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
Kinematics(double m1, double m2, double m3, double m4, double ebeam) {
|
||||||
|
/*
|
||||||
|
A(d,p)B is used as template, with A being beam, and p being ejectile.
|
||||||
|
Always, make m3 the thing you detect, m2 the target, and m1 the beam
|
||||||
|
|
||||||
|
ebeam is in MeV/u, all others are in amu
|
||||||
|
*/
|
||||||
|
m_A = m1;
|
||||||
|
m_d = m2;
|
||||||
|
m_p = m3, m_B = m4, E_beam = ebeam*m_A;
|
||||||
|
Q0 = (- m_B - m_p + m_d + m_A)*u_MeV;
|
||||||
|
}
|
||||||
|
Kinematics() {}
|
||||||
|
|
||||||
|
void setValues(double m1, double m2, double m3, double m4, double ebeam) {
|
||||||
|
/*
|
||||||
|
Can be used to 'live update' say the beam energy in the case of active target detectors.
|
||||||
|
*/
|
||||||
|
|
||||||
|
m_A = m1;
|
||||||
|
m_d = m2;
|
||||||
|
m_p = m3, m_B = m4, E_beam = ebeam*m_A;
|
||||||
|
Q0 = (- m_B - m_p + m_d + m_A)*u_MeV;
|
||||||
|
//std::cout << "Q0 MeV: " << Q0 << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setEBeam(double Ebeam) {E_beam = Ebeam;}
|
||||||
|
|
||||||
|
double getBeta4(double t3, double angle3);
|
||||||
|
double getTheta4(double t3, double angle3);
|
||||||
|
double getBrho(double t3, double angle3, double charge_state);
|
||||||
|
double getExc(double t3, double angle3); //t3 is proton energy detected in ORRUBA, angle3 is proton angle in degrees
|
||||||
|
|
||||||
|
double getBeta4_fromvec(double t3, const TVector3 &pos, const TVector3 &origin) {
|
||||||
|
TVector3 local = pos - origin; //position w.r.t origin
|
||||||
|
float angle = local.Theta()*180./M_PI;
|
||||||
|
return getBeta4(t3, angle);
|
||||||
|
}
|
||||||
|
|
||||||
|
double getExc_fromvec(double t3, const TVector3 &pos, const TVector3 &origin) {
|
||||||
|
TVector3 local = pos - origin; //position w.r.t origin
|
||||||
|
float angle = local.Theta()*180./M_PI;
|
||||||
|
return getExc(t3, angle);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setValuesFromFile(const std::string& filename) {
|
||||||
|
(void) filename;
|
||||||
|
/*std::ifstream in;
|
||||||
|
in.open(filename);
|
||||||
|
if(!in) {
|
||||||
|
std::cerr<< "File not open at " << filename << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for(std::string line; std::getline(in, line); ) {
|
||||||
|
if(line.size()!=0 && line[0]=='#')
|
||||||
|
; //don't do anything with '#' lines
|
||||||
|
else {
|
||||||
|
std::stringstream ss(line);
|
||||||
|
ss>>m_A>>m_d>>m_p>>m_B>>E_beam;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
in.close();*/
|
||||||
|
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//double Kinematics::getQval(double m1, double m2, double m3, double t1, double t3, double angle3)
|
||||||
|
double Kinematics::getExc(double t3, double angle3)
|
||||||
|
/*
|
||||||
|
\brief Follows convention in Marion, 2013: (1 - beam, 2- target, 3-ejectile, 4-recoil)
|
||||||
|
|
||||||
|
m1 is beam, (typically heavy nucleus)
|
||||||
|
m2 is 'd', (light target)
|
||||||
|
m3 is 'p', (light ejectile mass)
|
||||||
|
t1 is beam kinetic energy,
|
||||||
|
|
||||||
|
All calculations are done here, and other wrapper functions written make derived quantities from stuff calculated here.
|
||||||
|
|
||||||
|
\param t3 lab-kinetic-energy in MeV
|
||||||
|
\param angle3 lab-angle in deg of detected proton (if d,p) or other charged particle
|
||||||
|
\return Excitation energy of the heavy-recoil nucleus in MeV
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
double m1 = m_A;
|
||||||
|
double m2 = m_d;
|
||||||
|
double m3 = m_p;
|
||||||
|
double m4 = m_B;
|
||||||
|
double t1 = E_beam;
|
||||||
|
|
||||||
|
m1 *= u_MeV;
|
||||||
|
m2 *= u_MeV;
|
||||||
|
m3 *= u_MeV;
|
||||||
|
m4 *= u_MeV;
|
||||||
|
|
||||||
|
double e1 = m1 + t1;
|
||||||
|
double e3 = m3 + t3;
|
||||||
|
ET = t1 + m1 + m2;
|
||||||
|
double p1 = TMath::Sqrt(t1*t1 + 2*m1*t1);
|
||||||
|
double p3 = TMath::Sqrt(t3*t3 + 2*m3*t3);
|
||||||
|
double cosTheta = TMath::Cos(angle3*TMath::Pi()/180.);
|
||||||
|
// return m1+m2-m3-TMath::Sqrt(m1*m1 + m2*m2 + m3*m3 + 2.*m2*e1 - 2.*e3*(e1+m2)+ 2.*p1*p3*cosTheta);
|
||||||
|
double Q = m1+m2-m3-TMath::Sqrt(m1*m1 + m2*m2 + m3*m3 + 2.*m2*e1 - 2.*e3*(e1+m2)+ 2.*p1*p3*cosTheta);
|
||||||
|
|
||||||
|
Qx = Q;
|
||||||
|
//Recoil properties just in case it's useful
|
||||||
|
T4 = ET - e3 - (m1+m2-m3-Q);
|
||||||
|
P4 = TMath::Sqrt(T4*T4 + 2*m4*T4);
|
||||||
|
|
||||||
|
//this angle will not be affected by eloss
|
||||||
|
theta4 = (180./M_PI)*TMath::ASin((p3/P4)*TMath::Sin(angle3*M_PI/180.));
|
||||||
|
|
||||||
|
//recalculate everything other than angle with lowered Kinetic energy
|
||||||
|
P4 = TMath::Sqrt(T4*T4 + 2*(m4+Q-Q0)*T4);
|
||||||
|
gamma4 = T4/m4+1.;
|
||||||
|
beta4 = TMath::Sqrt(1. - 1./(gamma4*gamma4));
|
||||||
|
theta4 = (180./M_PI)*TMath::ASin((p3/P4)*TMath::Sin(angle3*M_PI/180.));
|
||||||
|
|
||||||
|
//if(m2==m3) std::cout << "Q0 elastic: " << Q0 << " " << Q << "\n" ;
|
||||||
|
|
||||||
|
return Q0 - Q;//Q0 = Q + Exc
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
double Kinematics::getBeta4(double t3, double angle3)
|
||||||
|
/*
|
||||||
|
\brief Follows convention in Marion, 2013: (1 - beam, 2- target, 3-ejectile, 4-recoil)
|
||||||
|
|
||||||
|
m1 is beam, (typically heavy nucleus)
|
||||||
|
m2 is 'd', (light target)
|
||||||
|
m3 is 'p', (light ejectile mass)
|
||||||
|
t1 is beam kinetic energy,
|
||||||
|
\param t3 lab-kinetic-energy in MeV
|
||||||
|
\param angle3 lab-angle in deg of detected proton (if d,p) or other charged particle
|
||||||
|
\return doppler-shift beta (=v/c) of the heavy-recoil nucleus, calls getExc() to fill the value
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
getExc(t3, angle3);
|
||||||
|
return beta4;
|
||||||
|
}
|
||||||
|
|
||||||
|
double Kinematics::getBrho(double t3, double angle3, double charge_state) {
|
||||||
|
/*
|
||||||
|
\brief Follows convention in Marion, 2013: (1 - beam, 2- target, 3-ejectile, 4-recoil)
|
||||||
|
|
||||||
|
m1 is beam, (typically heavy nucleus)
|
||||||
|
m2 is 'd', (light target)
|
||||||
|
m3 is 'p', (light ejectile mass)
|
||||||
|
t1 is beam kinetic energy,
|
||||||
|
\param t3 lab-kinetic-energy in MeV
|
||||||
|
\param angle3 lab-angle in deg of detected proton (if d,p) or other charged particle
|
||||||
|
\param charge_state charge state of the intended nucleus, in units of elementary charge (= +1 for H+, +2 for He2+ etc).
|
||||||
|
\return b-rho value, generated from P4*3.3359e-3/charge_state where P4 is 4momentum of heavy-recoil calculated from orruba kinematics
|
||||||
|
*/
|
||||||
|
getExc(t3,angle3);
|
||||||
|
return P4*3.3359e-3/charge_state;
|
||||||
|
}
|
||||||
|
|
||||||
|
double Kinematics::getTheta4(double t3, double angle3) {
|
||||||
|
/*
|
||||||
|
\brief Follows convention in Marion, 2013: (1 - beam, 2- target, 3-ejectile, 4-recoil)
|
||||||
|
|
||||||
|
m1 is beam, (typically heavy nucleus)
|
||||||
|
m2 is 'd', (light target)
|
||||||
|
m3 is 'p', (light ejectile mass)
|
||||||
|
t1 is beam kinetic energy,
|
||||||
|
\param t3 lab-kinetic-energy in MeV
|
||||||
|
\param angle3 lab-angle in deg of detected proton (if d,p) or other charged particle
|
||||||
|
\param charge_state charge state of the intended nucleus, in units of elementary charge (= +1 for H+, +2 for He2+ etc).
|
||||||
|
\return lab theta value of heavy recoil in degrees
|
||||||
|
*/
|
||||||
|
getExc(t3,angle3);
|
||||||
|
return theta4;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
90
Armory/Kinematics2.h
Normal file
90
Armory/Kinematics2.h
Normal file
|
|
@ -0,0 +1,90 @@
|
||||||
|
#include <TLorentzVector.h>
|
||||||
|
#include <TMath.h>
|
||||||
|
#include <TVector3.h>
|
||||||
|
#include <iostream>
|
||||||
|
const double u_MeV = 931.49410372; // u in MeV
|
||||||
|
|
||||||
|
class Kinematics {
|
||||||
|
private:
|
||||||
|
double m_A, m_d, m_p, m_B; // Ground state masses in amu
|
||||||
|
double E_beam; // Total kinetic energy of beam (MeV)
|
||||||
|
double Q0; // Ground state Q-value
|
||||||
|
|
||||||
|
// Cached outputs from the last calculation
|
||||||
|
double fExc = -9999;
|
||||||
|
double fBeta4 = -9999;
|
||||||
|
double fTheta4 = -9999;
|
||||||
|
double fP4 = -9999;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
Kinematics() : m_A(0), m_d(0), m_p(0), m_B(0), E_beam(0), Q0(0) {}
|
||||||
|
Kinematics(const Kinematics&) = default;
|
||||||
|
Kinematics& operator=(const Kinematics&) = default;
|
||||||
|
|
||||||
|
Kinematics(double m1, double m2, double m3, double m4, double ebeam_per_u) {
|
||||||
|
setValues(m1, m2, m3, m4, ebeam_per_u);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setValues(double m1, double m2, double m3, double m4, double ebeam_per_u) {
|
||||||
|
m_A = m1; m_d = m2; m_p = m3; m_B = m4;
|
||||||
|
E_beam = ebeam_per_u * m_A;
|
||||||
|
Q0 = (m_A + m_d - m_p - m_B) * u_MeV;
|
||||||
|
}
|
||||||
|
|
||||||
|
void computeKinematics(double t3, double angle3_deg) {
|
||||||
|
// 1. Convert ground state masses to energy units (MeV)
|
||||||
|
double m1_MeV = m_A * u_MeV;
|
||||||
|
double m2_MeV = m_d * u_MeV;
|
||||||
|
double m3_MeV = m_p * u_MeV;
|
||||||
|
|
||||||
|
// 2. Build Four-Vectors for Initial State
|
||||||
|
double p1_mag = TMath::Sqrt(E_beam * E_beam + 2.0 * m1_MeV * E_beam);
|
||||||
|
TLorentzVector P1(0, 0, p1_mag, m1_MeV + E_beam); // Beam along Z-axis
|
||||||
|
TLorentzVector P2(0, 0, 0, m2_MeV); // Target at rest
|
||||||
|
|
||||||
|
// 3. Build Four-Vector for Detected Ejectile (Particle 3)
|
||||||
|
double theta3_rad = angle3_deg * TMath::Pi() / 180.0;
|
||||||
|
double p3_mag = TMath::Sqrt(t3 * t3 + 2.0 * m3_MeV * t3);
|
||||||
|
|
||||||
|
TVector3 p3_vec(0, 0, 1);
|
||||||
|
p3_vec.SetTheta(theta3_rad);
|
||||||
|
p3_vec.SetMag(p3_mag);
|
||||||
|
|
||||||
|
TLorentzVector P3(p3_vec, m3_MeV + t3);
|
||||||
|
|
||||||
|
// 4. Solve for Recoil (Particle 4) using Four-Momentum Conservation
|
||||||
|
TLorentzVector P4 = P1 + P2 - P3;
|
||||||
|
|
||||||
|
// 5. Extract Recoil physical properties
|
||||||
|
double m4_dynamic = P4.M(); // Invariant mass of the excited recoil nucleus
|
||||||
|
fExc = m4_dynamic - (m_B * u_MeV);
|
||||||
|
fBeta4 = P4.Beta();
|
||||||
|
fTheta4 = P4.Theta() * 180.0 / TMath::Pi();
|
||||||
|
fP4 = P4.P();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Getters that trigger computation
|
||||||
|
double getExc(double t3, double angle3) { computeKinematics(t3, angle3); return fExc; }
|
||||||
|
double getBeta4(double t3, double angle3) { computeKinematics(t3, angle3); return fBeta4; }
|
||||||
|
double getTheta4(double t3, double angle3){ computeKinematics(t3, angle3); return fTheta4; }
|
||||||
|
double getBrho(double t3, double angle3, double charge_state) {
|
||||||
|
computeKinematics(t3, angle3);
|
||||||
|
return fP4 * 3.3359e-3 / charge_state;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Simple test function to run in ROOT
|
||||||
|
void KinematicsMacro() {
|
||||||
|
// Example: d(16O, p)17O reaction with a 10 MeV/u 16O beam
|
||||||
|
// Masses roughly: 16O (~15.995), d (~2.014), p (~1.007), 17O (~16.999)
|
||||||
|
Kinematics k(15.9949, 2.0141, 1.0078, 16.9991, 10.0);
|
||||||
|
|
||||||
|
double t3 = 12.0; // Ejectile proton energy in MeV
|
||||||
|
double angle3 = 45.0; // Proton lab angle in degrees
|
||||||
|
|
||||||
|
std::cout << "--- Kinematics Results ---" << std::endl;
|
||||||
|
std::cout << "Excitation Energy: " << k.getExc(t3, angle3) << " MeV" << std::endl;
|
||||||
|
std::cout << "Recoil Beta: " << k.getBeta4(t3, angle3) << std::endl;
|
||||||
|
std::cout << "Recoil Angle: " << k.getTheta4(t3, angle3) << " deg" << std::endl;
|
||||||
|
}
|
||||||
674
Armory/LICENSE
Normal file
674
Armory/LICENSE
Normal file
|
|
@ -0,0 +1,674 @@
|
||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
Version 3, 29 June 2007
|
||||||
|
|
||||||
|
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The GNU General Public License is a free, copyleft license for
|
||||||
|
software and other kinds of works.
|
||||||
|
|
||||||
|
The licenses for most software and other practical works are designed
|
||||||
|
to take away your freedom to share and change the works. By contrast,
|
||||||
|
the GNU General Public License is intended to guarantee your freedom to
|
||||||
|
share and change all versions of a program--to make sure it remains free
|
||||||
|
software for all its users. We, the Free Software Foundation, use the
|
||||||
|
GNU General Public License for most of our software; it applies also to
|
||||||
|
any other work released this way by its authors. You can apply it to
|
||||||
|
your programs, too.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom, not
|
||||||
|
price. Our General Public Licenses are designed to make sure that you
|
||||||
|
have the freedom to distribute copies of free software (and charge for
|
||||||
|
them if you wish), that you receive source code or can get it if you
|
||||||
|
want it, that you can change the software or use pieces of it in new
|
||||||
|
free programs, and that you know you can do these things.
|
||||||
|
|
||||||
|
To protect your rights, we need to prevent others from denying you
|
||||||
|
these rights or asking you to surrender the rights. Therefore, you have
|
||||||
|
certain responsibilities if you distribute copies of the software, or if
|
||||||
|
you modify it: responsibilities to respect the freedom of others.
|
||||||
|
|
||||||
|
For example, if you distribute copies of such a program, whether
|
||||||
|
gratis or for a fee, you must pass on to the recipients the same
|
||||||
|
freedoms that you received. You must make sure that they, too, receive
|
||||||
|
or can get the source code. And you must show them these terms so they
|
||||||
|
know their rights.
|
||||||
|
|
||||||
|
Developers that use the GNU GPL protect your rights with two steps:
|
||||||
|
(1) assert copyright on the software, and (2) offer you this License
|
||||||
|
giving you legal permission to copy, distribute and/or modify it.
|
||||||
|
|
||||||
|
For the developers' and authors' protection, the GPL clearly explains
|
||||||
|
that there is no warranty for this free software. For both users' and
|
||||||
|
authors' sake, the GPL requires that modified versions be marked as
|
||||||
|
changed, so that their problems will not be attributed erroneously to
|
||||||
|
authors of previous versions.
|
||||||
|
|
||||||
|
Some devices are designed to deny users access to install or run
|
||||||
|
modified versions of the software inside them, although the manufacturer
|
||||||
|
can do so. This is fundamentally incompatible with the aim of
|
||||||
|
protecting users' freedom to change the software. The systematic
|
||||||
|
pattern of such abuse occurs in the area of products for individuals to
|
||||||
|
use, which is precisely where it is most unacceptable. Therefore, we
|
||||||
|
have designed this version of the GPL to prohibit the practice for those
|
||||||
|
products. If such problems arise substantially in other domains, we
|
||||||
|
stand ready to extend this provision to those domains in future versions
|
||||||
|
of the GPL, as needed to protect the freedom of users.
|
||||||
|
|
||||||
|
Finally, every program is threatened constantly by software patents.
|
||||||
|
States should not allow patents to restrict development and use of
|
||||||
|
software on general-purpose computers, but in those that do, we wish to
|
||||||
|
avoid the special danger that patents applied to a free program could
|
||||||
|
make it effectively proprietary. To prevent this, the GPL assures that
|
||||||
|
patents cannot be used to render the program non-free.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow.
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
0. Definitions.
|
||||||
|
|
||||||
|
"This License" refers to version 3 of the GNU General Public License.
|
||||||
|
|
||||||
|
"Copyright" also means copyright-like laws that apply to other kinds of
|
||||||
|
works, such as semiconductor masks.
|
||||||
|
|
||||||
|
"The Program" refers to any copyrightable work licensed under this
|
||||||
|
License. Each licensee is addressed as "you". "Licensees" and
|
||||||
|
"recipients" may be individuals or organizations.
|
||||||
|
|
||||||
|
To "modify" a work means to copy from or adapt all or part of the work
|
||||||
|
in a fashion requiring copyright permission, other than the making of an
|
||||||
|
exact copy. The resulting work is called a "modified version" of the
|
||||||
|
earlier work or a work "based on" the earlier work.
|
||||||
|
|
||||||
|
A "covered work" means either the unmodified Program or a work based
|
||||||
|
on the Program.
|
||||||
|
|
||||||
|
To "propagate" a work means to do anything with it that, without
|
||||||
|
permission, would make you directly or secondarily liable for
|
||||||
|
infringement under applicable copyright law, except executing it on a
|
||||||
|
computer or modifying a private copy. Propagation includes copying,
|
||||||
|
distribution (with or without modification), making available to the
|
||||||
|
public, and in some countries other activities as well.
|
||||||
|
|
||||||
|
To "convey" a work means any kind of propagation that enables other
|
||||||
|
parties to make or receive copies. Mere interaction with a user through
|
||||||
|
a computer network, with no transfer of a copy, is not conveying.
|
||||||
|
|
||||||
|
An interactive user interface displays "Appropriate Legal Notices"
|
||||||
|
to the extent that it includes a convenient and prominently visible
|
||||||
|
feature that (1) displays an appropriate copyright notice, and (2)
|
||||||
|
tells the user that there is no warranty for the work (except to the
|
||||||
|
extent that warranties are provided), that licensees may convey the
|
||||||
|
work under this License, and how to view a copy of this License. If
|
||||||
|
the interface presents a list of user commands or options, such as a
|
||||||
|
menu, a prominent item in the list meets this criterion.
|
||||||
|
|
||||||
|
1. Source Code.
|
||||||
|
|
||||||
|
The "source code" for a work means the preferred form of the work
|
||||||
|
for making modifications to it. "Object code" means any non-source
|
||||||
|
form of a work.
|
||||||
|
|
||||||
|
A "Standard Interface" means an interface that either is an official
|
||||||
|
standard defined by a recognized standards body, or, in the case of
|
||||||
|
interfaces specified for a particular programming language, one that
|
||||||
|
is widely used among developers working in that language.
|
||||||
|
|
||||||
|
The "System Libraries" of an executable work include anything, other
|
||||||
|
than the work as a whole, that (a) is included in the normal form of
|
||||||
|
packaging a Major Component, but which is not part of that Major
|
||||||
|
Component, and (b) serves only to enable use of the work with that
|
||||||
|
Major Component, or to implement a Standard Interface for which an
|
||||||
|
implementation is available to the public in source code form. A
|
||||||
|
"Major Component", in this context, means a major essential component
|
||||||
|
(kernel, window system, and so on) of the specific operating system
|
||||||
|
(if any) on which the executable work runs, or a compiler used to
|
||||||
|
produce the work, or an object code interpreter used to run it.
|
||||||
|
|
||||||
|
The "Corresponding Source" for a work in object code form means all
|
||||||
|
the source code needed to generate, install, and (for an executable
|
||||||
|
work) run the object code and to modify the work, including scripts to
|
||||||
|
control those activities. However, it does not include the work's
|
||||||
|
System Libraries, or general-purpose tools or generally available free
|
||||||
|
programs which are used unmodified in performing those activities but
|
||||||
|
which are not part of the work. For example, Corresponding Source
|
||||||
|
includes interface definition files associated with source files for
|
||||||
|
the work, and the source code for shared libraries and dynamically
|
||||||
|
linked subprograms that the work is specifically designed to require,
|
||||||
|
such as by intimate data communication or control flow between those
|
||||||
|
subprograms and other parts of the work.
|
||||||
|
|
||||||
|
The Corresponding Source need not include anything that users
|
||||||
|
can regenerate automatically from other parts of the Corresponding
|
||||||
|
Source.
|
||||||
|
|
||||||
|
The Corresponding Source for a work in source code form is that
|
||||||
|
same work.
|
||||||
|
|
||||||
|
2. Basic Permissions.
|
||||||
|
|
||||||
|
All rights granted under this License are granted for the term of
|
||||||
|
copyright on the Program, and are irrevocable provided the stated
|
||||||
|
conditions are met. This License explicitly affirms your unlimited
|
||||||
|
permission to run the unmodified Program. The output from running a
|
||||||
|
covered work is covered by this License only if the output, given its
|
||||||
|
content, constitutes a covered work. This License acknowledges your
|
||||||
|
rights of fair use or other equivalent, as provided by copyright law.
|
||||||
|
|
||||||
|
You may make, run and propagate covered works that you do not
|
||||||
|
convey, without conditions so long as your license otherwise remains
|
||||||
|
in force. You may convey covered works to others for the sole purpose
|
||||||
|
of having them make modifications exclusively for you, or provide you
|
||||||
|
with facilities for running those works, provided that you comply with
|
||||||
|
the terms of this License in conveying all material for which you do
|
||||||
|
not control copyright. Those thus making or running the covered works
|
||||||
|
for you must do so exclusively on your behalf, under your direction
|
||||||
|
and control, on terms that prohibit them from making any copies of
|
||||||
|
your copyrighted material outside their relationship with you.
|
||||||
|
|
||||||
|
Conveying under any other circumstances is permitted solely under
|
||||||
|
the conditions stated below. Sublicensing is not allowed; section 10
|
||||||
|
makes it unnecessary.
|
||||||
|
|
||||||
|
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
|
||||||
|
|
||||||
|
No covered work shall be deemed part of an effective technological
|
||||||
|
measure under any applicable law fulfilling obligations under article
|
||||||
|
11 of the WIPO copyright treaty adopted on 20 December 1996, or
|
||||||
|
similar laws prohibiting or restricting circumvention of such
|
||||||
|
measures.
|
||||||
|
|
||||||
|
When you convey a covered work, you waive any legal power to forbid
|
||||||
|
circumvention of technological measures to the extent such circumvention
|
||||||
|
is effected by exercising rights under this License with respect to
|
||||||
|
the covered work, and you disclaim any intention to limit operation or
|
||||||
|
modification of the work as a means of enforcing, against the work's
|
||||||
|
users, your or third parties' legal rights to forbid circumvention of
|
||||||
|
technological measures.
|
||||||
|
|
||||||
|
4. Conveying Verbatim Copies.
|
||||||
|
|
||||||
|
You may convey verbatim copies of the Program's source code as you
|
||||||
|
receive it, in any medium, provided that you conspicuously and
|
||||||
|
appropriately publish on each copy an appropriate copyright notice;
|
||||||
|
keep intact all notices stating that this License and any
|
||||||
|
non-permissive terms added in accord with section 7 apply to the code;
|
||||||
|
keep intact all notices of the absence of any warranty; and give all
|
||||||
|
recipients a copy of this License along with the Program.
|
||||||
|
|
||||||
|
You may charge any price or no price for each copy that you convey,
|
||||||
|
and you may offer support or warranty protection for a fee.
|
||||||
|
|
||||||
|
5. Conveying Modified Source Versions.
|
||||||
|
|
||||||
|
You may convey a work based on the Program, or the modifications to
|
||||||
|
produce it from the Program, in the form of source code under the
|
||||||
|
terms of section 4, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) The work must carry prominent notices stating that you modified
|
||||||
|
it, and giving a relevant date.
|
||||||
|
|
||||||
|
b) The work must carry prominent notices stating that it is
|
||||||
|
released under this License and any conditions added under section
|
||||||
|
7. This requirement modifies the requirement in section 4 to
|
||||||
|
"keep intact all notices".
|
||||||
|
|
||||||
|
c) You must license the entire work, as a whole, under this
|
||||||
|
License to anyone who comes into possession of a copy. This
|
||||||
|
License will therefore apply, along with any applicable section 7
|
||||||
|
additional terms, to the whole of the work, and all its parts,
|
||||||
|
regardless of how they are packaged. This License gives no
|
||||||
|
permission to license the work in any other way, but it does not
|
||||||
|
invalidate such permission if you have separately received it.
|
||||||
|
|
||||||
|
d) If the work has interactive user interfaces, each must display
|
||||||
|
Appropriate Legal Notices; however, if the Program has interactive
|
||||||
|
interfaces that do not display Appropriate Legal Notices, your
|
||||||
|
work need not make them do so.
|
||||||
|
|
||||||
|
A compilation of a covered work with other separate and independent
|
||||||
|
works, which are not by their nature extensions of the covered work,
|
||||||
|
and which are not combined with it such as to form a larger program,
|
||||||
|
in or on a volume of a storage or distribution medium, is called an
|
||||||
|
"aggregate" if the compilation and its resulting copyright are not
|
||||||
|
used to limit the access or legal rights of the compilation's users
|
||||||
|
beyond what the individual works permit. Inclusion of a covered work
|
||||||
|
in an aggregate does not cause this License to apply to the other
|
||||||
|
parts of the aggregate.
|
||||||
|
|
||||||
|
6. Conveying Non-Source Forms.
|
||||||
|
|
||||||
|
You may convey a covered work in object code form under the terms
|
||||||
|
of sections 4 and 5, provided that you also convey the
|
||||||
|
machine-readable Corresponding Source under the terms of this License,
|
||||||
|
in one of these ways:
|
||||||
|
|
||||||
|
a) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by the
|
||||||
|
Corresponding Source fixed on a durable physical medium
|
||||||
|
customarily used for software interchange.
|
||||||
|
|
||||||
|
b) Convey the object code in, or embodied in, a physical product
|
||||||
|
(including a physical distribution medium), accompanied by a
|
||||||
|
written offer, valid for at least three years and valid for as
|
||||||
|
long as you offer spare parts or customer support for that product
|
||||||
|
model, to give anyone who possesses the object code either (1) a
|
||||||
|
copy of the Corresponding Source for all the software in the
|
||||||
|
product that is covered by this License, on a durable physical
|
||||||
|
medium customarily used for software interchange, for a price no
|
||||||
|
more than your reasonable cost of physically performing this
|
||||||
|
conveying of source, or (2) access to copy the
|
||||||
|
Corresponding Source from a network server at no charge.
|
||||||
|
|
||||||
|
c) Convey individual copies of the object code with a copy of the
|
||||||
|
written offer to provide the Corresponding Source. This
|
||||||
|
alternative is allowed only occasionally and noncommercially, and
|
||||||
|
only if you received the object code with such an offer, in accord
|
||||||
|
with subsection 6b.
|
||||||
|
|
||||||
|
d) Convey the object code by offering access from a designated
|
||||||
|
place (gratis or for a charge), and offer equivalent access to the
|
||||||
|
Corresponding Source in the same way through the same place at no
|
||||||
|
further charge. You need not require recipients to copy the
|
||||||
|
Corresponding Source along with the object code. If the place to
|
||||||
|
copy the object code is a network server, the Corresponding Source
|
||||||
|
may be on a different server (operated by you or a third party)
|
||||||
|
that supports equivalent copying facilities, provided you maintain
|
||||||
|
clear directions next to the object code saying where to find the
|
||||||
|
Corresponding Source. Regardless of what server hosts the
|
||||||
|
Corresponding Source, you remain obligated to ensure that it is
|
||||||
|
available for as long as needed to satisfy these requirements.
|
||||||
|
|
||||||
|
e) Convey the object code using peer-to-peer transmission, provided
|
||||||
|
you inform other peers where the object code and Corresponding
|
||||||
|
Source of the work are being offered to the general public at no
|
||||||
|
charge under subsection 6d.
|
||||||
|
|
||||||
|
A separable portion of the object code, whose source code is excluded
|
||||||
|
from the Corresponding Source as a System Library, need not be
|
||||||
|
included in conveying the object code work.
|
||||||
|
|
||||||
|
A "User Product" is either (1) a "consumer product", which means any
|
||||||
|
tangible personal property which is normally used for personal, family,
|
||||||
|
or household purposes, or (2) anything designed or sold for incorporation
|
||||||
|
into a dwelling. In determining whether a product is a consumer product,
|
||||||
|
doubtful cases shall be resolved in favor of coverage. For a particular
|
||||||
|
product received by a particular user, "normally used" refers to a
|
||||||
|
typical or common use of that class of product, regardless of the status
|
||||||
|
of the particular user or of the way in which the particular user
|
||||||
|
actually uses, or expects or is expected to use, the product. A product
|
||||||
|
is a consumer product regardless of whether the product has substantial
|
||||||
|
commercial, industrial or non-consumer uses, unless such uses represent
|
||||||
|
the only significant mode of use of the product.
|
||||||
|
|
||||||
|
"Installation Information" for a User Product means any methods,
|
||||||
|
procedures, authorization keys, or other information required to install
|
||||||
|
and execute modified versions of a covered work in that User Product from
|
||||||
|
a modified version of its Corresponding Source. The information must
|
||||||
|
suffice to ensure that the continued functioning of the modified object
|
||||||
|
code is in no case prevented or interfered with solely because
|
||||||
|
modification has been made.
|
||||||
|
|
||||||
|
If you convey an object code work under this section in, or with, or
|
||||||
|
specifically for use in, a User Product, and the conveying occurs as
|
||||||
|
part of a transaction in which the right of possession and use of the
|
||||||
|
User Product is transferred to the recipient in perpetuity or for a
|
||||||
|
fixed term (regardless of how the transaction is characterized), the
|
||||||
|
Corresponding Source conveyed under this section must be accompanied
|
||||||
|
by the Installation Information. But this requirement does not apply
|
||||||
|
if neither you nor any third party retains the ability to install
|
||||||
|
modified object code on the User Product (for example, the work has
|
||||||
|
been installed in ROM).
|
||||||
|
|
||||||
|
The requirement to provide Installation Information does not include a
|
||||||
|
requirement to continue to provide support service, warranty, or updates
|
||||||
|
for a work that has been modified or installed by the recipient, or for
|
||||||
|
the User Product in which it has been modified or installed. Access to a
|
||||||
|
network may be denied when the modification itself materially and
|
||||||
|
adversely affects the operation of the network or violates the rules and
|
||||||
|
protocols for communication across the network.
|
||||||
|
|
||||||
|
Corresponding Source conveyed, and Installation Information provided,
|
||||||
|
in accord with this section must be in a format that is publicly
|
||||||
|
documented (and with an implementation available to the public in
|
||||||
|
source code form), and must require no special password or key for
|
||||||
|
unpacking, reading or copying.
|
||||||
|
|
||||||
|
7. Additional Terms.
|
||||||
|
|
||||||
|
"Additional permissions" are terms that supplement the terms of this
|
||||||
|
License by making exceptions from one or more of its conditions.
|
||||||
|
Additional permissions that are applicable to the entire Program shall
|
||||||
|
be treated as though they were included in this License, to the extent
|
||||||
|
that they are valid under applicable law. If additional permissions
|
||||||
|
apply only to part of the Program, that part may be used separately
|
||||||
|
under those permissions, but the entire Program remains governed by
|
||||||
|
this License without regard to the additional permissions.
|
||||||
|
|
||||||
|
When you convey a copy of a covered work, you may at your option
|
||||||
|
remove any additional permissions from that copy, or from any part of
|
||||||
|
it. (Additional permissions may be written to require their own
|
||||||
|
removal in certain cases when you modify the work.) You may place
|
||||||
|
additional permissions on material, added by you to a covered work,
|
||||||
|
for which you have or can give appropriate copyright permission.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, for material you
|
||||||
|
add to a covered work, you may (if authorized by the copyright holders of
|
||||||
|
that material) supplement the terms of this License with terms:
|
||||||
|
|
||||||
|
a) Disclaiming warranty or limiting liability differently from the
|
||||||
|
terms of sections 15 and 16 of this License; or
|
||||||
|
|
||||||
|
b) Requiring preservation of specified reasonable legal notices or
|
||||||
|
author attributions in that material or in the Appropriate Legal
|
||||||
|
Notices displayed by works containing it; or
|
||||||
|
|
||||||
|
c) Prohibiting misrepresentation of the origin of that material, or
|
||||||
|
requiring that modified versions of such material be marked in
|
||||||
|
reasonable ways as different from the original version; or
|
||||||
|
|
||||||
|
d) Limiting the use for publicity purposes of names of licensors or
|
||||||
|
authors of the material; or
|
||||||
|
|
||||||
|
e) Declining to grant rights under trademark law for use of some
|
||||||
|
trade names, trademarks, or service marks; or
|
||||||
|
|
||||||
|
f) Requiring indemnification of licensors and authors of that
|
||||||
|
material by anyone who conveys the material (or modified versions of
|
||||||
|
it) with contractual assumptions of liability to the recipient, for
|
||||||
|
any liability that these contractual assumptions directly impose on
|
||||||
|
those licensors and authors.
|
||||||
|
|
||||||
|
All other non-permissive additional terms are considered "further
|
||||||
|
restrictions" within the meaning of section 10. If the Program as you
|
||||||
|
received it, or any part of it, contains a notice stating that it is
|
||||||
|
governed by this License along with a term that is a further
|
||||||
|
restriction, you may remove that term. If a license document contains
|
||||||
|
a further restriction but permits relicensing or conveying under this
|
||||||
|
License, you may add to a covered work material governed by the terms
|
||||||
|
of that license document, provided that the further restriction does
|
||||||
|
not survive such relicensing or conveying.
|
||||||
|
|
||||||
|
If you add terms to a covered work in accord with this section, you
|
||||||
|
must place, in the relevant source files, a statement of the
|
||||||
|
additional terms that apply to those files, or a notice indicating
|
||||||
|
where to find the applicable terms.
|
||||||
|
|
||||||
|
Additional terms, permissive or non-permissive, may be stated in the
|
||||||
|
form of a separately written license, or stated as exceptions;
|
||||||
|
the above requirements apply either way.
|
||||||
|
|
||||||
|
8. Termination.
|
||||||
|
|
||||||
|
You may not propagate or modify a covered work except as expressly
|
||||||
|
provided under this License. Any attempt otherwise to propagate or
|
||||||
|
modify it is void, and will automatically terminate your rights under
|
||||||
|
this License (including any patent licenses granted under the third
|
||||||
|
paragraph of section 11).
|
||||||
|
|
||||||
|
However, if you cease all violation of this License, then your
|
||||||
|
license from a particular copyright holder is reinstated (a)
|
||||||
|
provisionally, unless and until the copyright holder explicitly and
|
||||||
|
finally terminates your license, and (b) permanently, if the copyright
|
||||||
|
holder fails to notify you of the violation by some reasonable means
|
||||||
|
prior to 60 days after the cessation.
|
||||||
|
|
||||||
|
Moreover, your license from a particular copyright holder is
|
||||||
|
reinstated permanently if the copyright holder notifies you of the
|
||||||
|
violation by some reasonable means, this is the first time you have
|
||||||
|
received notice of violation of this License (for any work) from that
|
||||||
|
copyright holder, and you cure the violation prior to 30 days after
|
||||||
|
your receipt of the notice.
|
||||||
|
|
||||||
|
Termination of your rights under this section does not terminate the
|
||||||
|
licenses of parties who have received copies or rights from you under
|
||||||
|
this License. If your rights have been terminated and not permanently
|
||||||
|
reinstated, you do not qualify to receive new licenses for the same
|
||||||
|
material under section 10.
|
||||||
|
|
||||||
|
9. Acceptance Not Required for Having Copies.
|
||||||
|
|
||||||
|
You are not required to accept this License in order to receive or
|
||||||
|
run a copy of the Program. Ancillary propagation of a covered work
|
||||||
|
occurring solely as a consequence of using peer-to-peer transmission
|
||||||
|
to receive a copy likewise does not require acceptance. However,
|
||||||
|
nothing other than this License grants you permission to propagate or
|
||||||
|
modify any covered work. These actions infringe copyright if you do
|
||||||
|
not accept this License. Therefore, by modifying or propagating a
|
||||||
|
covered work, you indicate your acceptance of this License to do so.
|
||||||
|
|
||||||
|
10. Automatic Licensing of Downstream Recipients.
|
||||||
|
|
||||||
|
Each time you convey a covered work, the recipient automatically
|
||||||
|
receives a license from the original licensors, to run, modify and
|
||||||
|
propagate that work, subject to this License. You are not responsible
|
||||||
|
for enforcing compliance by third parties with this License.
|
||||||
|
|
||||||
|
An "entity transaction" is a transaction transferring control of an
|
||||||
|
organization, or substantially all assets of one, or subdividing an
|
||||||
|
organization, or merging organizations. If propagation of a covered
|
||||||
|
work results from an entity transaction, each party to that
|
||||||
|
transaction who receives a copy of the work also receives whatever
|
||||||
|
licenses to the work the party's predecessor in interest had or could
|
||||||
|
give under the previous paragraph, plus a right to possession of the
|
||||||
|
Corresponding Source of the work from the predecessor in interest, if
|
||||||
|
the predecessor has it or can get it with reasonable efforts.
|
||||||
|
|
||||||
|
You may not impose any further restrictions on the exercise of the
|
||||||
|
rights granted or affirmed under this License. For example, you may
|
||||||
|
not impose a license fee, royalty, or other charge for exercise of
|
||||||
|
rights granted under this License, and you may not initiate litigation
|
||||||
|
(including a cross-claim or counterclaim in a lawsuit) alleging that
|
||||||
|
any patent claim is infringed by making, using, selling, offering for
|
||||||
|
sale, or importing the Program or any portion of it.
|
||||||
|
|
||||||
|
11. Patents.
|
||||||
|
|
||||||
|
A "contributor" is a copyright holder who authorizes use under this
|
||||||
|
License of the Program or a work on which the Program is based. The
|
||||||
|
work thus licensed is called the contributor's "contributor version".
|
||||||
|
|
||||||
|
A contributor's "essential patent claims" are all patent claims
|
||||||
|
owned or controlled by the contributor, whether already acquired or
|
||||||
|
hereafter acquired, that would be infringed by some manner, permitted
|
||||||
|
by this License, of making, using, or selling its contributor version,
|
||||||
|
but do not include claims that would be infringed only as a
|
||||||
|
consequence of further modification of the contributor version. For
|
||||||
|
purposes of this definition, "control" includes the right to grant
|
||||||
|
patent sublicenses in a manner consistent with the requirements of
|
||||||
|
this License.
|
||||||
|
|
||||||
|
Each contributor grants you a non-exclusive, worldwide, royalty-free
|
||||||
|
patent license under the contributor's essential patent claims, to
|
||||||
|
make, use, sell, offer for sale, import and otherwise run, modify and
|
||||||
|
propagate the contents of its contributor version.
|
||||||
|
|
||||||
|
In the following three paragraphs, a "patent license" is any express
|
||||||
|
agreement or commitment, however denominated, not to enforce a patent
|
||||||
|
(such as an express permission to practice a patent or covenant not to
|
||||||
|
sue for patent infringement). To "grant" such a patent license to a
|
||||||
|
party means to make such an agreement or commitment not to enforce a
|
||||||
|
patent against the party.
|
||||||
|
|
||||||
|
If you convey a covered work, knowingly relying on a patent license,
|
||||||
|
and the Corresponding Source of the work is not available for anyone
|
||||||
|
to copy, free of charge and under the terms of this License, through a
|
||||||
|
publicly available network server or other readily accessible means,
|
||||||
|
then you must either (1) cause the Corresponding Source to be so
|
||||||
|
available, or (2) arrange to deprive yourself of the benefit of the
|
||||||
|
patent license for this particular work, or (3) arrange, in a manner
|
||||||
|
consistent with the requirements of this License, to extend the patent
|
||||||
|
license to downstream recipients. "Knowingly relying" means you have
|
||||||
|
actual knowledge that, but for the patent license, your conveying the
|
||||||
|
covered work in a country, or your recipient's use of the covered work
|
||||||
|
in a country, would infringe one or more identifiable patents in that
|
||||||
|
country that you have reason to believe are valid.
|
||||||
|
|
||||||
|
If, pursuant to or in connection with a single transaction or
|
||||||
|
arrangement, you convey, or propagate by procuring conveyance of, a
|
||||||
|
covered work, and grant a patent license to some of the parties
|
||||||
|
receiving the covered work authorizing them to use, propagate, modify
|
||||||
|
or convey a specific copy of the covered work, then the patent license
|
||||||
|
you grant is automatically extended to all recipients of the covered
|
||||||
|
work and works based on it.
|
||||||
|
|
||||||
|
A patent license is "discriminatory" if it does not include within
|
||||||
|
the scope of its coverage, prohibits the exercise of, or is
|
||||||
|
conditioned on the non-exercise of one or more of the rights that are
|
||||||
|
specifically granted under this License. You may not convey a covered
|
||||||
|
work if you are a party to an arrangement with a third party that is
|
||||||
|
in the business of distributing software, under which you make payment
|
||||||
|
to the third party based on the extent of your activity of conveying
|
||||||
|
the work, and under which the third party grants, to any of the
|
||||||
|
parties who would receive the covered work from you, a discriminatory
|
||||||
|
patent license (a) in connection with copies of the covered work
|
||||||
|
conveyed by you (or copies made from those copies), or (b) primarily
|
||||||
|
for and in connection with specific products or compilations that
|
||||||
|
contain the covered work, unless you entered into that arrangement,
|
||||||
|
or that patent license was granted, prior to 28 March 2007.
|
||||||
|
|
||||||
|
Nothing in this License shall be construed as excluding or limiting
|
||||||
|
any implied license or other defenses to infringement that may
|
||||||
|
otherwise be available to you under applicable patent law.
|
||||||
|
|
||||||
|
12. No Surrender of Others' Freedom.
|
||||||
|
|
||||||
|
If conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot convey a
|
||||||
|
covered work so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you may
|
||||||
|
not convey it at all. For example, if you agree to terms that obligate you
|
||||||
|
to collect a royalty for further conveying from those to whom you convey
|
||||||
|
the Program, the only way you could satisfy both those terms and this
|
||||||
|
License would be to refrain entirely from conveying the Program.
|
||||||
|
|
||||||
|
13. Use with the GNU Affero General Public License.
|
||||||
|
|
||||||
|
Notwithstanding any other provision of this License, you have
|
||||||
|
permission to link or combine any covered work with a work licensed
|
||||||
|
under version 3 of the GNU Affero General Public License into a single
|
||||||
|
combined work, and to convey the resulting work. The terms of this
|
||||||
|
License will continue to apply to the part which is the covered work,
|
||||||
|
but the special requirements of the GNU Affero General Public License,
|
||||||
|
section 13, concerning interaction through a network will apply to the
|
||||||
|
combination as such.
|
||||||
|
|
||||||
|
14. Revised Versions of this License.
|
||||||
|
|
||||||
|
The Free Software Foundation may publish revised and/or new versions of
|
||||||
|
the GNU General Public License from time to time. Such new versions will
|
||||||
|
be similar in spirit to the present version, but may differ in detail to
|
||||||
|
address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the
|
||||||
|
Program specifies that a certain numbered version of the GNU General
|
||||||
|
Public License "or any later version" applies to it, you have the
|
||||||
|
option of following the terms and conditions either of that numbered
|
||||||
|
version or of any later version published by the Free Software
|
||||||
|
Foundation. If the Program does not specify a version number of the
|
||||||
|
GNU General Public License, you may choose any version ever published
|
||||||
|
by the Free Software Foundation.
|
||||||
|
|
||||||
|
If the Program specifies that a proxy can decide which future
|
||||||
|
versions of the GNU General Public License can be used, that proxy's
|
||||||
|
public statement of acceptance of a version permanently authorizes you
|
||||||
|
to choose that version for the Program.
|
||||||
|
|
||||||
|
Later license versions may give you additional or different
|
||||||
|
permissions. However, no additional obligations are imposed on any
|
||||||
|
author or copyright holder as a result of your choosing to follow a
|
||||||
|
later version.
|
||||||
|
|
||||||
|
15. Disclaimer of Warranty.
|
||||||
|
|
||||||
|
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
|
||||||
|
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
|
||||||
|
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
|
||||||
|
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
|
||||||
|
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||||
|
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
|
||||||
|
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
|
||||||
|
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
16. Limitation of Liability.
|
||||||
|
|
||||||
|
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||||
|
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
|
||||||
|
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
|
||||||
|
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
|
||||||
|
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
|
||||||
|
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
|
||||||
|
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
|
||||||
|
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
|
||||||
|
SUCH DAMAGES.
|
||||||
|
|
||||||
|
17. Interpretation of Sections 15 and 16.
|
||||||
|
|
||||||
|
If the disclaimer of warranty and limitation of liability provided
|
||||||
|
above cannot be given local legal effect according to their terms,
|
||||||
|
reviewing courts shall apply local law that most closely approximates
|
||||||
|
an absolute waiver of all civil liability in connection with the
|
||||||
|
Program, unless a warranty or assumption of liability accompanies a
|
||||||
|
copy of the Program in return for a fee.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Programs
|
||||||
|
|
||||||
|
If you develop a new program, and you want it to be of the greatest
|
||||||
|
possible use to the public, the best way to achieve this is to make it
|
||||||
|
free software which everyone can redistribute and change under these terms.
|
||||||
|
|
||||||
|
To do so, attach the following notices to the program. It is safest
|
||||||
|
to attach them to the start of each source file to most effectively
|
||||||
|
state the exclusion of warranty; and each file should have at least
|
||||||
|
the "copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
|
<one line to give the program's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
If the program does terminal interaction, make it output a short
|
||||||
|
notice like this when it starts in an interactive mode:
|
||||||
|
|
||||||
|
<program> Copyright (C) <year> <name of author>
|
||||||
|
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||||
|
This is free software, and you are welcome to redistribute it
|
||||||
|
under certain conditions; type `show c' for details.
|
||||||
|
|
||||||
|
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||||
|
parts of the General Public License. Of course, your program's commands
|
||||||
|
might be different; for a GUI interface, you would use an "about box".
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or school,
|
||||||
|
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||||
|
For more information on this, and how to apply and follow the GNU GPL, see
|
||||||
|
<https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
The GNU General Public License does not permit incorporating your program
|
||||||
|
into proprietary programs. If your program is a subroutine library, you
|
||||||
|
may consider it more useful to permit linking proprietary applications with
|
||||||
|
the library. If this is what you want to do, use the GNU Lesser General
|
||||||
|
Public License instead of this License. But first, please read
|
||||||
|
<https://www.gnu.org/licenses/why-not-lgpl.html>.
|
||||||
|
|
@ -10,7 +10,7 @@ COPTS = -fPIC -DLINUX -g -O0 -Wall -std=c++17 -lpthread
|
||||||
|
|
||||||
ROOTLIBS = `root-config --cflags --glibs`
|
ROOTLIBS = `root-config --cflags --glibs`
|
||||||
|
|
||||||
ALL = Mapper AnasenMS
|
ALL = Mapper EventBuilder#AnasenMS
|
||||||
|
|
||||||
#########################################################################
|
#########################################################################
|
||||||
|
|
||||||
|
|
@ -23,6 +23,10 @@ Mapper : Mapper.cpp ../mapping.h ClassDet.h
|
||||||
@echo "--------- making Mapper"
|
@echo "--------- making Mapper"
|
||||||
$(CC) $(COPTS) -o Mapper Mapper.cpp $(ROOTLIBS)
|
$(CC) $(COPTS) -o Mapper Mapper.cpp $(ROOTLIBS)
|
||||||
|
|
||||||
AnasenMS : constant.h Isotope.h ClassTransfer.h ClassSX3.h ClassPW.h ClassAnasen.h anasenMS.cpp
|
# AnasenMS : constant.h Isotope.h ClassTransfer.h ClassSX3.h ClassPW.h ClassAnasen.h anasenMS.cpp
|
||||||
@echo "--------- making ANASEN Monte Carlo"
|
# @echo "--------- making ANASEN Monte Carlo"
|
||||||
$(CC) $(COPTS) -o AnasenMS anasenMS.cpp $(ROOTLIBS)
|
# $(CC) $(COPTS) -o AnasenMS anasenMS.cpp $(ROOTLIBS)
|
||||||
|
|
||||||
|
EventBuilder : EventBuilder.cpp ../ClassData.h fsuReader.h ../Hit.h
|
||||||
|
@echo "--------- making EventBuilder"
|
||||||
|
$(CC) $(COPTS) -o EventBuilder EventBuilder.cpp $(ROOTLIBS)
|
||||||
|
|
|
||||||
98
Armory/PC_StepLadder_Correction.h
Normal file
98
Armory/PC_StepLadder_Correction.h
Normal file
|
|
@ -0,0 +1,98 @@
|
||||||
|
#include <TF1.h>
|
||||||
|
|
||||||
|
double model_invert(double* y, double* p) {
|
||||||
|
double result = y[0];
|
||||||
|
double slope = 0.56;
|
||||||
|
double z_grid[8] = {147.998,101.946,59.7634,19.6965,-19.6965,-59.7634,-101.946,-147.998}; //crossover z values
|
||||||
|
for(int i=0;i<7;i++) {
|
||||||
|
if(y[0] <= z_grid[i] && y[0] > z_grid[i+1]) {
|
||||||
|
double zavg = (z_grid[i] + z_grid[i+1])*0.5; //midpoint about which we pivot
|
||||||
|
result = (y[0]-zavg)/slope + zavg;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
double model_a1c1(double* x, double* p) {
|
||||||
|
double result = x[0];
|
||||||
|
double factor = 29.0;
|
||||||
|
double slope = 0.0;
|
||||||
|
if(TMath::Abs(x[0]) < 16.2) result=x[0]*slope;
|
||||||
|
else if(TMath::Abs(x[0]) < 49.8 ) result=x[0]*slope+TMath::Sign(1.0,x[0])*factor;
|
||||||
|
else if(TMath::Abs(x[0]) < 85.2 ) result=x[0]*slope+TMath::Sign(1.0,x[0])*factor*2;
|
||||||
|
else result=x[0]*slope+TMath::Sign(1.0,x[0])*factor*3;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
double model_invert_a1c1(double *y, double *q) {
|
||||||
|
double result=y[0];
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::tuple<TVector3,TVector3,double> find_PC_PathLength(const TVector3& x1, const TVector3& x2) {
|
||||||
|
/*
|
||||||
|
Function that finds the path length between anode and cathode surfaces, both one-sheet hyperboloids of form (x*x+y*y)/(a*a) - (z*z)/(c*c) = 1
|
||||||
|
* path length found for a given particle moving along a certain direction from x1 to x2
|
||||||
|
* Typical arguments here will be x1=r_rhoMin, x2=qqqevent.pos or sx3event.pos
|
||||||
|
*/
|
||||||
|
TVector3 dx = x2-x1;// direction vector
|
||||||
|
double t2 = 1.0; //The value of 't' at the destination point, by definition: t=(z(t)-z0)/dz
|
||||||
|
auto onesheet_hyperboloid_intersect = [&](double a, double c) {
|
||||||
|
auto A = pow(dx.Perp(),2)/(a*a) - pow(dx.Z(),2)/(c*c);
|
||||||
|
auto B = 2*(dx.X()*x1.X()+dx.Y()*x1.Y())/(a*a) - 2*(dx.Z()*x1.Z())/(c*c);
|
||||||
|
auto C = pow(x1.Perp(),2)/(a*a) - pow(x1.Z(),2)/(c*c) - 1.0;
|
||||||
|
double disc = B*B - 4*A*C;
|
||||||
|
if(disc<0)
|
||||||
|
return TVector3(0,0,54321);
|
||||||
|
else {
|
||||||
|
double tsol1 = (-B + TMath::Sqrt(disc))/(2*A);
|
||||||
|
double tsol2 = (-B - TMath::Sqrt(disc))/(2*A);
|
||||||
|
if(tsol1 >= 0 && tsol1 <= t2)
|
||||||
|
return x1+tsol1*dx;
|
||||||
|
else if(tsol2>=0 && tsol2 <= t2)
|
||||||
|
return x1+tsol2*dx;
|
||||||
|
else
|
||||||
|
return TVector3(0,0,54321);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
//TODO: Magic numbers here describing waist 'a', and flare 'c' will need better treatment.
|
||||||
|
//Currently, these are derived by fitting the crossover points to R^2/a^2 - z^2/c^2 = 1 for anodes
|
||||||
|
// Cathode a, c values are found by scaling up the anode waist by 43/37, the ratio of the outermost radii
|
||||||
|
TVector3 anode_intersect = onesheet_hyperboloid_intersect(32.0429,301.895);
|
||||||
|
TVector3 cathode_intersect = onesheet_hyperboloid_intersect(37.239045,301.895);
|
||||||
|
if(anode_intersect.Z()!=54321 && cathode_intersect.Z()!=54321)
|
||||||
|
return std::tuple(cathode_intersect,anode_intersect,(cathode_intersect-anode_intersect).Mag()*0.1);
|
||||||
|
else
|
||||||
|
return std::tuple(TVector3(0,0,0), TVector3(0,0,0), 54321);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*void testmodel() {
|
||||||
|
TF1 eqline("x","x",-200,200);
|
||||||
|
eqline.Draw("");
|
||||||
|
eqline.SetLineStyle(kDashed);
|
||||||
|
|
||||||
|
//TF1 f1("model",model,-200,200,2);
|
||||||
|
TF1 f1a("model_inv",model_a1c1,-200,200,2);
|
||||||
|
eqline.SetNpx(10000);
|
||||||
|
f1a.SetNpx(10000);
|
||||||
|
std::vector<double> pars = {0.0,1.};
|
||||||
|
f1a.SetParameters(pars.data());
|
||||||
|
f1a.SetLineColor(kGreen+2);
|
||||||
|
f1a.SetLineStyle(kLine);
|
||||||
|
f1a.Draw("L SAME");
|
||||||
|
|
||||||
|
TF1 f1("model",model,-200,200,2);
|
||||||
|
//TF1 f1("model_inv",model_invert,-200,200,2);
|
||||||
|
eqline.SetNpx(10000);
|
||||||
|
f1.SetNpx(10000);
|
||||||
|
//std::vector<double> pars = {0.0,1.};
|
||||||
|
f1.SetParameters(pars.data());
|
||||||
|
f1.SetLineColor(kGreen+2);
|
||||||
|
f1.SetLineStyle(kLine);
|
||||||
|
f1.Draw("L SAME");
|
||||||
|
|
||||||
|
gPad->Modified(); gPad->Update();
|
||||||
|
while(gPad->WaitPrimitive());
|
||||||
|
}*/
|
||||||
190
Armory/SX3Geom.h
Normal file
190
Armory/SX3Geom.h
Normal file
|
|
@ -0,0 +1,190 @@
|
||||||
|
#ifndef SX3Geom_h
|
||||||
|
#define SX3Geom_h
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
|
const double DEFAULT_NULL=-987654321.;
|
||||||
|
|
||||||
|
class sx3_geometry_scalefactors {
|
||||||
|
public:
|
||||||
|
//If sx3 has L, R being the left and right extremities, we choose add, stretch here such that
|
||||||
|
// x_mm = (x_raw+add)*stretch; so add=abs(L), stretch=75/(abs(L)+R)
|
||||||
|
float add[4];
|
||||||
|
float stretch[4];
|
||||||
|
};
|
||||||
|
|
||||||
|
class qqq5_finegains {
|
||||||
|
public:
|
||||||
|
std::array<std::pair<float,float>,32> front;
|
||||||
|
//front.at(30).first = slope at clkpos 0, ring 30 for E front layer
|
||||||
|
//front.at(30).second = intercept for the same as above
|
||||||
|
std::array<std::pair<float,float>,4> back;
|
||||||
|
};
|
||||||
|
class sx3_fbgains {
|
||||||
|
public:
|
||||||
|
//Order of indices is [pad][strip]
|
||||||
|
float padoffsets[4][4];
|
||||||
|
float padgains[4][4];
|
||||||
|
|
||||||
|
float stripLoffsets[4][4];
|
||||||
|
float stripLgains[4][4];
|
||||||
|
|
||||||
|
float stripRoffsets[4][4];
|
||||||
|
float stripRgains[4][4];
|
||||||
|
};
|
||||||
|
|
||||||
|
std::array<sx3_fbgains,24> sx3_xtalk_gains; //every sx3 needs to be gainmatched as a frontL-back, frontR-back pair (pad strip pair)
|
||||||
|
std::array<sx3_geometry_scalefactors,24> sx3gs;
|
||||||
|
|
||||||
|
class sx3 {
|
||||||
|
public:
|
||||||
|
//TODO: Convert to std::array
|
||||||
|
//Holds all information in an event, including ped subtraction+scaling. back[2].at(0) will have the largest energy seen in ch2, if any
|
||||||
|
std::vector<float> back[4];
|
||||||
|
std::vector<float> frontL[4];
|
||||||
|
std::vector<float> frontR[4];
|
||||||
|
|
||||||
|
double ts = DEFAULT_NULL;
|
||||||
|
//Easy lookup of final calibrated event. Only filled for valid cases, assumed for now to be 1L, 1R, 1B
|
||||||
|
float frontX=DEFAULT_NULL;
|
||||||
|
float frontXmm=DEFAULT_NULL;
|
||||||
|
float frontE=DEFAULT_NULL;
|
||||||
|
float backE=DEFAULT_NULL;
|
||||||
|
int stripF=DEFAULT_NULL;
|
||||||
|
int stripB=DEFAULT_NULL;
|
||||||
|
float frontEL=DEFAULT_NULL;
|
||||||
|
float frontER=DEFAULT_NULL;
|
||||||
|
|
||||||
|
float phi=DEFAULT_NULL; //
|
||||||
|
|
||||||
|
std::set<int> valid_front_chans;
|
||||||
|
std::set<int> valid_back_chans;
|
||||||
|
std::set<int> unmatched_front_chans; //every front channel is unmatched and invalid at first. when it gets matched, it gets removed and sent to valid
|
||||||
|
|
||||||
|
bool foundevent=false;
|
||||||
|
bool valid=false;//valid will be set to false in all cases where we have ambiguity
|
||||||
|
int flags=-1;//flags settable to different types of values to indicate different invalid situations
|
||||||
|
|
||||||
|
void fillevent(const std::string& position, const int subchannel, const float value); //make 'const' what functions don't need to change, helps with performance
|
||||||
|
void validate(const sx3_fbgains&, const sx3_geometry_scalefactors&);
|
||||||
|
void validate();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void sx3::fillevent(const std::string& positionstring, const int subchannel, const float value) {
|
||||||
|
assert(subchannel>=0 && subchannel<4);
|
||||||
|
foundevent=1;
|
||||||
|
if(positionstring=="FRONT_L") {
|
||||||
|
frontL[subchannel].push_back(value);
|
||||||
|
unmatched_front_chans.insert(subchannel);
|
||||||
|
} else if(positionstring=="FRONT_R") {
|
||||||
|
frontR[subchannel].push_back(value);
|
||||||
|
unmatched_front_chans.insert(subchannel);
|
||||||
|
} else if(positionstring=="BACK") {
|
||||||
|
back[subchannel].push_back(value);
|
||||||
|
valid_back_chans.insert(subchannel);
|
||||||
|
} else {
|
||||||
|
std::cout << "Unknown string "+positionstring+" encountered in sx3::fillevent \n" << std::endl;
|
||||||
|
}
|
||||||
|
if(frontL[subchannel].size()!=0 && frontR[subchannel].size()!=0 ) {
|
||||||
|
unmatched_front_chans.erase(subchannel);
|
||||||
|
valid_front_chans.insert(subchannel); //std::set, so no duplication will happen
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//void sx3::validate(const sx3_fbgains& fbgains, const sx3_geometry_scalefactors& sx3gs) {
|
||||||
|
void sx3::validate() {
|
||||||
|
if(valid_front_chans.size()!=0 && valid_back_chans.size()!=0) {
|
||||||
|
valid=true;
|
||||||
|
float maxFE=0;
|
||||||
|
float maxBE=0;
|
||||||
|
//float zpos=0;
|
||||||
|
int bchan=-1;
|
||||||
|
int fchan=-1;
|
||||||
|
/* for(auto cc: valid_front_chans) {
|
||||||
|
std::cout << "fc" << cc << std::endl;// " " << frontL[cc].at(0) << " " << frontR[cc].at(0) << std::endl;
|
||||||
|
}
|
||||||
|
for(auto cc: valid_back_chans) {
|
||||||
|
std::cout << "bc" << cc << std::endl; //" " << back[cc].at(0) << std::endl;
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
for(auto chan: valid_front_chans) {
|
||||||
|
if(frontL[chan].size()>1) {
|
||||||
|
printf("\nmultihit sx3 at Lsubchan:%d, ts:%1.13g\n",chan,ts);
|
||||||
|
for(const auto& e: frontL[chan]) printf("e: %f\t",e);
|
||||||
|
std::sort(frontL[chan].begin(), frontL[chan].end(), std::greater<float>());
|
||||||
|
flags += (-1000);
|
||||||
|
}
|
||||||
|
if(frontR[chan].size()>1) {
|
||||||
|
printf("\nmultihit sx3 at Rsubchan:%d, ts:%1.13g\n",chan,ts);
|
||||||
|
for(const auto& e: frontR[chan]) printf("e: %f\t",e);
|
||||||
|
std::sort(frontR[chan].begin(), frontR[chan].end(), std::greater<float>());
|
||||||
|
flags += (-2000);
|
||||||
|
}
|
||||||
|
//assign position using max L+R value
|
||||||
|
/*printf("chan:%d sizeL: %d sizeR: %d\n",chan, frontL[chan].size(), frontR[chan].size()); fflush(stdout);
|
||||||
|
printf("foo\n");
|
||||||
|
std::cout << "\nL:" << std::endl;
|
||||||
|
for(auto thing: frontL[chan]) std::cout << thing << " " << std::flush;
|
||||||
|
std::cout << "\nR:" << std::endl;
|
||||||
|
for(auto thing: frontR[chan]) std::cout << thing << " " << std::flush;*/
|
||||||
|
if(frontL[chan].at(0) + frontR[chan].at(0)>= maxFE) {
|
||||||
|
maxFE = frontL[chan].at(0) + frontR[chan].at(0);
|
||||||
|
//zpos = (frontL[chan].at(0)-frontR[chan].at(0))/maxFE;
|
||||||
|
fchan = chan;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(auto chan: valid_back_chans) {
|
||||||
|
if(back[chan].size()>1) {
|
||||||
|
printf("\nmultihit sx3 at Bsubchan:%d, ts:%1.13g\n",chan,ts);
|
||||||
|
for(const auto& e: back[chan]) printf("e: %f\t",e);
|
||||||
|
std::sort(back[chan].begin(), back[chan].end(), std::greater<float>());
|
||||||
|
flags += (-3000);
|
||||||
|
}
|
||||||
|
if(back[chan].size() ==0 ) {
|
||||||
|
printf("foo\n");
|
||||||
|
//continue;
|
||||||
|
}
|
||||||
|
if(back[chan].at(0) >= maxBE) {
|
||||||
|
maxBE = back[chan].at(0);
|
||||||
|
bchan = chan;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
Cross-talk corrections are important when evaluating 'energy' signals from strips/pads.
|
||||||
|
They can cause unexpected behavior when used universally for all EL, ER cases, so we split scenarios in two.
|
||||||
|
- Positions along each strip (frontX) *are not* corrected for crosstalk.
|
||||||
|
- Total F and B energies (frontE, backE) *are*.
|
||||||
|
Sudarsan B, 31 Oct 2024
|
||||||
|
*/
|
||||||
|
|
||||||
|
if(fchan==-1 || bchan==-1) {
|
||||||
|
std::cout << "how" << std::endl;
|
||||||
|
std::cout << "fc " << std::flush; for(auto fc : valid_front_chans) std::cout << fc << " (" << frontL[fc].at(0) << "," << frontR[fc].at(0)<< ") "; std::cout << std::endl;
|
||||||
|
std::cout << "bc " << std::flush; for(auto bc : valid_back_chans) std::cout << bc << " " << back[bc].at(0) << std::flush; std::cout << std::endl;
|
||||||
|
}
|
||||||
|
float Eleft = frontL[fchan].at(0);
|
||||||
|
float Eright = frontR[fchan].at(0);
|
||||||
|
frontEL = Eleft;
|
||||||
|
frontER = Eright;
|
||||||
|
frontX = (Eleft-Eright)/(Eleft+Eright);
|
||||||
|
//frontXmm = (frontX+sx3gs.add[fchan])*sx3gs.stretch[fchan]; //convert to mm
|
||||||
|
|
||||||
|
//frontE = Eleft*fbgains.stripLgains[bchan][fchan] + fbgains.stripLoffsets[bchan][fchan]
|
||||||
|
// + Eright*fbgains.stripRgains[bchan][fchan] + fbgains.stripRoffsets[bchan][fchan];
|
||||||
|
//backE = back[bchan].at(0)*fbgains.padgains[bchan][fchan]+fbgains.padoffsets[bchan][fchan];
|
||||||
|
frontE = Eleft+Eright;
|
||||||
|
backE = maxBE;
|
||||||
|
stripF=fchan;
|
||||||
|
stripB=bchan;
|
||||||
|
|
||||||
|
flags = 0;
|
||||||
|
} else if(valid_front_chans.size()!=0 && valid_back_chans.size()==0) {
|
||||||
|
flags = -10;
|
||||||
|
} else if(valid_front_chans.size()==0 && valid_back_chans.size()!=0) {
|
||||||
|
flags = -20;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef sx3 sx3det;
|
||||||
|
#endif
|
||||||
795
Armory/fsuReader.h
Normal file
795
Armory/fsuReader.h
Normal file
|
|
@ -0,0 +1,795 @@
|
||||||
|
#include "ClassData.h"
|
||||||
|
#include "Hit.h"
|
||||||
|
#include <algorithm>
|
||||||
|
#include <filesystem>
|
||||||
|
|
||||||
|
// #include "AggSeparator.h"
|
||||||
|
|
||||||
|
class FSUReader{
|
||||||
|
|
||||||
|
public:
|
||||||
|
FSUReader();
|
||||||
|
FSUReader(std::string fileName, uInt dataSize = 100, int verbose = 1);
|
||||||
|
FSUReader(std::vector<std::string> fileList, uInt dataSize = 100, int verbose = 1);
|
||||||
|
~FSUReader();
|
||||||
|
|
||||||
|
void OpenFile(std::string fileName, uInt dataSize, int verbose = 1);
|
||||||
|
bool IsOpen() const{return inFile == nullptr ? false : true;}
|
||||||
|
bool IsEndOfFile() const {
|
||||||
|
// printf("%s : %d | %ld |%ld\n", __func__, feof(inFile), ftell(inFile), inFileSize);
|
||||||
|
if(fileList.empty() ) {
|
||||||
|
if( (uLong )ftell(inFile) >= inFileSize){
|
||||||
|
return true;
|
||||||
|
}else{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
if( fileID + 1 == (int) fileList.size() && ((uLong)ftell(inFile) >= inFileSize) ) {
|
||||||
|
return true;
|
||||||
|
}else{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScanNumBlock(int verbose = 1, uShort saveData = 0); // saveData = 0 (no save), 1 (no trace), 2 (with trace);
|
||||||
|
int ReadNextBlock(bool traceON = false, int verbose = 0, uShort saveData = 0); // saveData = 0 (no save), 1 (no trace), 2 (with trace);
|
||||||
|
int ReadBlock(unsigned int ID, int verbose = 0);
|
||||||
|
|
||||||
|
unsigned int GetFilePos() const {return filePos;}
|
||||||
|
unsigned long GetTotNumBlock() const{ return totNumBlock;}
|
||||||
|
std::vector<unsigned int> GetBlockTimestamp() const {return blockTimeStamp;}
|
||||||
|
|
||||||
|
Data * GetData() const{return data;}
|
||||||
|
|
||||||
|
std::string GetFileName() const{return fileName;}
|
||||||
|
int GetDPPType() const{return DPPType;}
|
||||||
|
int GetSN() const{return sn;}
|
||||||
|
int GetTick2ns() const{return tick2ns;}
|
||||||
|
int GetNumCh() const{return numCh;}
|
||||||
|
int GetFileOrder() const{return order;}
|
||||||
|
int GetChMask() const{return chMask;}
|
||||||
|
unsigned long GetFileByteSize() const {return inFileSize;}
|
||||||
|
|
||||||
|
void ClearHitList() { hit.clear();}
|
||||||
|
ulong GetHitListLength() const {return hit.size();}
|
||||||
|
std::vector<Hit> GetHitVector() const {return hit;}
|
||||||
|
void SortHit(int verbose = false);
|
||||||
|
Hit GetHit(int id) const {
|
||||||
|
if( id < 0 ) id = hit.size() + id;
|
||||||
|
return hit[id];
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClearHitCount() {hitCount = 0;}
|
||||||
|
ulong GetHitCount() const{return hitCount;}
|
||||||
|
|
||||||
|
std::vector<Hit> ReadBatch(unsigned int batchSize = 1000000, bool verbose = false); // output the sorted Hit
|
||||||
|
|
||||||
|
// std::string SaveHit(std::vector<Hit> hitList, bool isAppend = false);
|
||||||
|
// std::string SaveHit2NewFile(std::string saveFolder = "./", std::string indexStr = "");
|
||||||
|
// void SortAndSaveTS(unsigned int batchSize = 1000000, bool verbose = false);
|
||||||
|
// off_t GetTSFileSize() const {return tsFileSize;}
|
||||||
|
|
||||||
|
//TODO
|
||||||
|
//void SplitFile(unsigned long hitSizePreFile);
|
||||||
|
|
||||||
|
void PrintHit(ulong numHit = -1, ulong startIndex = 0) {
|
||||||
|
for( ulong i = startIndex; i < std::min(numHit, hitCount); i++){
|
||||||
|
printf("%10zu ", i); hit[i].Print();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void PrintHitListInfo(std::vector<Hit> * hitList, std::string name){
|
||||||
|
size_t n = hitList->size();
|
||||||
|
size_t s = sizeof(Hit);
|
||||||
|
printf("============== %s, size : %zu | %.2f MByte\n", name.c_str(), n, n*s/1024./1024.);
|
||||||
|
if( n > 0 ){
|
||||||
|
printf("t0 : %15llu ns\n", hitList->front().timestamp);
|
||||||
|
printf("t1 : %15llu ns\n", hitList->back().timestamp);
|
||||||
|
printf("dt : %15.3f ms\n", (hitList->back().timestamp - hitList->front().timestamp)/1e6);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void PrintHitListInfo(){
|
||||||
|
size_t n = hit.size();
|
||||||
|
size_t s = sizeof(Hit);
|
||||||
|
printf("============== reader.hit, size : %zu | %.2f MByte\n", n, n*s/1024./1024.);
|
||||||
|
if( n > 0 ){
|
||||||
|
printf("t0 : %15llu ns\n", hit.at(0).timestamp);
|
||||||
|
printf("t1 : %15llu ns\n", hit.back().timestamp);
|
||||||
|
printf("dt : %15.3f ms\n", (hit.back().timestamp - hit.front().timestamp)/1e6);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//void SaveAsCAENCoMPASSFormat();
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
FILE * inFile;
|
||||||
|
Data * data;
|
||||||
|
|
||||||
|
std::string fileName;
|
||||||
|
std::vector<std::string> fileList;
|
||||||
|
short fileID;
|
||||||
|
unsigned long inFileSize;
|
||||||
|
unsigned int filePos;
|
||||||
|
unsigned long totNumBlock;
|
||||||
|
unsigned int blockID;
|
||||||
|
|
||||||
|
bool isDualBlock;
|
||||||
|
|
||||||
|
uShort sn;
|
||||||
|
uShort DPPType;
|
||||||
|
uShort tick2ns;
|
||||||
|
uShort order;
|
||||||
|
uShort chMask;
|
||||||
|
uShort numCh;
|
||||||
|
|
||||||
|
std::vector<unsigned int> blockPos;
|
||||||
|
std::vector<unsigned int > blockTimeStamp;
|
||||||
|
|
||||||
|
unsigned long hitCount;
|
||||||
|
|
||||||
|
std::vector<Hit> hit;
|
||||||
|
|
||||||
|
unsigned int word[1]; /// 4 byte
|
||||||
|
size_t dummy;
|
||||||
|
char * buffer;
|
||||||
|
|
||||||
|
off_t tsFileSize;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
inline FSUReader::~FSUReader(){
|
||||||
|
delete data;
|
||||||
|
|
||||||
|
if( inFile ) fclose(inFile);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
inline FSUReader::FSUReader(){
|
||||||
|
inFile = nullptr;
|
||||||
|
data = nullptr;
|
||||||
|
|
||||||
|
blockPos.clear();
|
||||||
|
blockTimeStamp.clear();
|
||||||
|
hit.clear();
|
||||||
|
|
||||||
|
fileList.clear();
|
||||||
|
fileID = -1;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
inline FSUReader::FSUReader(std::string fileName, uInt dataSize, int verbose){
|
||||||
|
inFile = nullptr;
|
||||||
|
data = nullptr;
|
||||||
|
|
||||||
|
blockPos.clear();
|
||||||
|
blockTimeStamp.clear();
|
||||||
|
hit.clear();
|
||||||
|
|
||||||
|
fileList.clear();
|
||||||
|
fileID = -1;
|
||||||
|
OpenFile(fileName, dataSize, verbose);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline FSUReader::FSUReader(std::vector<std::string> fileList, uInt dataSize, int verbose){
|
||||||
|
inFile = nullptr;
|
||||||
|
data = nullptr;
|
||||||
|
|
||||||
|
blockPos.clear();
|
||||||
|
blockTimeStamp.clear();
|
||||||
|
hit.clear();
|
||||||
|
//The files are the same DPPType and sn
|
||||||
|
this->fileList = fileList;
|
||||||
|
fileID = 0;
|
||||||
|
OpenFile(fileList[fileID], dataSize, verbose);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void FSUReader::OpenFile(std::string fileName, uInt dataSize, int verbose){
|
||||||
|
|
||||||
|
/// File format must be YYY...Y_runXXX_AAA_BBB_TT_CCC.fsu
|
||||||
|
/// YYY...Y = prefix
|
||||||
|
/// XXX = runID, 3 digits
|
||||||
|
/// AAA = board Serial Number, 3 digits
|
||||||
|
/// BBB = DPPtype, 3 digits
|
||||||
|
/// TT = tick2ns, any digits
|
||||||
|
/// CCC = over size index, 3 digits
|
||||||
|
|
||||||
|
if( inFile != nullptr ) fclose(inFile);
|
||||||
|
|
||||||
|
inFile = fopen(fileName.c_str(), "r");
|
||||||
|
|
||||||
|
if( inFile == NULL ){
|
||||||
|
printf("FSUReader::Cannot open file : %s \n", fileName.c_str());
|
||||||
|
this->fileName = "";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this->fileName = fileName;
|
||||||
|
|
||||||
|
fseek(inFile, 0L, SEEK_END);
|
||||||
|
inFileSize = ftell(inFile);
|
||||||
|
if(verbose) printf("%s | file size : %ld Byte = %.2f MB\n", fileName.c_str() , inFileSize, inFileSize/1024./1024.);
|
||||||
|
fseek(inFile, 0L, SEEK_SET);
|
||||||
|
filePos = 0;
|
||||||
|
|
||||||
|
if( fileID > 0 ) return;
|
||||||
|
|
||||||
|
totNumBlock = 0;
|
||||||
|
blockID = 0;
|
||||||
|
blockPos.clear();
|
||||||
|
blockTimeStamp.clear();
|
||||||
|
|
||||||
|
hitCount = 0;
|
||||||
|
hit.clear();
|
||||||
|
|
||||||
|
//check is the file is *.fsu or *.fsu.X
|
||||||
|
size_t found = fileName.find_last_of('.');
|
||||||
|
std::string ext = fileName.substr(found + 1);
|
||||||
|
|
||||||
|
if( ext.find("fsu") != std::string::npos ) {
|
||||||
|
if(verbose > 1) printf("It is an raw data *.fsu format\n");
|
||||||
|
isDualBlock = false;
|
||||||
|
chMask = -1;
|
||||||
|
}else{
|
||||||
|
chMask = atoi(ext.c_str());
|
||||||
|
isDualBlock = true;
|
||||||
|
if(verbose > 1) printf("It is a splitted dual block data *.fsu.X format, dual channel mask : %d \n", chMask);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string fileNameNoExt;
|
||||||
|
found = fileName.find_last_of(".fsu");
|
||||||
|
size_t found2 = fileName.find_last_of('/');
|
||||||
|
if( found2 == std::string::npos ){
|
||||||
|
fileNameNoExt = fileName.substr(0, found-4);
|
||||||
|
}else{
|
||||||
|
fileNameNoExt = fileName.substr(found2+1, found-4);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Split the string by underscores
|
||||||
|
std::istringstream iss(fileNameNoExt);
|
||||||
|
std::vector<std::string> tokens;
|
||||||
|
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());
|
||||||
|
|
||||||
|
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( DPPType == 0 ){
|
||||||
|
fclose(inFile);
|
||||||
|
inFile = nullptr;
|
||||||
|
printf("Cannot find DPPType in the filename. Abort.");
|
||||||
|
return ;
|
||||||
|
}
|
||||||
|
|
||||||
|
numCh = (DPPType == DPPTypeCode::DPP_QDC_CODE ? 64 : 16);
|
||||||
|
|
||||||
|
data = new Data(numCh, dataSize);
|
||||||
|
data->tick2ns = tick2ns;
|
||||||
|
data->boardSN = sn;
|
||||||
|
data->DPPType = DPPType;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
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");
|
||||||
|
fileID ++;
|
||||||
|
OpenFile(fileList[fileID], data->GetDataSize(), 1 );
|
||||||
|
}else{
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dummy = fread(word, 4, 1, inFile);
|
||||||
|
fseek(inFile, -4, SEEK_CUR);
|
||||||
|
|
||||||
|
if( dummy != 1) {
|
||||||
|
printf("fread error, should read 4 bytes, but read %ld x 4 byte, file pos: %ld / %ld byte\n",
|
||||||
|
dummy, ftell(inFile), inFileSize);
|
||||||
|
return -10;
|
||||||
|
}
|
||||||
|
short header = ((word[0] >> 28 ) & 0xF);
|
||||||
|
|
||||||
|
Hit temp;
|
||||||
|
|
||||||
|
if( header == 0xA ) { ///normal header
|
||||||
|
|
||||||
|
unsigned int aggSize = (word[0] & 0x0FFFFFFF) * 4; ///byte
|
||||||
|
if( aggSize > inFileSize - ftell(inFile)) aggSize = inFileSize - ftell(inFile);
|
||||||
|
buffer = new char[aggSize];
|
||||||
|
dummy = fread(buffer, aggSize, 1, inFile);
|
||||||
|
filePos = ftell(inFile);
|
||||||
|
if( dummy != 1) {
|
||||||
|
printf("fread error, should read %d bytes, but read %ld x %d byte, file pos: %ld / %ld byte \n",
|
||||||
|
aggSize, dummy, aggSize, ftell(inFile), inFileSize);
|
||||||
|
return -30;
|
||||||
|
}
|
||||||
|
|
||||||
|
data->DecodeBuffer(buffer, aggSize, !traceON, verbose); // data will own the buffer
|
||||||
|
//printf(" word Index = %u | filePos : %u | ", data->GetWordIndex(), filePos);
|
||||||
|
|
||||||
|
}else if( (header & 0xF ) == 0x8 ) { /// dual channel header
|
||||||
|
|
||||||
|
unsigned int dualSize = (word[0] & 0x7FFFFFFF) * 4; ///byte
|
||||||
|
buffer = new char[dualSize];
|
||||||
|
dummy = fread(buffer, dualSize, 1, inFile);
|
||||||
|
filePos = ftell(inFile);
|
||||||
|
|
||||||
|
data->buffer = buffer;
|
||||||
|
data->DecodeDualBlock(buffer, dualSize, DPPType, chMask, !traceON, verbose);
|
||||||
|
|
||||||
|
}else{
|
||||||
|
printf("incorrect header.\n trminate.");
|
||||||
|
return -20;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int eventCout = 0;
|
||||||
|
|
||||||
|
for( int ch = 0; ch < data->GetNChannel(); ch++){
|
||||||
|
if( data->NumEventsDecoded[ch] == 0 ) continue;
|
||||||
|
|
||||||
|
hitCount += data->NumEventsDecoded[ch];
|
||||||
|
eventCout += data->NumEventsDecoded[ch];
|
||||||
|
|
||||||
|
if( saveData ){
|
||||||
|
int start = data->GetDataIndex(ch) - data->NumEventsDecoded[ch] + 1;
|
||||||
|
if( start < 0 ) start = start + data->GetDataSize();
|
||||||
|
|
||||||
|
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);
|
||||||
|
temp.fineTime = data->GetFineTime(ch, k);
|
||||||
|
temp.pileUp = data->GetPileUp(ch, k);
|
||||||
|
if( saveData > 1 ) {
|
||||||
|
temp.traceLength = data->Waveform1[ch][k].size();
|
||||||
|
temp.trace = data->Waveform1[ch][k];
|
||||||
|
}else{
|
||||||
|
temp.traceLength = 0;
|
||||||
|
if( temp.trace.size() > 0 ) temp.trace.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
hit.push_back(temp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
data->ClearTriggerRate();
|
||||||
|
data->ClearNumEventsDecoded();
|
||||||
|
data->ClearBuffer(); // this will clear the buffer.
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline int FSUReader::ReadBlock(unsigned int ID, int verbose){
|
||||||
|
if( totNumBlock == 0 )return -1;
|
||||||
|
if( ID >= totNumBlock )return -1;
|
||||||
|
|
||||||
|
data->ClearData();
|
||||||
|
|
||||||
|
fseek( inFile, 0L, SEEK_SET);
|
||||||
|
|
||||||
|
if( verbose ) printf("Block index: %u, File Pos: %u byte\n", ID, blockPos[ID]);
|
||||||
|
|
||||||
|
fseek(inFile, blockPos[ID], SEEK_CUR);
|
||||||
|
filePos = blockPos[ID];
|
||||||
|
blockID = ID;
|
||||||
|
return ReadNextBlock(false, verbose, false);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void FSUReader::SortHit(int verbose){
|
||||||
|
if( verbose) printf("\nQuick Sort hit array according to time...");
|
||||||
|
std::sort(hit.begin(), hit.end(), [](const Hit& a, const Hit& b) {
|
||||||
|
return a.timestamp < b.timestamp;
|
||||||
|
});
|
||||||
|
if( verbose) printf(".......done.\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void FSUReader::ScanNumBlock(int verbose, uShort saveData){
|
||||||
|
if( inFile == nullptr ) return;
|
||||||
|
if( feof(inFile) ) return;
|
||||||
|
|
||||||
|
blockID = 0;
|
||||||
|
blockPos.push_back(0);
|
||||||
|
|
||||||
|
data->ClearData();
|
||||||
|
rewind(inFile);
|
||||||
|
filePos = 0;
|
||||||
|
|
||||||
|
bool isTraceOn = saveData < 2 ? false : true;
|
||||||
|
|
||||||
|
while( ReadNextBlock(isTraceOn, verbose - 1, saveData) == 0 ){
|
||||||
|
blockPos.push_back(filePos);
|
||||||
|
blockTimeStamp.push_back(data->aggTime);
|
||||||
|
blockID ++;
|
||||||
|
if(verbose && blockID % 10000 == 0) printf("%u, %.2f%% %u/%lu\n\033[A\r", blockID, filePos*100./inFileSize, filePos, inFileSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
totNumBlock = blockID;
|
||||||
|
if(verbose) {
|
||||||
|
printf("\nScan complete: number of data Block : %lu\n", totNumBlock);
|
||||||
|
printf( " number of hit : %lu", hitCount);
|
||||||
|
if( hitCount > 1e6 ) printf(" = %.3f million", hitCount/1e6);
|
||||||
|
printf("\n");
|
||||||
|
if( saveData )printf( " size of the hit array : %lu\n", hit.size());
|
||||||
|
|
||||||
|
if( saveData ){
|
||||||
|
size_t sizeT = sizeof(hit[0]) * hit.size();
|
||||||
|
printf("size of hit array : %lu byte = %.2f kByte, = %.2f MByte\n", sizeT, sizeT/1024., sizeT/1024./1024.);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( fileList.size() > 0 ){
|
||||||
|
fileID = 0;
|
||||||
|
OpenFile(fileList[fileID], data->GetDataSize(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
rewind(inFile);
|
||||||
|
blockID = 0;
|
||||||
|
filePos = 0;
|
||||||
|
|
||||||
|
//check is the hitCount == hit.size();
|
||||||
|
if( saveData ){
|
||||||
|
if( hitCount != hit.size()){
|
||||||
|
printf("!!!!!! the Data::dataSize is not big enough. !!!!!!!!!!!!!!!\n");
|
||||||
|
}else{
|
||||||
|
SortHit(verbose+1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::vector<Hit> FSUReader::ReadBatch(unsigned int batchSize, bool verbose){
|
||||||
|
|
||||||
|
// printf("%s sn:%d. filePos : %lu\n", __func__, sn, ftell(inFile));
|
||||||
|
|
||||||
|
std::vector<Hit> hitList_A;
|
||||||
|
if( IsEndOfFile() ) {
|
||||||
|
hitList_A = hit;
|
||||||
|
hit.clear();
|
||||||
|
return hitList_A;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( hit.size() == 0 ){
|
||||||
|
int res = 0;
|
||||||
|
do{
|
||||||
|
res = ReadNextBlock(true, 0, 3);
|
||||||
|
}while ( hit.size() < batchSize && res == 0);
|
||||||
|
SortHit();
|
||||||
|
uLong t0_B = hit.at(0).timestamp;
|
||||||
|
uLong t1_B = hit.back().timestamp;
|
||||||
|
if( verbose ) {
|
||||||
|
printf(" hit in memeory : %7zu | %u | %lu \n", hit.size(), filePos, inFileSize);
|
||||||
|
printf("t0 : %15lu ns\n", t0_B);
|
||||||
|
printf("t1 : %15lu ns\n", t1_B);
|
||||||
|
printf("dt : %15.3f ms\n", (t1_B - t0_B)/1e6);
|
||||||
|
}
|
||||||
|
|
||||||
|
hitList_A = hit;
|
||||||
|
hit.clear();
|
||||||
|
|
||||||
|
}else{
|
||||||
|
|
||||||
|
hitList_A = hit;
|
||||||
|
hit.clear();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if( IsEndOfFile() ) return hitList_A; // when file finished for 1st batch read
|
||||||
|
|
||||||
|
int res = 0;
|
||||||
|
do{
|
||||||
|
res = ReadNextBlock(true, 0, 3);
|
||||||
|
}while ( hit.size() < batchSize && res == 0);
|
||||||
|
SortHit();
|
||||||
|
uLong t0_B = hit.at(0).timestamp;
|
||||||
|
uLong t1_B = hit.back().timestamp;
|
||||||
|
|
||||||
|
if( verbose ) {
|
||||||
|
printf(" hit in memeory : %7zu | %u | %lu \n", hit.size(), filePos, inFileSize);
|
||||||
|
printf("t0 : %15lu\n", t0_B);
|
||||||
|
printf("t1 : %15lu\n", t1_B);
|
||||||
|
printf("dt : %15.3f ms\n", (t1_B - t0_B)/1e6);
|
||||||
|
}
|
||||||
|
|
||||||
|
uLong t0_A = hitList_A.at(0).timestamp;
|
||||||
|
uLong t1_A = hitList_A.back().timestamp;
|
||||||
|
ulong ID_A = 0;
|
||||||
|
ulong ID_B = 0;
|
||||||
|
|
||||||
|
if( t0_A >= t0_B) {
|
||||||
|
printf("\033[0;31m!!!!!!!!!!!!!!!!! %s | Need to increase the batch size. \033[0m\n", __func__);
|
||||||
|
return std::vector<Hit> ();
|
||||||
|
}
|
||||||
|
|
||||||
|
if( t1_A > t0_B) { // need to sort between two hitList
|
||||||
|
|
||||||
|
if( verbose ) {
|
||||||
|
printf("############# need to sort \n");
|
||||||
|
printf("=========== sume of A + B : %zu \n", hitList_A.size() + hit.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<Hit> hitTemp;
|
||||||
|
|
||||||
|
// find the hit that is >= t0_B, save them to hitTemp
|
||||||
|
for( size_t j = 0; j < hitList_A.size() ; j++){
|
||||||
|
if( hitList_A[j].timestamp < t0_B ) continue;;
|
||||||
|
if( ID_A == 0 ) ID_A = j;
|
||||||
|
hitTemp.push_back(hitList_A[j]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove hitList_A element that is >= t0_B
|
||||||
|
hitList_A.erase(hitList_A.begin() + ID_A, hitList_A.end() );
|
||||||
|
|
||||||
|
// find the hit that is <= t1_A, save them to hitTemp
|
||||||
|
for( size_t j = 0; j < hit.size(); j++){
|
||||||
|
if( hit[j].timestamp > t1_A ) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
hitTemp.push_back(hit[j]);
|
||||||
|
ID_B = j + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// remove hit elements that is <= t1_A
|
||||||
|
hit.erase(hit.begin(), hit.begin() + ID_B );
|
||||||
|
|
||||||
|
// sort hitTemp
|
||||||
|
std::sort(hitTemp.begin(), hitTemp.end(), [](const Hit& a, const Hit& b) {
|
||||||
|
return a.timestamp < b.timestamp;
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
if( verbose ) {
|
||||||
|
printf("----------------- ID_A : %lu, Drop\n", ID_A);
|
||||||
|
printf("----------------- ID_B : %lu, Drop\n", ID_B);
|
||||||
|
PrintHitListInfo(&hitList_A, "hitList_A");
|
||||||
|
PrintHitListInfo(&hitTemp, "hitTemp");
|
||||||
|
PrintHitListInfo();
|
||||||
|
printf("=========== sume of A + B + Temp : %zu \n", hitList_A.size() + hit.size() + hitTemp.size());
|
||||||
|
printf("----------------- refill hitList_A \n");
|
||||||
|
}
|
||||||
|
|
||||||
|
for( size_t j = 0; j < hitTemp.size(); j++){
|
||||||
|
hitList_A.push_back(hitTemp[j]);
|
||||||
|
}
|
||||||
|
hitTemp.clear();
|
||||||
|
|
||||||
|
if( verbose ) {
|
||||||
|
PrintHitListInfo(&hitList_A, "hitList_A");
|
||||||
|
PrintHitListInfo();
|
||||||
|
printf("=========== sume of A + B : %zu \n", hitList_A.size() + hit.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return hitList_A;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
inline void FSUReader::SortAndSaveTS(unsigned int batchSize, bool verbose){
|
||||||
|
|
||||||
|
int count = 0;
|
||||||
|
std::vector<Hit> hitList_A ;
|
||||||
|
|
||||||
|
do{
|
||||||
|
|
||||||
|
if( verbose ) printf("***************************************************\n");
|
||||||
|
|
||||||
|
int res = 0;
|
||||||
|
do{
|
||||||
|
res = ReadNextBlock(true, 0, 3);
|
||||||
|
}while ( hit.size() < batchSize && res == 0);
|
||||||
|
|
||||||
|
SortHit();
|
||||||
|
uLong t0_B = hit.at(0).timestamp;
|
||||||
|
uLong t1_B = hit.back().timestamp;
|
||||||
|
|
||||||
|
if( verbose ) {
|
||||||
|
printf(" hit in memeory : %7zu | %u | %lu \n", hit.size(), filePos, inFileSize);
|
||||||
|
printf("t0 : %15lu\n", t0_B);
|
||||||
|
printf("t1 : %15lu\n", t1_B);
|
||||||
|
}
|
||||||
|
|
||||||
|
if( count == 0 ) {
|
||||||
|
hitList_A = hit; // copy hit
|
||||||
|
}else{
|
||||||
|
|
||||||
|
uLong t0_A = hitList_A.at(0).timestamp;
|
||||||
|
uLong t1_A = hitList_A.back().timestamp;
|
||||||
|
ulong ID_A = 0;
|
||||||
|
ulong ID_B = 0;
|
||||||
|
|
||||||
|
if( t0_A > t0_B) {
|
||||||
|
printf("Need to increase the batch size. \n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( t1_A > t0_B) { // need to sort between two hitList
|
||||||
|
|
||||||
|
if( verbose ) {
|
||||||
|
printf("############# need to sort \n");
|
||||||
|
printf("=========== sume of A + B : %zu \n", hitList_A.size() + hit.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<Hit> hitTemp;
|
||||||
|
|
||||||
|
for( size_t j = 0; j < hitList_A.size() ; j++){
|
||||||
|
if( hitList_A[j].timestamp < t0_B ) continue;
|
||||||
|
if( ID_A == 0 ) ID_A = j;
|
||||||
|
hitTemp.push_back(hitList_A[j]);
|
||||||
|
}
|
||||||
|
|
||||||
|
hitList_A.erase(hitList_A.begin() + ID_A, hitList_A.end() );
|
||||||
|
if( verbose ) {
|
||||||
|
printf("----------------- ID_A : %lu, Drop\n", ID_A);
|
||||||
|
PrintHitListInfo(hitList_A, "hitList_A");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for( size_t j = 0; j < hit.size(); j++){
|
||||||
|
if( hit[j].timestamp > t1_A ) {
|
||||||
|
ID_B = j;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
hitTemp.push_back(hit[j]);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::sort(hitTemp.begin(), hitTemp.end(), [](const Hit& a, const Hit& b) {
|
||||||
|
return a.timestamp < b.timestamp;
|
||||||
|
});
|
||||||
|
|
||||||
|
hit.erase(hit.begin(), hit.begin() + ID_B );
|
||||||
|
|
||||||
|
if( verbose ) {
|
||||||
|
PrintHitListInfo(hitTemp, "hitTemp");
|
||||||
|
printf("----------------- ID_B : %lu, Drop\n", ID_B);
|
||||||
|
PrintHitListInfo(hit, "hit");
|
||||||
|
printf("=========== sume of A + B + Temp : %zu \n", hitList_A.size() + hit.size() + hitTemp.size());
|
||||||
|
printf("----------------- refill hitList_A \n");
|
||||||
|
}
|
||||||
|
ulong ID_Temp = 0;
|
||||||
|
for( size_t j = 0; j < hitTemp.size(); j++){
|
||||||
|
hitList_A.push_back(hitTemp[j]);
|
||||||
|
if( hitList_A.size() >= batchSize ) {
|
||||||
|
ID_Temp = j+1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
hitTemp.erase(hitTemp.begin(), hitTemp.begin() + ID_Temp );
|
||||||
|
for( size_t j = 0 ; j < hit.size(); j ++){
|
||||||
|
hitTemp.push_back(hit[j]);
|
||||||
|
}
|
||||||
|
SaveHit(hitList_A, count <= 1 ? false : true);
|
||||||
|
|
||||||
|
if( verbose ) {
|
||||||
|
PrintHitListInfo(hitList_A, "hitList_A");
|
||||||
|
PrintHitListInfo(hitTemp, "hitTemp");
|
||||||
|
printf("----------------- replace hitList_A by hitTemp \n");
|
||||||
|
}
|
||||||
|
|
||||||
|
hitList_A.clear();
|
||||||
|
hitList_A = hitTemp;
|
||||||
|
hit.clear();
|
||||||
|
|
||||||
|
if( verbose ) {
|
||||||
|
PrintHitListInfo(hitList_A, "hitList_A");
|
||||||
|
printf("===========================================\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
}else{ // save hitList_A, replace hitList_A
|
||||||
|
|
||||||
|
SaveHit(hitList_A, count <= 1? false : true);
|
||||||
|
hitList_A.clear();
|
||||||
|
hitList_A = hit;
|
||||||
|
if( verbose ) PrintHitListInfo(hitList_A, "hitList_A");
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ClearHitList();
|
||||||
|
count ++;
|
||||||
|
}while(filePos < inFileSize);
|
||||||
|
|
||||||
|
SaveHit(hitList_A, count <= 1 ? false : true);
|
||||||
|
|
||||||
|
printf("================= finished.\n");
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
inline std::string FSUReader::SaveHit(std::vector<Hit> hitList, bool isAppend){
|
||||||
|
|
||||||
|
std::string outFileName;
|
||||||
|
if( fileList.empty() ) {
|
||||||
|
outFileName = fileName + ".ts" ;
|
||||||
|
}else{
|
||||||
|
outFileName = fileList[0] + ".ts" ;
|
||||||
|
}
|
||||||
|
uint64_t hitSize = hitList.size();
|
||||||
|
|
||||||
|
FILE * outFile ;
|
||||||
|
if( isAppend ) {
|
||||||
|
outFile = fopen(outFileName.c_str(), "rb+"); //read/write bineary
|
||||||
|
|
||||||
|
rewind(outFile);
|
||||||
|
fseek( outFile, 4, SEEK_CUR);
|
||||||
|
uint64_t org_hitSize;
|
||||||
|
fread(&org_hitSize, 8, 1, outFile);
|
||||||
|
|
||||||
|
rewind(outFile);
|
||||||
|
fseek( outFile, 4, SEEK_CUR);
|
||||||
|
|
||||||
|
org_hitSize += hitSize;
|
||||||
|
|
||||||
|
fwrite(&org_hitSize, 8, 1, outFile);
|
||||||
|
fseek(outFile, 0, SEEK_END);
|
||||||
|
|
||||||
|
}else{
|
||||||
|
outFile = fopen(outFileName.c_str(), "wb"); //overwrite binary
|
||||||
|
uint32_t header = 0xAA000000;
|
||||||
|
header += sn;
|
||||||
|
fwrite( &header, 4, 1, outFile );
|
||||||
|
fwrite( &hitSize, 8, 1, outFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for( ulong i = 0; i < hitSize; i++){
|
||||||
|
|
||||||
|
if( i% 10000 == 0 ) printf("Saving %lu/%lu Hit (%.2f%%)\n\033[A\r", i, hitSize, i*100./hitSize);
|
||||||
|
|
||||||
|
uint16_t flag = hitList[i].ch + (hitList[i].pileUp << 8) ;
|
||||||
|
|
||||||
|
if( DPPType == DPPTypeCode::DPP_PSD_CODE ) flag += ( 1 << 15);
|
||||||
|
if( hitList[i].traceLength > 0 ) flag += (1 << 14);
|
||||||
|
|
||||||
|
// fwrite( &(hit[i].ch), 1, 1, outFile);
|
||||||
|
fwrite( &flag, 2, 1, outFile);
|
||||||
|
fwrite( &(hitList[i].energy), 2, 1, outFile);
|
||||||
|
if( DPPType == DPPTypeCode::DPP_PSD_CODE ) fwrite( &(hitList[i].energy2), 2, 1, outFile);
|
||||||
|
fwrite( &(hitList[i].timestamp), 6, 1, outFile);
|
||||||
|
fwrite( &(hitList[i].fineTime), 2, 1, outFile);
|
||||||
|
if( hitList[i].traceLength > 0 ) fwrite( &(hitList[i].traceLength), 2, 1, outFile);
|
||||||
|
|
||||||
|
for( uShort j = 0; j < hitList[i].traceLength; j++){
|
||||||
|
fwrite( &(hitList[i].trace[j]), 2, 1, outFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
off_t tsFileSize = ftello(outFile); // unsigned int = Max ~4GB
|
||||||
|
fclose(outFile);
|
||||||
|
|
||||||
|
printf("Saved to %s, size: ", outFileName.c_str());
|
||||||
|
if( tsFileSize < 1024 ) {
|
||||||
|
printf(" %ld Byte", tsFileSize);
|
||||||
|
}else if( tsFileSize < 1024*1024 ) {
|
||||||
|
printf(" %.2f kB", tsFileSize/1024.);
|
||||||
|
}else if( tsFileSize < 1024*1024*1024){
|
||||||
|
printf(" %.2f MB", tsFileSize/1024./1024.);
|
||||||
|
}else{
|
||||||
|
printf(" %.2f GB", tsFileSize/1024./1024./1024.);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
return outFileName;
|
||||||
|
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
56
Armory/macro.h
Normal file
56
Armory/macro.h
Normal file
|
|
@ -0,0 +1,56 @@
|
||||||
|
#ifndef MACRO_H
|
||||||
|
#define MACRO_H
|
||||||
|
|
||||||
|
#define MaxNPorts 4 //for optical link
|
||||||
|
#define MaxNBoards 4 //for both optical link and usb
|
||||||
|
|
||||||
|
#define MaxNDigitizer MaxNPorts * MaxNBoards
|
||||||
|
|
||||||
|
#define MaxRegChannel 16
|
||||||
|
#define MaxNChannels 64
|
||||||
|
#define MaxRecordLength 0x3fff * 8
|
||||||
|
#define MaxSaveFileSize 1024 * 1024 * 1024 * 2
|
||||||
|
|
||||||
|
#define MaxDisplayTraceTimeLength 20000 //ns
|
||||||
|
#define ScopeUpdateMiliSec 200 // msec
|
||||||
|
#define MaxNumberOfTrace 5 // in an event
|
||||||
|
|
||||||
|
#define SETTINGSIZE 2048
|
||||||
|
|
||||||
|
#define DAQLockFile "DAQLock.dat"
|
||||||
|
#define PIDFile "pid.dat"
|
||||||
|
|
||||||
|
#include <sys/time.h> /** struct timeval, select() */
|
||||||
|
|
||||||
|
inline unsigned int getTime_us(){
|
||||||
|
unsigned int time_us;
|
||||||
|
struct timeval t1;
|
||||||
|
struct timezone tz;
|
||||||
|
gettimeofday(&t1, &tz);
|
||||||
|
time_us = (t1.tv_sec) * 1000 * 1000 + t1.tv_usec;
|
||||||
|
return time_us;
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <chrono>
|
||||||
|
inline unsigned long long getTime_ns(){
|
||||||
|
std::chrono::high_resolution_clock::time_point currentTime = std::chrono::high_resolution_clock::now();
|
||||||
|
std::chrono::nanoseconds nanoseconds = std::chrono::duration_cast<std::chrono::nanoseconds>(currentTime.time_since_epoch());
|
||||||
|
return nanoseconds.count();
|
||||||
|
}
|
||||||
|
|
||||||
|
typedef unsigned short uShort;
|
||||||
|
typedef unsigned int uInt;
|
||||||
|
typedef unsigned long uLong;
|
||||||
|
typedef unsigned long long ullong;
|
||||||
|
|
||||||
|
#define DebugMode 0 //process check, when 1, print out all function call
|
||||||
|
|
||||||
|
// if DebugMode is 1, define DebugPrint() to be printf(), else, DebugPrint() define nothing
|
||||||
|
#if DebugMode
|
||||||
|
#define DebugPrint(fmt, ...) printf(fmt "::%s\n",##__VA_ARGS__, __func__);
|
||||||
|
#else
|
||||||
|
#define DebugPrint(fmt, ...)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
||||||
6
BatchProcess.sh
Normal file
6
BatchProcess.sh
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
#!/bin/bash
|
||||||
|
#parallel -j 6 echo ./ProcessRun.sh {1} 2000 0 ::: {020..400}
|
||||||
|
|
||||||
|
#parallel --results log/log_{}.txt --ctag -j 6 ./ProcessRun.sh {1} 2000 0 ::: {020..400} # for 17F
|
||||||
|
|
||||||
|
parallel --results log/log_{}.txt --ctag -j 6 ./ProcessRun.sh {1} 2000 0 ::: {001..021}
|
||||||
270
Calibration.C
Normal file
270
Calibration.C
Normal file
|
|
@ -0,0 +1,270 @@
|
||||||
|
|
||||||
|
#define Calibration_cxx
|
||||||
|
|
||||||
|
#include <TH2.h>
|
||||||
|
#include <TF1.h>
|
||||||
|
#include <TStyle.h>
|
||||||
|
#include <TCanvas.h>
|
||||||
|
#include <TMath.h>
|
||||||
|
#include <TCutG.h>
|
||||||
|
#include <fstream>
|
||||||
|
#include <utility>
|
||||||
|
#include <algorithm>
|
||||||
|
#include "Armory/HistPlotter.h"
|
||||||
|
#include "TVector3.h"
|
||||||
|
#include "Calibration.h"
|
||||||
|
|
||||||
|
TH2F *hQQQFVB;
|
||||||
|
HistPlotter *plotter;
|
||||||
|
int padID = 0;
|
||||||
|
|
||||||
|
TCutG *cut;
|
||||||
|
std::map<std::tuple<int, int, int>, std::vector<std::pair<double, double>>> dataPoints;
|
||||||
|
|
||||||
|
bool qqqEcut = false;
|
||||||
|
|
||||||
|
// Gain Arrays
|
||||||
|
const int MAX_QQQ = 4;
|
||||||
|
const int MAX_RING = 16;
|
||||||
|
const int MAX_WEDGE = 16;
|
||||||
|
double qqqwGain[MAX_QQQ][MAX_RING][MAX_WEDGE] = {{{0}}};
|
||||||
|
// double qqqrGain[MAX_QQQ][MAX_RING][MAX_WEDGE] = {{{0}}};
|
||||||
|
bool qqqwGainValid[MAX_QQQ][MAX_RING][MAX_WEDGE] = {{{false}}};
|
||||||
|
// bool qqqrGainValid[MAX_QQQ][MAX_RING][MAX_WEDGE] = {{{false}}};
|
||||||
|
|
||||||
|
void Calibration::Begin(TTree * /*tree*/)
|
||||||
|
{
|
||||||
|
plotter = new HistPlotter("Calib.root", "TFILE");
|
||||||
|
// ----------------------- Load QQQ Gains
|
||||||
|
{
|
||||||
|
std::string filename = "qqq_GainMatch.txt";
|
||||||
|
std::ifstream infile(filename);
|
||||||
|
if (!infile.is_open())
|
||||||
|
{
|
||||||
|
std::cerr << "Error opening " << filename << "!" << std::endl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int det, ring, wedge;
|
||||||
|
double gainw, gainr;
|
||||||
|
while (infile >> det >> ring >> wedge >> gainw >> gainr)
|
||||||
|
{
|
||||||
|
qqqwGain[det][ring][wedge] = gainw;
|
||||||
|
// qqqrGain[det][ring][wedge] = gainr;
|
||||||
|
qqqwGainValid[det][ring][wedge] = (gainw > 0);
|
||||||
|
// qqqrGainValid[det][ring][wedge] = (gainr > 0);
|
||||||
|
}
|
||||||
|
infile.close();
|
||||||
|
std::cout << "Loaded QQQ gains from " << filename << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int det = 0; det < MAX_QQQ; det++)
|
||||||
|
{
|
||||||
|
for (int ring = 0; ring < MAX_RING; ring++)
|
||||||
|
{
|
||||||
|
for (int wedge = 0; wedge < MAX_WEDGE; wedge++)
|
||||||
|
{
|
||||||
|
TString hname = Form("hCal_qqq%d_ring%d_wedge%d", det, ring, wedge);
|
||||||
|
TString htitle = Form("QQQ det%d ring%d wedge%d; Energy (arb); Counts", det, ring, wedge);
|
||||||
|
// hQQQSpectra[det][ring][wedge] = new TH1F(hname, htitle, 4000, 0, 16000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Bool_t Calibration::Process(Long64_t entry)
|
||||||
|
{
|
||||||
|
b_qqqMulti->GetEntry(entry);
|
||||||
|
b_qqqID->GetEntry(entry);
|
||||||
|
b_qqqCh->GetEntry(entry);
|
||||||
|
b_qqqE->GetEntry(entry);
|
||||||
|
b_qqqT->GetEntry(entry);
|
||||||
|
|
||||||
|
qqq.CalIndex();
|
||||||
|
|
||||||
|
for (int i = 0; i < qqq.multi; i++)
|
||||||
|
{
|
||||||
|
for (int j = i + 1; j < qqq.multi; j++)
|
||||||
|
{
|
||||||
|
if (qqq.e[i] > 100)
|
||||||
|
qqqEcut = true;
|
||||||
|
if (qqq.id[i] == qqq.id[j])
|
||||||
|
{
|
||||||
|
int chWedge = -1;
|
||||||
|
int chRing = -1;
|
||||||
|
float eWedgeRaw = 0.0;
|
||||||
|
float eWedge = 0.0;
|
||||||
|
float eRingRaw = 0.0;
|
||||||
|
float eRing = 0.0;
|
||||||
|
if (qqq.ch[i] < 16 && qqq.ch[j] >= 16 && /*qqqrGainValid[qqq.id[i]][qqq.ch[i]][qqq.ch[j] - 16] &&*/ qqqwGainValid[qqq.id[i]][qqq.ch[i]][qqq.ch[j] - 16])
|
||||||
|
{
|
||||||
|
chWedge = qqq.ch[i];
|
||||||
|
eWedgeRaw = qqq.e[i];
|
||||||
|
eWedge = qqq.e[i] * qqqwGain[qqq.id[i]][qqq.ch[i]][qqq.ch[j] - 16];
|
||||||
|
// printf("Wedge E: %.2f Gain: %.4f \n", eWedge, qqqGain[qqq.id[i]][qqq.ch[i]][qqq.ch[j] - 16]);
|
||||||
|
chRing = qqq.ch[j] - 16;
|
||||||
|
eRingRaw = qqq.e[j];
|
||||||
|
eRing = qqq.e[j];// * qqqrGain[qqq.id[j]][qqq.ch[j]][qqq.ch[i] - 16];
|
||||||
|
}
|
||||||
|
else if (qqq.ch[j] < 16 && qqq.ch[i] >= 16 && /*qqqrGainValid[qqq.id[j]][qqq.ch[j]][qqq.ch[i] - 16] &&*/ qqqwGainValid[qqq.id[j]][qqq.ch[j]][qqq.ch[i] - 16])
|
||||||
|
{
|
||||||
|
chWedge = qqq.ch[j];
|
||||||
|
eWedge = qqq.e[j] * qqqwGain[qqq.id[j]][qqq.ch[j]][qqq.ch[i] - 16];
|
||||||
|
eWedgeRaw = qqq.e[j];
|
||||||
|
|
||||||
|
chRing = qqq.ch[i] - 16;
|
||||||
|
eRing = qqq.e[i];// * qqqrGain[qqq.id[i]][qqq.ch[i]][qqq.ch[j] - 16];
|
||||||
|
eRingRaw = qqq.e[i];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// hQQQFVB->Fill(eWedge, eRing);
|
||||||
|
plotter->Fill2D(Form("hRaw_qqq%d_ring%d_wedge%d", qqq.id[i], chRing, chWedge), 400, 0, 16000, 400, 0, 16000, eWedgeRaw, eRingRaw, "ERaw");
|
||||||
|
plotter->Fill2D(Form("hGM_qqq%d_ring%d_wedge%d", qqq.id[i], chRing, chWedge), 400, 0, 16000, 400, 0, 16000, eWedge, eRing, "EGM");
|
||||||
|
plotter->Fill2D("hRawQQQ", 4000, 0, 16000, 4000, 0, 16000, eWedgeRaw, eRingRaw);
|
||||||
|
plotter->Fill2D("hGMQQQ", 4000, 0, 16000, 4000, 0, 16000, eWedge, eRing);
|
||||||
|
|
||||||
|
TString histName = Form("hQQQFVB_id%d_r%d_w%d", qqq.id[i], chRing, chWedge);
|
||||||
|
// TH2F *hist2d = (TH2F *)gDirectory->Get(histName);
|
||||||
|
// if (!hist2d)
|
||||||
|
// {
|
||||||
|
// hist2d = new TH2F(histName, Form("QQQ Det%d R%d W%d;Wedge E;Ring E", qqq.id[i], chRing, chWedge), 400, 0, 16000, 400, 0, 16000);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// hist2d->Fill(eWedge, eRing);
|
||||||
|
// if (cut && cut->IsInside(eWedge, eRing))
|
||||||
|
const double MIN_ADC = 1500.0;
|
||||||
|
const double MAX_ADC = 3000.0;
|
||||||
|
|
||||||
|
// if (eWedge >= MIN_ADC && eWedge <= MAX_ADC &&
|
||||||
|
// eRing >= MIN_ADC && eRing <= MAX_ADC)
|
||||||
|
double ratio = (eWedge > 0.0) ? (eRing / eWedge) : 0.0;
|
||||||
|
|
||||||
|
double maxslope = 1.5;
|
||||||
|
|
||||||
|
bool validPoint = false;
|
||||||
|
if (ratio < maxslope && ratio > 1. / maxslope)
|
||||||
|
{
|
||||||
|
// Accumulate data for gain matching
|
||||||
|
dataPoints[{qqq.id[i], chRing, chWedge}].emplace_back(eWedge, eRing);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return kTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Calibration::Terminate()
|
||||||
|
{
|
||||||
|
const double AM241_PEAK = 5485.56;
|
||||||
|
const double P_PEAK = 7000; // keV
|
||||||
|
|
||||||
|
double calibArray[MAX_QQQ][MAX_RING][MAX_WEDGE] = {{{0}}};
|
||||||
|
bool calibValid[MAX_QQQ][MAX_RING][MAX_WEDGE] = {{{false}}};
|
||||||
|
|
||||||
|
std::ofstream outFile("qqq_Calib.txt");
|
||||||
|
if (!outFile.is_open())
|
||||||
|
{
|
||||||
|
std::cerr << "Error opening qqq_Calib.txt!" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
// 1. Create per–channel 1D spectra in ADC from stored gain-matched data
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
|
std::map<std::tuple<int, int, int>, TH1F *> spectra;
|
||||||
|
|
||||||
|
for (auto &kv : dataPoints)
|
||||||
|
{
|
||||||
|
int det, ring, wedge;
|
||||||
|
std::tie(det, ring, wedge) = kv.first;
|
||||||
|
|
||||||
|
TString hname = Form("hSpec_d%d_r%d_w%d", det, ring, wedge);
|
||||||
|
TH1F *h = new TH1F(hname, hname, 4000, 0, 16000);
|
||||||
|
|
||||||
|
for (auto &p : kv.second)
|
||||||
|
{
|
||||||
|
double eWedge = p.first; // already gain-matched ADC
|
||||||
|
double eRing = p.second;
|
||||||
|
|
||||||
|
// Use ring ADC for calibration (cleaner alpha peak)
|
||||||
|
h->Fill(eRing);
|
||||||
|
}
|
||||||
|
|
||||||
|
spectra[kv.first] = h;
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
// 2. Fit Am-241 peak and extract keV/ADC calibration slope
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
|
for (auto &kv : spectra)
|
||||||
|
{
|
||||||
|
int det, ring, wedge;
|
||||||
|
std::tie(det, ring, wedge) = kv.first;
|
||||||
|
TH1F *h = kv.second;
|
||||||
|
|
||||||
|
if (!h || h->GetEntries() < 50)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int binMax = h->GetMaximumBin();
|
||||||
|
double adcPeak = h->GetXaxis()->GetBinCenter(binMax);
|
||||||
|
|
||||||
|
if (adcPeak <= 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// double slope_keV = AM241_PEAK / adcPeak; // keV per ADC
|
||||||
|
double slope_keV = P_PEAK / adcPeak; // keV per ADC
|
||||||
|
|
||||||
|
calibArray[det][ring][wedge] = slope_keV;
|
||||||
|
calibValid[det][ring][wedge] = true;
|
||||||
|
|
||||||
|
outFile << det << " " << wedge << " " << ring << " "
|
||||||
|
<< slope_keV << "\n";
|
||||||
|
|
||||||
|
// printf("QQQ DET=%d R=%d W=%d ADCpeak=%.1f slope_keV=%.6f\n",det, ring, wedge, adcPeak, slope_keV);
|
||||||
|
}
|
||||||
|
|
||||||
|
outFile.close();
|
||||||
|
std::cout << "Wrote QQQ calibration file qqq_Calib.txt\n";
|
||||||
|
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
// 3. Build fully calibrated 2D combined histogram
|
||||||
|
//----------------------------------------------------------------------
|
||||||
|
|
||||||
|
TH2F *hCal = new TH2F("hCal",
|
||||||
|
"All QQQ Calibrated;Wedge Energy (keV);Ring Energy (keV)",
|
||||||
|
800, 0, 7000,
|
||||||
|
800, 0, 7000);
|
||||||
|
|
||||||
|
for (auto &kv : dataPoints)
|
||||||
|
{
|
||||||
|
int det, ring, wedge;
|
||||||
|
std::tie(det, ring, wedge) = kv.first;
|
||||||
|
|
||||||
|
if (!calibValid[det][ring][wedge])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
double slope = calibArray[det][ring][wedge];
|
||||||
|
|
||||||
|
for (auto &p : kv.second)
|
||||||
|
{
|
||||||
|
double eWGM = p.first; // gain matched ADC
|
||||||
|
double eRGM = p.second;
|
||||||
|
|
||||||
|
double eWkeV = eWGM * slope / 1000;
|
||||||
|
double eRkeV = eRGM * slope / 1000;
|
||||||
|
|
||||||
|
hCal->Fill(eWkeV, eRkeV);
|
||||||
|
plotter->Fill2D("hCalQQQ", 4000, 0, 10, 4000, 0, 10, eWkeV, eRkeV);
|
||||||
|
plotter->Fill2D(Form("hRCal_qqq%d", det), 16, 0, 15, 400, 0, 24, ring, eRkeV, "RingCal");
|
||||||
|
plotter->Fill2D(Form("hWCal_qqq%d", det), 16, 0, 15, 400, 0, 24, wedge, eWkeV, "WedgeCal");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
plotter->FlushToDisk();
|
||||||
|
std::cout << "Calibrated 2D QQQ histogram saved.\n";
|
||||||
|
}
|
||||||
114
Calibration.h
Normal file
114
Calibration.h
Normal file
|
|
@ -0,0 +1,114 @@
|
||||||
|
#ifndef Calibration_h
|
||||||
|
#define Calibration_h
|
||||||
|
|
||||||
|
#include <TROOT.h>
|
||||||
|
#include <TChain.h>
|
||||||
|
#include <TFile.h>
|
||||||
|
#include <TSelector.h>
|
||||||
|
|
||||||
|
#include "Armory/ClassDet.h"
|
||||||
|
|
||||||
|
class Calibration : public TSelector {
|
||||||
|
public :
|
||||||
|
TTree *fChain; //!pointer to the analyzed TTree or TChain
|
||||||
|
|
||||||
|
// Fixed size dimensions of array or collections stored in the TTree if any.
|
||||||
|
|
||||||
|
// Declaration of leaf types
|
||||||
|
Det sx3;
|
||||||
|
Det qqq;
|
||||||
|
Det pc ;
|
||||||
|
|
||||||
|
ULong64_t evID;
|
||||||
|
UInt_t run;
|
||||||
|
|
||||||
|
// List of branches
|
||||||
|
TBranch *b_eventID; //!
|
||||||
|
TBranch *b_run; //!
|
||||||
|
TBranch *b_sx3Multi; //!
|
||||||
|
TBranch *b_sx3ID; //!
|
||||||
|
TBranch *b_sx3Ch; //!
|
||||||
|
TBranch *b_sx3E; //!
|
||||||
|
TBranch *b_sx3T; //!
|
||||||
|
TBranch *b_qqqMulti; //!
|
||||||
|
TBranch *b_qqqID; //!
|
||||||
|
TBranch *b_qqqCh; //!
|
||||||
|
TBranch *b_qqqE; //!
|
||||||
|
TBranch *b_qqqT; //!
|
||||||
|
TBranch *b_pcMulti; //!
|
||||||
|
TBranch *b_pcID; //!
|
||||||
|
TBranch *b_pcCh; //!
|
||||||
|
TBranch *b_pcE; //!
|
||||||
|
TBranch *b_pcT; //!
|
||||||
|
|
||||||
|
Calibration(TTree * /*tree*/ =0) : fChain(0) { }
|
||||||
|
virtual ~Calibration() { }
|
||||||
|
virtual Int_t Version() const { return 2; }
|
||||||
|
virtual void Begin(TTree *tree);
|
||||||
|
virtual void SlaveBegin(TTree *tree);
|
||||||
|
virtual void Init(TTree *tree);
|
||||||
|
virtual Bool_t Notify();
|
||||||
|
virtual Bool_t Process(Long64_t entry);
|
||||||
|
virtual Int_t GetEntry(Long64_t entry, Int_t getall = 0) { return fChain ? fChain->GetTree()->GetEntry(entry, getall) : 0; }
|
||||||
|
virtual void SetOption(const char *option) { fOption = option; }
|
||||||
|
virtual void SetObject(TObject *obj) { fObject = obj; }
|
||||||
|
virtual void SetInputList(TList *input) { fInput = input; }
|
||||||
|
virtual TList *GetOutputList() const { return fOutput; }
|
||||||
|
virtual void SlaveTerminate();
|
||||||
|
virtual void Terminate();
|
||||||
|
|
||||||
|
ClassDef(Calibration,0);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef Calibration_cxx
|
||||||
|
void Calibration::Init(TTree *tree){
|
||||||
|
|
||||||
|
// Set branch addresses and branch pointers
|
||||||
|
if (!tree) return;
|
||||||
|
fChain = tree;
|
||||||
|
fChain->SetMakeClass(1);
|
||||||
|
|
||||||
|
fChain->SetBranchAddress("evID", &evID, &b_eventID);
|
||||||
|
fChain->SetBranchAddress("run", &run, &b_run);
|
||||||
|
|
||||||
|
sx3.SetDetDimension(24,12);
|
||||||
|
qqq.SetDetDimension(4,32);
|
||||||
|
pc.SetDetDimension(2,24);
|
||||||
|
|
||||||
|
fChain->SetBranchAddress("sx3Multi", &sx3.multi, &b_sx3Multi);
|
||||||
|
fChain->SetBranchAddress("sx3ID", &sx3.id, &b_sx3ID);
|
||||||
|
fChain->SetBranchAddress("sx3Ch", &sx3.ch, &b_sx3Ch);
|
||||||
|
fChain->SetBranchAddress("sx3E", &sx3.e, &b_sx3E);
|
||||||
|
fChain->SetBranchAddress("sx3T", &sx3.t, &b_sx3T);
|
||||||
|
fChain->SetBranchAddress("qqqMulti", &qqq.multi, &b_qqqMulti);
|
||||||
|
fChain->SetBranchAddress("qqqID", &qqq.id, &b_qqqID);
|
||||||
|
fChain->SetBranchAddress("qqqCh", &qqq.ch, &b_qqqCh);
|
||||||
|
fChain->SetBranchAddress("qqqE", &qqq.e, &b_qqqE);
|
||||||
|
fChain->SetBranchAddress("qqqT", &qqq.t, &b_qqqT);
|
||||||
|
fChain->SetBranchAddress("pcMulti", &pc.multi, &b_pcMulti);
|
||||||
|
fChain->SetBranchAddress("pcID", &pc.id, &b_pcID);
|
||||||
|
fChain->SetBranchAddress("pcCh", &pc.ch, &b_pcCh);
|
||||||
|
fChain->SetBranchAddress("pcE", &pc.e, &b_pcE);
|
||||||
|
fChain->SetBranchAddress("pcT", &pc.t, &b_pcT);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Bool_t Calibration::Notify(){
|
||||||
|
|
||||||
|
return kTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Calibration::SlaveBegin(TTree * /*tree*/){
|
||||||
|
|
||||||
|
TString option = GetOption();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void Calibration::SlaveTerminate(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif // #ifdef Calibration_cxx
|
||||||
639
DataDump.C
Normal file
639
DataDump.C
Normal file
|
|
@ -0,0 +1,639 @@
|
||||||
|
#define DataDump_cxx
|
||||||
|
|
||||||
|
#include "DataDump.h"
|
||||||
|
#include "Armory/ClassPW.h"
|
||||||
|
#include "Armory/HistPlotter.h"
|
||||||
|
|
||||||
|
#include <TH2.h>
|
||||||
|
#include <TStyle.h>
|
||||||
|
#include <TCanvas.h>
|
||||||
|
#include <TMath.h>
|
||||||
|
#include <TBranch.h>
|
||||||
|
#include "TVector3.h"
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <map>
|
||||||
|
#include <utility>
|
||||||
|
#include <vector>
|
||||||
|
#include <utility>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
// Global instances
|
||||||
|
PW pw_contr;
|
||||||
|
PW pwinstance;
|
||||||
|
TVector3 hitPos;
|
||||||
|
long long int gcount=0;
|
||||||
|
|
||||||
|
class Event {
|
||||||
|
public:
|
||||||
|
TVector3 pos;
|
||||||
|
int ch1=-1; //ring# for QQQ, anode# for PC
|
||||||
|
int ch2=-1; //wedge# for QQQ, cathode# for PC
|
||||||
|
double Energy1=-1; //Front for QQQ, Anode for PC
|
||||||
|
double Energy2=-1; //Back for QQQ, Cathode for PC
|
||||||
|
double Time1=-1;
|
||||||
|
double Time2=-1;
|
||||||
|
Event(TVector3 p, double E1, double E2, double T1, double T2): pos(p), Energy1(E1), Energy2(E2), Time1(T1), Time2(T2) {}
|
||||||
|
};
|
||||||
|
/*
|
||||||
|
void testfunction()
|
||||||
|
{
|
||||||
|
for(auto cathode: cathodes) {
|
||||||
|
std::unordered_set<int> chans;
|
||||||
|
chans.insert(cathode.ch);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
// Calibration globals
|
||||||
|
const int MAX_QQQ = 4;
|
||||||
|
const int MAX_RING = 16;
|
||||||
|
const int MAX_WEDGE = 16;
|
||||||
|
double qqqGain[MAX_QQQ][MAX_RING][MAX_WEDGE] = {{{0}}};
|
||||||
|
bool qqqGainValid[MAX_QQQ][MAX_RING][MAX_WEDGE] = {{{false}}};
|
||||||
|
double qqqCalib[MAX_QQQ][MAX_RING][MAX_WEDGE] = {{{0}}};
|
||||||
|
bool qqqCalibValid[MAX_QQQ][MAX_RING][MAX_WEDGE] = {{{false}}};
|
||||||
|
// TCutg *cutQQQ;
|
||||||
|
|
||||||
|
// PC Arrays
|
||||||
|
double pcSlope[48];
|
||||||
|
double pcIntercept[48];
|
||||||
|
|
||||||
|
HistPlotter *plotter;
|
||||||
|
|
||||||
|
bool HitNonZero;
|
||||||
|
bool sx3ecut;
|
||||||
|
bool qqqEcut;
|
||||||
|
|
||||||
|
|
||||||
|
void DataDump::Begin(TTree * /*tree*/)
|
||||||
|
{
|
||||||
|
TString option = GetOption();
|
||||||
|
plotter = new HistPlotter("Analyzer_QQQ.root", "TFILE");
|
||||||
|
|
||||||
|
pw_contr.ConstructGeo();
|
||||||
|
pwinstance.ConstructGeo();
|
||||||
|
|
||||||
|
// ---------------------------------------------------------
|
||||||
|
// 1. CRITICAL FIX: Initialize PC Arrays to Default (Raw)
|
||||||
|
// ---------------------------------------------------------
|
||||||
|
for (int i = 0; i < 48; i++) {
|
||||||
|
pcSlope[i] = 1.0; // Default slope = 1 (preserves Raw energy)
|
||||||
|
pcIntercept[i] = 0.0; // Default intercept = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate Crossover Geometry ONCE
|
||||||
|
TVector3 a, c, diff;
|
||||||
|
double a2, ac, c2, adiff, cdiff, denom, alpha;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < pwinstance.An.size(); i++)
|
||||||
|
{
|
||||||
|
a = pwinstance.An[i].first - pwinstance.An[i].second;
|
||||||
|
for (size_t j = 0; j < pwinstance.Ca.size(); j++)
|
||||||
|
{
|
||||||
|
c = pwinstance.Ca[j].first - pwinstance.Ca[j].second;
|
||||||
|
diff = pwinstance.An[i].first - pwinstance.Ca[j].first;
|
||||||
|
a2 = a.Dot(a);
|
||||||
|
c2 = c.Dot(c);
|
||||||
|
ac = a.Dot(c);
|
||||||
|
adiff = a.Dot(diff);
|
||||||
|
cdiff = c.Dot(diff);
|
||||||
|
denom = a2 * c2 - ac * ac;
|
||||||
|
alpha = (ac * cdiff - c2 * adiff) / denom;
|
||||||
|
|
||||||
|
Crossover[i][j][0].x = pwinstance.An[i].first.X() + alpha * a.X();
|
||||||
|
Crossover[i][j][0].y = pwinstance.An[i].first.Y() + alpha * a.Y();
|
||||||
|
Crossover[i][j][0].z = pwinstance.An[i].first.Z() + alpha * a.Z();
|
||||||
|
|
||||||
|
if (Crossover[i][j][0].z < -190 || Crossover[i][j][0].z > 190 || (i+j)%24 == 12 )
|
||||||
|
{
|
||||||
|
Crossover[i][j][0].z = 9999999;
|
||||||
|
}
|
||||||
|
|
||||||
|
Crossover[i][j][1].x = alpha;
|
||||||
|
Crossover[i][j][1].y = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load PC Calibrations
|
||||||
|
std::ifstream inputFile("slope_intercept_results.txt");
|
||||||
|
if (inputFile.is_open())
|
||||||
|
{
|
||||||
|
std::string line;
|
||||||
|
int index;
|
||||||
|
double slope, intercept;
|
||||||
|
while (std::getline(inputFile, line))
|
||||||
|
{
|
||||||
|
std::stringstream ss(line);
|
||||||
|
ss >> index >> slope >> intercept;
|
||||||
|
if (index >= 0 && index <= 47)
|
||||||
|
{
|
||||||
|
pcSlope[index] = slope;
|
||||||
|
pcIntercept[index] = intercept;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inputFile.close();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cerr << "Error opening slope_intercept.txt" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ... (Load QQQ Gains and Calibs - same as before) ...
|
||||||
|
{
|
||||||
|
std::string filename = "qqq_GainMatch.dat";
|
||||||
|
std::ifstream infile(filename);
|
||||||
|
if (infile.is_open())
|
||||||
|
{
|
||||||
|
int det, ring, wedge;
|
||||||
|
double gainw, gainr;
|
||||||
|
while (infile >> det >> wedge >> ring >> gainw >> gainr)
|
||||||
|
{
|
||||||
|
qqqGain[det][wedge][ring] = gainw;
|
||||||
|
qqqGainValid[det][wedge][ring] = (gainw > 0);
|
||||||
|
}
|
||||||
|
infile.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
std::string filename = "qqq_Calib.dat";
|
||||||
|
std::ifstream infile(filename);
|
||||||
|
if (infile.is_open())
|
||||||
|
{
|
||||||
|
int det, ring, wedge;
|
||||||
|
double slope;
|
||||||
|
while (infile >> det >> wedge >> ring >> slope)
|
||||||
|
{
|
||||||
|
qqqCalib[det][wedge][ring] = slope;
|
||||||
|
qqqCalibValid[det][wedge][ring] = (slope > 0);
|
||||||
|
}
|
||||||
|
infile.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Bool_t DataDump::Process(Long64_t entry)
|
||||||
|
{
|
||||||
|
hitPos.Clear();
|
||||||
|
HitNonZero = false;
|
||||||
|
bool qqq1000cut = false;
|
||||||
|
b_sx3Multi->GetEntry(entry);
|
||||||
|
b_sx3ID->GetEntry(entry);
|
||||||
|
b_sx3Ch->GetEntry(entry);
|
||||||
|
b_sx3E->GetEntry(entry);
|
||||||
|
b_sx3T->GetEntry(entry);
|
||||||
|
b_qqqMulti->GetEntry(entry);
|
||||||
|
b_qqqID->GetEntry(entry);
|
||||||
|
b_qqqCh->GetEntry(entry);
|
||||||
|
b_qqqE->GetEntry(entry);
|
||||||
|
b_qqqT->GetEntry(entry);
|
||||||
|
b_pcMulti->GetEntry(entry);
|
||||||
|
b_pcID->GetEntry(entry);
|
||||||
|
b_pcCh->GetEntry(entry);
|
||||||
|
b_pcE->GetEntry(entry);
|
||||||
|
b_pcT->GetEntry(entry);
|
||||||
|
|
||||||
|
sx3.CalIndex();
|
||||||
|
qqq.CalIndex();
|
||||||
|
pc.CalIndex();
|
||||||
|
|
||||||
|
// QQQ Processing
|
||||||
|
int qqqCount = 0;
|
||||||
|
int qqqAdjCh = 0;
|
||||||
|
// REMOVE WHEN RERUNNING USING THE NEW CALIBRATION FILE
|
||||||
|
for (int i = 0; i < qqq.multi; i++)
|
||||||
|
{
|
||||||
|
if ((qqq.id[i] == 3 || qqq.id[i] == 1) && qqq.ch[i] < 16)
|
||||||
|
{
|
||||||
|
qqq.ch[i] = 16 - qqq.ch[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int i = 0; i < qqq.multi; i++)
|
||||||
|
{
|
||||||
|
if (qqq.id[i] == 0 && qqq.ch[i] >= 16)
|
||||||
|
{
|
||||||
|
qqq.ch[i] = 31 - qqq.ch[i] + 16;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<std::tuple<int,int,double,int,double>> qqqlist;
|
||||||
|
std::vector<Event> QQQ_Events, PC_Events;
|
||||||
|
std::vector<Event> QQQ_Events_Raw, PC_Events_Raw;
|
||||||
|
bool PCQQQTimeCut = false;
|
||||||
|
for (int i = 0; i < qqq.multi; i++)
|
||||||
|
{
|
||||||
|
for (int j = i + 1; j < qqq.multi; j++)
|
||||||
|
{
|
||||||
|
if (qqq.id[i] == qqq.id[j])
|
||||||
|
{
|
||||||
|
qqqCount++;
|
||||||
|
|
||||||
|
int chWedge = -1;
|
||||||
|
int chRing = -1;
|
||||||
|
double eWedge = 0.0;
|
||||||
|
double eWedgeMeV = 0.0;
|
||||||
|
double eRing = 0.0;
|
||||||
|
double eRingMeV = 0.0;
|
||||||
|
double tRing = 0.0;
|
||||||
|
double tWedge = 0.0;
|
||||||
|
|
||||||
|
if (qqq.ch[i] < 16 && qqq.ch[j] >= 16 && qqqGainValid[qqq.id[i]][qqq.ch[i]][qqq.ch[j] - 16])
|
||||||
|
{
|
||||||
|
chWedge = qqq.ch[i];
|
||||||
|
eWedge = qqq.e[i] * qqqGain[qqq.id[i]][qqq.ch[i]][qqq.ch[j] - 16];
|
||||||
|
chRing = qqq.ch[j] - 16;
|
||||||
|
eRing = qqq.e[j];
|
||||||
|
tRing = static_cast<double>(qqq.t[j]);
|
||||||
|
tWedge = static_cast<double>(qqq.t[i]);
|
||||||
|
}
|
||||||
|
else if (qqq.ch[j] < 16 && qqq.ch[i] >= 16 && qqqGainValid[qqq.id[j]][qqq.ch[j]][qqq.ch[i] - 16])
|
||||||
|
{
|
||||||
|
chWedge = qqq.ch[j];
|
||||||
|
eWedge = qqq.e[j] * qqqGain[qqq.id[j]][qqq.ch[j]][qqq.ch[i] - 16];
|
||||||
|
chRing = qqq.ch[i] - 16;
|
||||||
|
eRing = qqq.e[i];
|
||||||
|
tRing = static_cast<double>(qqq.t[i]);
|
||||||
|
tWedge = static_cast<double>(qqq.t[j]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (qqqCalibValid[qqq.id[i]][chWedge][chRing]) {
|
||||||
|
eWedgeMeV = eWedge * qqqCalib[qqq.id[i]][chWedge][chRing] / 1000;
|
||||||
|
eRingMeV = eRing * qqqCalib[qqq.id[i]][chWedge][chRing] / 1000;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
continue;
|
||||||
|
|
||||||
|
double theta = -TMath::Pi() / 2 + 2 * TMath::Pi() / 16 / 4. * (qqq.id[i] * 16 + chWedge + 0.5);
|
||||||
|
double rho = 50. + 40. / 16. * (chRing + 0.5);
|
||||||
|
|
||||||
|
Event qqqevent(TVector3(rho*TMath::Cos(theta),rho*TMath::Sin(theta),23+75+30), eRingMeV, eWedgeMeV, tRing, tWedge);
|
||||||
|
Event qqqeventr(TVector3(rho*TMath::Cos(theta),rho*TMath::Sin(theta),23+75+30), eRing, eWedge, tRing, tWedge);
|
||||||
|
QQQ_Events.push_back(qqqevent);
|
||||||
|
QQQ_Events_Raw.push_back(qqqeventr);
|
||||||
|
qqqlist.push_back(std::tuple(qqq.id[i],chRing,eRingMeV,chWedge,eWedgeMeV));
|
||||||
|
} //end if qqq.id[i] == qqq.id[j]
|
||||||
|
}//inner qqq loop, j
|
||||||
|
}//outer qqq loop, i
|
||||||
|
|
||||||
|
// PC Gain Matching and Filling
|
||||||
|
double anodeT = -99999;
|
||||||
|
double cathodeT = 99999;
|
||||||
|
int anodeIndex = -1;
|
||||||
|
int cathodeIndex = -1;
|
||||||
|
|
||||||
|
|
||||||
|
int aID = 0;
|
||||||
|
int cID = 0;
|
||||||
|
double aE = 0;
|
||||||
|
double cE = 0;
|
||||||
|
double aESum = 0;
|
||||||
|
double cESum = 0;
|
||||||
|
double aEMax = 0;
|
||||||
|
int aIDMax = 0;
|
||||||
|
anodeHits.clear();
|
||||||
|
cathodeHits.clear();
|
||||||
|
anodeTimes.clear();
|
||||||
|
cathodeTimes.clear();
|
||||||
|
corrcatMax.clear();
|
||||||
|
corranoMax.clear();
|
||||||
|
|
||||||
|
std::array<bool,24> caths_seen{0}, anos_seen{0};
|
||||||
|
std::vector<std::tuple<int,double,double>> anodeChunks, cathodeChunks;
|
||||||
|
for (int i = 0; i < pc.multi; i++)
|
||||||
|
{
|
||||||
|
if (pc.e[i] > 4)
|
||||||
|
{
|
||||||
|
;//plotter->Fill2D("PC_Index_Vs_Energy", 48, 0, 48, 2000, 0, 30000, pc.index[i], static_cast<double>(pc.e[i]), "hRawPC");
|
||||||
|
} else
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (pc.index[i] < 48) {
|
||||||
|
pc.e[i] = pcSlope[pc.index[i]] * pc.e[i] + pcIntercept[pc.index[i]];
|
||||||
|
//plotter->Fill2D("PC_Index_VS_GainMatched_Energy", 48, 0, 48, 2000, 0, 30000, pc.index[i], pc.e[i], "hGMPC");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pc.index[i] < 24) {
|
||||||
|
anodeT = static_cast<double>(pc.t[i]);
|
||||||
|
anodeIndex = pc.index[i];
|
||||||
|
anos_seen[anodeIndex] = 1;
|
||||||
|
anodeHits.push_back(std::pair<int, double>(pc.index[i], pc.e[i]));
|
||||||
|
anodeTimes.push_back(anodeT);
|
||||||
|
anodeChunks.push_back(std::tuple<int,double,double>(pc.index[i],anodeT,pc.e[i]));
|
||||||
|
} else {
|
||||||
|
cathodeT = static_cast<double>(pc.t[i]);
|
||||||
|
cathodeIndex = pc.index[i] - 24;
|
||||||
|
caths_seen[cathodeIndex] = 1;
|
||||||
|
cathodeChunks.push_back(std::tuple<int,double,double>(pc.index[i]-24,cathodeT,pc.e[i]));
|
||||||
|
cathodeHits.push_back(std::pair<int, double>(pc.index[i] - 24, pc.e[i]));
|
||||||
|
cathodeTimes.push_back(cathodeT);
|
||||||
|
}
|
||||||
|
}//end of pc.multi loop
|
||||||
|
|
||||||
|
if(anodeHits.size() && cathodeHits.size()) {
|
||||||
|
for(size_t ii=0; ii<anodeHits.size(); ii++) {
|
||||||
|
const auto& an = anodeHits.at(ii);
|
||||||
|
const auto& at = anodeTimes.at(ii);
|
||||||
|
for(size_t jj=0; jj<cathodeHits.size(); jj++) {
|
||||||
|
const auto& ca = cathodeHits.at(jj);
|
||||||
|
const auto& ct = cathodeTimes.at(jj);
|
||||||
|
plotter->Fill2D("ach_minus_cch_vs_ach",60,-30,30,24,0,24,an.first-ca.first,an.first);
|
||||||
|
plotter->Fill2D("ach_minus_cch_vs_dt",60,-30,30,400,-1000,1000,an.first-ca.first,at-ct);
|
||||||
|
plotter->Fill2D("ach_vs_cch",24,0,24,24,0,24,an.first,ca.first);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
gcount++;
|
||||||
|
}
|
||||||
|
bool all_three = anodeHits.size() > 0 && cathodeHits.size() > 0 && qqqlist.size() > 0;
|
||||||
|
|
||||||
|
if(all_three) std::cout << "---" << std::endl;
|
||||||
|
for(size_t ii=0; ii<anodeHits.size() && all_three; ii++) {
|
||||||
|
const auto& an = anodeHits.at(ii);
|
||||||
|
const auto& at = anodeTimes.at(ii);
|
||||||
|
std::cout << "an" << std::setprecision(16) << ", " << an.first << ", " << an.second << ", " << at << " ,-1, -1" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(size_t jj=0; jj<cathodeHits.size() && all_three; jj++) {
|
||||||
|
const auto& ca = cathodeHits.at(jj);
|
||||||
|
const auto& ct = cathodeTimes.at(jj);
|
||||||
|
std::cout << "ca" << std::setprecision(16) << ", " << ca.first << ", " << ca.second << ", " << ct << " ,-1, -1" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(size_t jj=0; jj<qqqlist.size() && all_three; jj++) {
|
||||||
|
const auto[id,chr,er,chw,ew] = qqqlist.at(jj);
|
||||||
|
std::cout << "q" << std::setprecision(16) << ", " << id << ", " << chr << ", " << er << ", " << chw << ", " << ew << std::endl;
|
||||||
|
}
|
||||||
|
if(all_three) std::cout << " --end-- " << std::endl;
|
||||||
|
|
||||||
|
if(gcount == 100)
|
||||||
|
return -1;
|
||||||
|
// std::sort(anodeChunks.begin(),anodeChunks.end(),);
|
||||||
|
if (anodeHits.size() >= 1 && cathodeHits.size() >= 1)
|
||||||
|
{
|
||||||
|
// 2. CRITICAL FIX: Define reference vector 'a'
|
||||||
|
// In Analyzer.cxx, 'a' was left over from the loop. We use the first anode wire as reference here.
|
||||||
|
// (Assuming pwinstance.An is populated and wires are generally parallel).
|
||||||
|
TVector3 refAnode = pwinstance.An[0].first - pwinstance.An[0].second;
|
||||||
|
for (const auto &anode : anodeHits)
|
||||||
|
{
|
||||||
|
aID = anode.first;
|
||||||
|
aE = anode.second;
|
||||||
|
aESum += aE;
|
||||||
|
if (aE > aEMax)
|
||||||
|
{
|
||||||
|
aEMax = aE;
|
||||||
|
aIDMax = aID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto &cathode : cathodeHits)
|
||||||
|
{
|
||||||
|
cID = cathode.first;
|
||||||
|
cE = cathode.second;
|
||||||
|
for (int j = -4; j < 3; j++)
|
||||||
|
{
|
||||||
|
if ((aIDMax + 24 + j) % 24 == 23 - cID)
|
||||||
|
{
|
||||||
|
corrcatMax.push_back(std::pair<int, double>(cID, cE));
|
||||||
|
cESum += cE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TVector3 anodeIntersection;
|
||||||
|
anodeIntersection.Clear();
|
||||||
|
if (corrcatMax.size() > 0)
|
||||||
|
{
|
||||||
|
double x = 0, y = 0, z = 0;
|
||||||
|
for (const auto &corr : corrcatMax)
|
||||||
|
{
|
||||||
|
if (Crossover[aIDMax][corr.first][0].z > 9000000)
|
||||||
|
continue;
|
||||||
|
if (cESum > 0)
|
||||||
|
{
|
||||||
|
x += (corr.second) / cESum * Crossover[aIDMax][corr.first][0].x;
|
||||||
|
y += (corr.second) / cESum * Crossover[aIDMax][corr.first][0].y;
|
||||||
|
z += (corr.second) / cESum * Crossover[aIDMax][corr.first][0].z;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (x == 0 && y == 0 && z == 0)
|
||||||
|
;
|
||||||
|
// to ignore events with no valid crossover points
|
||||||
|
else
|
||||||
|
anodeIntersection = TVector3(x, y, z);
|
||||||
|
}
|
||||||
|
bool PCQQQPhiCut = false;
|
||||||
|
// flip the algorithm for cathode 1 multi anode events
|
||||||
|
if ((hitPos.Phi() > (anodeIntersection.Phi() - TMath::PiOver4())) && (hitPos.Phi() < (anodeIntersection.Phi() + TMath::PiOver4()))) {
|
||||||
|
PCQQQPhiCut = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (anodeIntersection.Z() != 0)
|
||||||
|
{
|
||||||
|
plotter->Fill1D("PC_Z_Projection", 600, -300, 300, anodeIntersection.Z(), "hPCzQQQ");
|
||||||
|
plotter->Fill2D("Z_Proj_VsDelTime", 600, -300, 300, 200, -2000, 2000, anodeIntersection.Z(), anodeT - cathodeT, "hPCzQQQ");
|
||||||
|
plotter->Fill2D("IntPhi_vs_QQQphi", 100, -200, 200, 80, -200, 200, anodeIntersection.Phi() * 180. / TMath::Pi(), hitPos.Phi() * 180. / TMath::Pi(), "hPCQQQ");
|
||||||
|
plotter->Fill2D("Inttheta_vs_QQQtheta", 90, 0, 180, 20, 0, 45, anodeIntersection.Theta() * 180. / TMath::Pi(), hitPos.Theta() * 180. / TMath::Pi(), "hPCQQQ");
|
||||||
|
plotter->Fill2D("Inttheta_vs_QQQtheta_TC" + std::to_string(PCQQQTimeCut), 90, 0, 180, 20, 0, 45, anodeIntersection.Theta() * 180. / TMath::Pi(), hitPos.Theta() * 180. / TMath::Pi(), "hPCQQQ");
|
||||||
|
plotter->Fill2D("IntPhi_vs_QQQphi_TC" + std::to_string(PCQQQTimeCut) + "PhiC" + std::to_string(PCQQQPhiCut), 100, -200, 200, 80, -200, 200, anodeIntersection.Phi() * 180. / TMath::Pi(), hitPos.Phi() * 180. / TMath::Pi(), "hPCQQQ");
|
||||||
|
}
|
||||||
|
if (anodeIntersection.Z() != 0 && cathodeHits.size() >= 2)
|
||||||
|
plotter->Fill1D("PC_Z_Projection_TC" + std::to_string(PCQQQTimeCut) + "PhiC" + std::to_string(PCQQQPhiCut), 600, -300, 300, anodeIntersection.Z(), "hPCzQQQ");
|
||||||
|
|
||||||
|
if (anodeIntersection.Z() != 0 && cathodeHits.size() == 1)
|
||||||
|
{
|
||||||
|
plotter->Fill1D("PC_Z_proj_1C", 600, -300, 300, anodeIntersection.Z(), "hPCzQQQ");
|
||||||
|
plotter->Fill2D("IntersectionPhi_vs_AnodeZ_1C", 400, -200, 200, 600, -300, 300, anodeIntersection.Phi() * 180. / TMath::Pi(), anodeIntersection.Z(), "hPCzQQQ");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (anodeIntersection.Z() != 0 && cathodeHits.size() == 2)
|
||||||
|
{
|
||||||
|
plotter->Fill1D("PC_Z_proj_2C", 600, -300, 300, anodeIntersection.Z(), "hPCzQQQ");
|
||||||
|
plotter->Fill2D("IntersectionPhi_vs_AnodeZ_2C", 400, -200, 200, 600, -300, 300, anodeIntersection.Phi() * 180. / TMath::Pi(), anodeIntersection.Z(), "hGMPC");
|
||||||
|
}
|
||||||
|
if (anodeIntersection.Z() != 0 && cathodeHits.size() > 2)
|
||||||
|
{
|
||||||
|
plotter->Fill1D("PC_Z_proj_nC", 600, -300, 300, anodeIntersection.Z(), "hPCzQQQ");
|
||||||
|
plotter->Fill2D("IntersectionPhi_vs_AnodeZ_nC", 400, -200, 200, 600, -300, 300, anodeIntersection.Phi() * 180. / TMath::Pi(), anodeIntersection.Z(), "hGMPC");
|
||||||
|
}
|
||||||
|
if (anodeHits.size() > 0 && cathodeHits.size() > 0)
|
||||||
|
plotter->Fill2D("AHits_vs_CHits", 12, 0, 11, 6, 0, 5, anodeHits.size(), cathodeHits.size(), "hRawPC");
|
||||||
|
|
||||||
|
// make another plot with nearest neighbour constraint
|
||||||
|
bool hasNeighbourAnodes = false;
|
||||||
|
bool hasNeighbourCathodes = false;
|
||||||
|
|
||||||
|
// 1. Check Anodes for neighbours (including wrap-around 0-23)
|
||||||
|
for (size_t i = 0; i < anodeHits.size(); i++)
|
||||||
|
{
|
||||||
|
for (size_t j = i + 1; j < anodeHits.size(); j++)
|
||||||
|
{
|
||||||
|
int diff = std::abs(anodeHits[i].first - anodeHits[j].first);
|
||||||
|
if (diff == 1 || diff == 23)
|
||||||
|
{ // 23 handles the cylindrical wrap
|
||||||
|
hasNeighbourAnodes = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (hasNeighbourAnodes)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Check Cathodes for neighbours (including wrap-around 0-23)
|
||||||
|
for (size_t i = 0; i < cathodeHits.size(); i++)
|
||||||
|
{
|
||||||
|
for (size_t j = i + 1; j < cathodeHits.size(); j++)
|
||||||
|
{
|
||||||
|
int diff = std::abs(cathodeHits[i].first - cathodeHits[j].first);
|
||||||
|
if (diff == 1 || diff == 23)
|
||||||
|
{
|
||||||
|
hasNeighbourCathodes = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (hasNeighbourCathodes)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------
|
||||||
|
// FILL PLOTS
|
||||||
|
// ---------------------------------------------------------
|
||||||
|
if (anodeHits.size() > 0 && cathodeHits.size() > 0)
|
||||||
|
{
|
||||||
|
plotter->Fill2D("AHits_vs_CHits_NA" + std::to_string(hasNeighbourAnodes), 12, 0, 11, 6, 0, 5, anodeHits.size(), cathodeHits.size(), "hRawPC");
|
||||||
|
plotter->Fill2D("AHits_vs_CHits_NC" + std::to_string(hasNeighbourCathodes), 12, 0, 11, 6, 0, 5, anodeHits.size(), cathodeHits.size(), "hRawPC");
|
||||||
|
|
||||||
|
// Constraint Plot: Only fill if BOTH planes have adjacent hits
|
||||||
|
// This effectively removes events with only isolated single-wire hits (noise)
|
||||||
|
if (hasNeighbourAnodes && hasNeighbourCathodes)
|
||||||
|
{
|
||||||
|
plotter->Fill2D("AHits_vs_CHits_NN", 12, 0, 11, 6, 0, 5, anodeHits.size(), cathodeHits.size(), "hRawPC");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (HitNonZero && anodeIntersection.Z() != 0)
|
||||||
|
{
|
||||||
|
pw_contr.CalTrack2(hitPos, anodeIntersection);
|
||||||
|
plotter->Fill1D("VertexRecon", 600, -300, 300, pw_contr.GetZ0());
|
||||||
|
plotter->Fill1D("VertexRecon_TC"+std::to_string(PCQQQTimeCut)+"_PhiC"+std::to_string(PCQQQPhiCut), 600, -300, 300, pw_contr.GetZ0());
|
||||||
|
|
||||||
|
if (cathodeHits.size() == 2)
|
||||||
|
plotter->Fill1D("VertexRecon_2c_TC"+std::to_string(PCQQQTimeCut)+"_PhiC"+std::to_string(PCQQQPhiCut), 600, -300, 300, pw_contr.GetZ0());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < qqq.multi; i++)
|
||||||
|
{
|
||||||
|
if (PCQQQTimeCut)
|
||||||
|
{
|
||||||
|
plotter->Fill2D("PC_XY_Projection_QQQ_TimeCut" + std::to_string(qqq.id[i]), 400, -100, 100, 400, -100, 100, anodeIntersection.X(), anodeIntersection.Y(), "hPCQQQ");
|
||||||
|
}
|
||||||
|
plotter->Fill2D("PC_XY_Projection_QQQ" + std::to_string(qqq.id[i]), 400, -100, 100, 400, -100, 100, anodeIntersection.X(), anodeIntersection.Y(), "hPCQQQ");
|
||||||
|
|
||||||
|
for (int j = i + 1; j < qqq.multi; j++)
|
||||||
|
{
|
||||||
|
if (qqq.id[i] == qqq.id[j])
|
||||||
|
{
|
||||||
|
int chWedge = -1;
|
||||||
|
int chRing = -1;
|
||||||
|
double eWedge = 0.0;
|
||||||
|
double eWedgeMeV = 0.0;
|
||||||
|
double eRing = 0.0;
|
||||||
|
double eRingMeV = 0.0;
|
||||||
|
double tRing = 0.0;
|
||||||
|
int qqqID = -1;
|
||||||
|
if (qqq.ch[i] < 16 && qqq.ch[j] >= 16 && qqqGainValid[qqq.id[i]][qqq.ch[i]][qqq.ch[j] - 16])
|
||||||
|
{
|
||||||
|
chWedge = qqq.ch[i];
|
||||||
|
eWedge = qqq.e[i] * qqqGain[qqq.id[i]][qqq.ch[i]][qqq.ch[j] - 16];
|
||||||
|
chRing = qqq.ch[j] - 16;
|
||||||
|
eRing = qqq.e[j];
|
||||||
|
tRing = static_cast<double>(qqq.t[j]);
|
||||||
|
qqqID = qqq.id[i];
|
||||||
|
}
|
||||||
|
else if (qqq.ch[j] < 16 && qqq.ch[i] >= 16 && qqqGainValid[qqq.id[j]][qqq.ch[j]][qqq.ch[i] - 16])
|
||||||
|
{
|
||||||
|
chWedge = qqq.ch[j];
|
||||||
|
eWedge = qqq.e[j] * qqqGain[qqq.id[j]][qqq.ch[j]][qqq.ch[i] - 16];
|
||||||
|
chRing = qqq.ch[i] - 16;
|
||||||
|
tRing = static_cast<double>(qqq.t[i]);
|
||||||
|
eRing = qqq.e[i];
|
||||||
|
qqqID = qqq.id[i];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (qqqCalibValid[qqq.id[i]][chRing][chWedge])
|
||||||
|
{
|
||||||
|
eWedgeMeV = eWedge * qqqCalib[qqq.id[i]][chRing][chWedge] / 1000;
|
||||||
|
eRingMeV = eRing * qqqCalib[qqq.id[i]][chRing][chWedge] / 1000;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// if (anodeIntersection.Z() != 0)
|
||||||
|
{
|
||||||
|
plotter->Fill2D("PC_Z_vs_QQQRing", 600, -300, 300, 16, 0, 16, anodeIntersection.Z(), chRing, "hPCzQQQ");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (anodeIntersection.Z() != 0 && cathodeHits.size() == 2)
|
||||||
|
{
|
||||||
|
plotter->Fill2D("PC_Z_vs_QQQRing_2C", 600, -300, 300, 16, 0, 16, anodeIntersection.Z(), chRing, "hPCzQQQ");
|
||||||
|
plotter->Fill2D("PC_Z_vs_QQQRing_2C" + std::to_string(qqq.id[i]), 600, -300, 300, 16, 0, 16, anodeIntersection.Z(), chRing, "hPCzQQQ");
|
||||||
|
plotter->Fill2D("PC_Z_vs_QQQWedge_2C", 600, -300, 300, 16, 0, 16, anodeIntersection.Z(), chWedge, "hPCzQQQ");
|
||||||
|
}
|
||||||
|
plotter->Fill2D("Vertex_V_QQQRingTC" + std::to_string(PCQQQTimeCut) + "PhiC" + std::to_string(PCQQQPhiCut), 600, -300, 300, 16, 0, 16, pw_contr.GetZ0(), chRing, "hPCQQQ");
|
||||||
|
double phi = TMath::ATan2(anodeIntersection.Y(), anodeIntersection.X()) * 180. / TMath::Pi();
|
||||||
|
plotter->Fill2D("PolarAngle_Vs_QQQWedge" + std::to_string(qqqID), 360, -360, 360, 16, 0, 16, phi, chWedge, "hPCQQQ");
|
||||||
|
// plotter->Fill2D("EdE_PC_vs_QQQ_timegate_ls1000"+std::to_string())
|
||||||
|
|
||||||
|
plotter->Fill2D("PC_Z_vs_QQQRing_Det" + std::to_string(qqqID), 600, -300, 300, 16, 0, 16, anodeIntersection.Z(), chRing, "hPCQQQ");
|
||||||
|
//double theta = -TMath::Pi() / 2 + 2 * TMath::Pi() / 16 / 4. * (qqq.id[i] * 16 + chWedge + 0.5);
|
||||||
|
//double rho = 50. + 40. / 16. * (chRing + 0.5);
|
||||||
|
|
||||||
|
for (int k = 0; k < pc.multi; k++)
|
||||||
|
{
|
||||||
|
if(pc.index[k] >= 24)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
double sinTheta = TMath::Sin(hitPos.Theta());
|
||||||
|
|
||||||
|
plotter->Fill2D("CalibratedQQQE_RvsPCE_TC" + std::to_string(PCQQQTimeCut) + "PhiC" + std::to_string(PCQQQPhiCut), 1000, 0, 10, 2000, 0, 30000, eRingMeV, pc.e[k]*sinTheta, "hPCQQQ");
|
||||||
|
plotter->Fill2D("CalibratedQQQE_WvsPCE_TC" + std::to_string(PCQQQTimeCut) + "PhiC" + std::to_string(PCQQQPhiCut), 1000, 0, 10, 2000, 0, 30000, eWedgeMeV, pc.e[k]*sinTheta, "hPCQQQ");
|
||||||
|
plotter->Fill2D("PCQQQ_dTimevsdPhi", 200, -2000, 2000, 80, -200, 200, tRing - static_cast<double>(pc.t[k]), (hitPos.Phi()-anodeIntersection.Phi()) * 180. / TMath::Pi(), "hTiming");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int i = 0; i < sx3.multi; i++)
|
||||||
|
{
|
||||||
|
// plotting sx3 strip hits vs anode phi
|
||||||
|
if (sx3.ch[i] < 8)
|
||||||
|
plotter->Fill2D("AnodePhi_vs_SX3Strip", 100, -200, 200, 8 * 24, 0, 8 * 24, anodeIntersection.Phi() * 180. / TMath::Pi(), sx3.id[i] * 8 + sx3.ch[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (anodeIntersection.Z() != 0 && cathodeHits.size() == 3)
|
||||||
|
{
|
||||||
|
plotter->Fill1D("PC_Z_proj_3C", 600, -300, 300, anodeIntersection.Z(), "hPCzQQQ");
|
||||||
|
}
|
||||||
|
|
||||||
|
plotter->Fill2D("AnodeMaxE_Vs_Cathode_Sum_Energy", 2000, 0, 30000, 2000, 0, 30000, aEMax, cESum, "hGMPC");
|
||||||
|
plotter->Fill1D("Correlated_Cathode_MaxAnode", 6, 0, 5, corrcatMax.size(), "hGMPC");
|
||||||
|
plotter->Fill2D("Correlated_Cathode_VS_MaxAnodeEnergy", 6, 0, 5, 2000, 0, 30000, corrcatMax.size(), aEMax, "hGMPC");
|
||||||
|
plotter->Fill1D("AnodeHits", 12, 0, 11, anodeHits.size(), "hGMPC");
|
||||||
|
plotter->Fill2D("AnodeMaxE_vs_AnodeHits", 12, 0, 11, 2000, 0, 30000, anodeHits.size(), aEMax, "hGMPC");
|
||||||
|
|
||||||
|
if (anodeHits.size() < 1)
|
||||||
|
{
|
||||||
|
plotter->Fill1D("NoAnodeHits_CathodeHits", 6, 0, 5, cathodeHits.size(), "hGMPC");
|
||||||
|
}
|
||||||
|
|
||||||
|
return kTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DataDump::Terminate()
|
||||||
|
{
|
||||||
|
plotter->FlushToDisk();
|
||||||
|
}
|
||||||
132
DataDump.h
Normal file
132
DataDump.h
Normal file
|
|
@ -0,0 +1,132 @@
|
||||||
|
#ifndef DataDump_h
|
||||||
|
#define DataDump_h
|
||||||
|
|
||||||
|
#include <TROOT.h>
|
||||||
|
#include <TChain.h>
|
||||||
|
#include <TApplication.h>
|
||||||
|
#include <TFile.h>
|
||||||
|
#include <TSelector.h>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <vector> // Required for vectors
|
||||||
|
#include <utility> // Required for std::pair
|
||||||
|
|
||||||
|
#include "Armory/ClassDet.h"
|
||||||
|
#include "Armory/ClassPW.h" // YOU ADDED THIS (Correct! Defines Coord)
|
||||||
|
|
||||||
|
class DataDump : public TSelector {
|
||||||
|
public :
|
||||||
|
TTree *fChain; //!pointer to the analyzed TTree or TChain
|
||||||
|
|
||||||
|
// Declaration of leaf types
|
||||||
|
Det sx3;
|
||||||
|
Det qqq;
|
||||||
|
Det pc ;
|
||||||
|
Det misc;
|
||||||
|
|
||||||
|
ULong64_t evID;
|
||||||
|
UInt_t run;
|
||||||
|
|
||||||
|
// List of branches
|
||||||
|
TBranch *b_eventID; //!
|
||||||
|
TBranch *b_run; //!
|
||||||
|
TBranch *b_sx3Multi; //!
|
||||||
|
TBranch *b_sx3ID; //!
|
||||||
|
TBranch *b_sx3Ch; //!
|
||||||
|
TBranch *b_sx3E; //!
|
||||||
|
TBranch *b_sx3T; //!
|
||||||
|
TBranch *b_qqqMulti; //!
|
||||||
|
TBranch *b_qqqID; //!
|
||||||
|
TBranch *b_qqqCh; //!
|
||||||
|
TBranch *b_qqqE; //!
|
||||||
|
TBranch *b_qqqT; //!
|
||||||
|
TBranch *b_pcMulti; //!
|
||||||
|
TBranch *b_pcID; //!
|
||||||
|
TBranch *b_pcCh; //!
|
||||||
|
TBranch *b_pcE; //!
|
||||||
|
TBranch *b_pcT; //!
|
||||||
|
TBranch *b_miscMulti; //!
|
||||||
|
TBranch *b_miscID; //!
|
||||||
|
TBranch *b_miscCh; //!
|
||||||
|
TBranch *b_miscE; //!
|
||||||
|
TBranch *b_miscT; //!
|
||||||
|
TBranch *b_miscTf; //!
|
||||||
|
|
||||||
|
// 1. Geometry Cache
|
||||||
|
Coord Crossover[24][24][2];
|
||||||
|
|
||||||
|
// 2. Persistent Vectors (REQUIRED for the optimized .cxx to work)
|
||||||
|
std::vector<std::pair<int, double>> anodeHits;
|
||||||
|
std::vector<std::pair<int, double>> cathodeHits;
|
||||||
|
std::vector<std::pair<int, double>> corrcatMax;
|
||||||
|
std::vector<std::pair<int, double>> corranoMax;
|
||||||
|
std::vector<double> cathodeTimes;
|
||||||
|
std::vector<double> anodeTimes;
|
||||||
|
|
||||||
|
DataDump(TTree * /*tree*/ =0) : fChain(0) { }
|
||||||
|
virtual ~DataDump() { }
|
||||||
|
virtual Int_t Version() const { return 2; }
|
||||||
|
virtual void Begin(TTree *tree);
|
||||||
|
virtual void SlaveBegin(TTree *tree);
|
||||||
|
virtual void Init(TTree *tree);
|
||||||
|
virtual Bool_t Notify();
|
||||||
|
virtual Bool_t Process(Long64_t entry);
|
||||||
|
virtual Int_t GetEntry(Long64_t entry, Int_t getall = 0) { return fChain ? fChain->GetTree()->GetEntry(entry, getall) : 0; }
|
||||||
|
virtual void SetOption(const char *option) { fOption = option; }
|
||||||
|
virtual void SetObject(TObject *obj) { fObject = obj; }
|
||||||
|
virtual void SetInputList(TList *input) { fInput = input; }
|
||||||
|
virtual TList *GetOutputList() const { return fOutput; }
|
||||||
|
virtual void SlaveTerminate();
|
||||||
|
virtual void Terminate();
|
||||||
|
|
||||||
|
ClassDef(DataDump,0);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef DataDump_cxx
|
||||||
|
void DataDump::Init(TTree *tree){
|
||||||
|
|
||||||
|
if (!tree) return;
|
||||||
|
fChain = tree;
|
||||||
|
fChain->SetMakeClass(1);
|
||||||
|
|
||||||
|
fChain->SetBranchAddress("evID", &evID, &b_eventID);
|
||||||
|
fChain->SetBranchAddress("run", &run, &b_run);
|
||||||
|
|
||||||
|
sx3.SetDetDimension(24,12);
|
||||||
|
qqq.SetDetDimension(4,32);
|
||||||
|
pc.SetDetDimension(2,24);
|
||||||
|
|
||||||
|
fChain->SetBranchAddress("sx3Multi", &sx3.multi, &b_sx3Multi);
|
||||||
|
fChain->SetBranchAddress("sx3ID", &sx3.id, &b_sx3ID);
|
||||||
|
fChain->SetBranchAddress("sx3Ch", &sx3.ch, &b_sx3Ch);
|
||||||
|
fChain->SetBranchAddress("sx3E", &sx3.e, &b_sx3E);
|
||||||
|
fChain->SetBranchAddress("sx3T", &sx3.t, &b_sx3T);
|
||||||
|
fChain->SetBranchAddress("qqqMulti", &qqq.multi, &b_qqqMulti);
|
||||||
|
fChain->SetBranchAddress("qqqID", &qqq.id, &b_qqqID);
|
||||||
|
fChain->SetBranchAddress("qqqCh", &qqq.ch, &b_qqqCh);
|
||||||
|
fChain->SetBranchAddress("qqqE", &qqq.e, &b_qqqE);
|
||||||
|
fChain->SetBranchAddress("qqqT", &qqq.t, &b_qqqT);
|
||||||
|
fChain->SetBranchAddress("pcMulti", &pc.multi, &b_pcMulti);
|
||||||
|
fChain->SetBranchAddress("pcID", &pc.id, &b_pcID);
|
||||||
|
fChain->SetBranchAddress("pcCh", &pc.ch, &b_pcCh);
|
||||||
|
fChain->SetBranchAddress("pcE", &pc.e, &b_pcE);
|
||||||
|
fChain->SetBranchAddress("pcT", &pc.t, &b_pcT);
|
||||||
|
fChain->SetBranchAddress("miscMulti", &misc.multi, &b_miscMulti);
|
||||||
|
fChain->SetBranchAddress("miscID", &misc.id, &b_miscID);
|
||||||
|
fChain->SetBranchAddress("miscCh", &misc.ch, &b_miscCh);
|
||||||
|
fChain->SetBranchAddress("miscE", &misc.e, &b_miscE);
|
||||||
|
fChain->SetBranchAddress("miscT", &misc.t, &b_miscT);
|
||||||
|
}
|
||||||
|
|
||||||
|
Bool_t DataDump::Notify(){
|
||||||
|
return kTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DataDump::SlaveBegin(TTree * /*tree*/){
|
||||||
|
// TString option = GetOption();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DataDump::SlaveTerminate(){
|
||||||
|
}
|
||||||
|
#endif // #ifdef DataDump_cxx
|
||||||
268
ELoss/Eloss_17F
Normal file
268
ELoss/Eloss_17F
Normal file
|
|
@ -0,0 +1,268 @@
|
||||||
|
0.017002095 0.00676442
|
||||||
|
0.03400419 0.0135288
|
||||||
|
0.085010476 0.032227
|
||||||
|
0.136016762 0.0489265
|
||||||
|
0.170020952 0.0592235
|
||||||
|
0.255031428 0.0823584
|
||||||
|
0.340041904 0.102374
|
||||||
|
0.42505238 0.120086
|
||||||
|
0.510062856 0.135943
|
||||||
|
0.595073332 0.150461
|
||||||
|
0.680083808 0.164011
|
||||||
|
0.765094284 0.176885
|
||||||
|
0.85010476 0.189282
|
||||||
|
0.935115236 0.201176
|
||||||
|
1.020125712 0.212518
|
||||||
|
1.190146664 0.233962
|
||||||
|
1.360167616 0.254045
|
||||||
|
1.530188568 0.27299
|
||||||
|
1.70020952 0.291072
|
||||||
|
2.040251424 0.325807
|
||||||
|
2.380293328 0.359536
|
||||||
|
2.720335232 0.392589
|
||||||
|
3.060377136 0.425159
|
||||||
|
3.40041904 0.457286
|
||||||
|
4.2505238 0.536817
|
||||||
|
5.10062856 0.615601
|
||||||
|
5.95073332 0.693052
|
||||||
|
6.80083808 0.769499
|
||||||
|
7.65094284 0.845324
|
||||||
|
8.5010476 0.920793
|
||||||
|
10.20125712 1.07377
|
||||||
|
11.90146664 1.23229
|
||||||
|
13.60167616 1.39414
|
||||||
|
15.30188568 1.55782
|
||||||
|
17.0020952 1.72459
|
||||||
|
21.252619 2.15811
|
||||||
|
25.5031428 2.61883
|
||||||
|
29.7536666 3.10864
|
||||||
|
34.0041904 3.62853
|
||||||
|
38.2547142 4.17854
|
||||||
|
42.505238 4.75843
|
||||||
|
51.0062856 6.00863
|
||||||
|
59.5073332 7.38089
|
||||||
|
68.0083808 8.87668
|
||||||
|
76.5094284 10.4957
|
||||||
|
85.010476 12.2377
|
||||||
|
93.5115236 14.1011
|
||||||
|
102.0125712 16.0845
|
||||||
|
110.5136188 18.1875
|
||||||
|
119.0146664 20.4097
|
||||||
|
127.515714 22.7505
|
||||||
|
136.0167616 25.2096
|
||||||
|
144.5178092 27.7867
|
||||||
|
153.0188568 30.4814
|
||||||
|
161.5199044 33.2935
|
||||||
|
170.020952 36.2195
|
||||||
|
187.0230472 42.214
|
||||||
|
204.0251424 48.6246
|
||||||
|
221.0272376 55.449
|
||||||
|
238.0293328 62.6845
|
||||||
|
255.031428 70.3284
|
||||||
|
272.0335232 78.3781
|
||||||
|
289.0356184 86.8308
|
||||||
|
306.0377136 95.684
|
||||||
|
323.0398088 104.935
|
||||||
|
340.041904 114.581
|
||||||
|
357.0439992 124.619
|
||||||
|
374.0460944 135.048
|
||||||
|
391.0481896 145.863
|
||||||
|
408.0502848 157.064
|
||||||
|
425.05238 168.647
|
||||||
|
459.0565704 192.95
|
||||||
|
493.0607608 218.753
|
||||||
|
527.0649512 246.038
|
||||||
|
561.0691416 274.787
|
||||||
|
595.073332 304.983
|
||||||
|
646.0796176 352.95
|
||||||
|
697.0859032 404.079
|
||||||
|
748.0921888 458.315
|
||||||
|
799.0984744 515.608
|
||||||
|
850.10476 575.909
|
||||||
|
935.115236 682.969
|
||||||
|
1020.125712 798.048
|
||||||
|
1105.136188 920.949
|
||||||
|
1190.146664 1051.49
|
||||||
|
1275.15714 1189.49
|
||||||
|
1360.167616 1334.78
|
||||||
|
1445.178092 1487.21
|
||||||
|
1530.188568 1646.62
|
||||||
|
1615.199044 1812.86
|
||||||
|
1700.20952 1985.8
|
||||||
|
1785.219996 2165.29
|
||||||
|
1870.230472 2351.2
|
||||||
|
1955.240948 2543.42
|
||||||
|
2040.251424 2741.82
|
||||||
|
2125.2619 2946.27
|
||||||
|
2210.272376 3156.67
|
||||||
|
2295.282852 3372.91
|
||||||
|
2380.293328 3594.88
|
||||||
|
2465.303804 3822.47
|
||||||
|
2550.31428 4055.59
|
||||||
|
2635.324756 4294.14
|
||||||
|
2720.335232 4538.01
|
||||||
|
2805.345708 4787.13
|
||||||
|
2890.356184 5041.4
|
||||||
|
2975.36666 5300.73
|
||||||
|
3060.377136 5565.04
|
||||||
|
3145.387612 5834.24
|
||||||
|
3230.398088 6108.26
|
||||||
|
3315.408564 6387.01
|
||||||
|
3400.41904 6670.42
|
||||||
|
3570.439992 7250.92
|
||||||
|
3740.460944 7849.17
|
||||||
|
3910.481896 8464.62
|
||||||
|
4080.502848 9096.74
|
||||||
|
4250.5238 9745.02
|
||||||
|
4420.544752 10409
|
||||||
|
4590.565704 11088.2
|
||||||
|
4760.586656 11782.1
|
||||||
|
4930.607608 12490.4
|
||||||
|
5100.62856 13212.7
|
||||||
|
5270.649512 13948.5
|
||||||
|
5440.670464 14697.4
|
||||||
|
5610.691416 15459.2
|
||||||
|
5780.712368 16233.4
|
||||||
|
5950.73332 17019.7
|
||||||
|
6120.754272 17817.8
|
||||||
|
6290.775224 18627.3
|
||||||
|
6460.796176 19448
|
||||||
|
6630.817128 20279.6
|
||||||
|
6800.83808 21121.8
|
||||||
|
6970.859032 21974.2
|
||||||
|
7140.879984 22836.7
|
||||||
|
7310.900936 23709
|
||||||
|
7480.921888 24590.9
|
||||||
|
7650.94284 25482
|
||||||
|
7820.963792 26382.2
|
||||||
|
7990.984744 27291.2
|
||||||
|
8161.005696 28208.8
|
||||||
|
8331.026648 29134.9
|
||||||
|
8501.0476 30069.1
|
||||||
|
8841.089504 31961.3
|
||||||
|
9181.131408 33884
|
||||||
|
9521.173312 35835.8
|
||||||
|
9861.215216 37815.1
|
||||||
|
10201.25712 39820.8
|
||||||
|
10541.29902 41851.6
|
||||||
|
10881.34093 43906.4
|
||||||
|
11221.38283 45984.1
|
||||||
|
11561.42474 48083.6
|
||||||
|
11901.46664 50203.9
|
||||||
|
12241.50854 52344.2
|
||||||
|
12581.55045 54503.4
|
||||||
|
12921.59235 56680.8
|
||||||
|
13261.63426 58875.5
|
||||||
|
13601.67616 61086.7
|
||||||
|
13941.71806 63313.8
|
||||||
|
14281.75997 65556.1
|
||||||
|
14621.80187 67812.7
|
||||||
|
14961.84378 70083.2
|
||||||
|
15301.88568 72366.9
|
||||||
|
15641.92758 74663.1
|
||||||
|
15981.96949 76971.4
|
||||||
|
16322.01139 79291.2
|
||||||
|
16662.0533 81622
|
||||||
|
17002.0952 83963.3
|
||||||
|
17342.1371 86314.6
|
||||||
|
17682.17901 88675.4
|
||||||
|
18022.22091 91045.4
|
||||||
|
18362.26282 93424
|
||||||
|
18702.30472 95811
|
||||||
|
19042.34662 98205.9
|
||||||
|
19382.38853 100608
|
||||||
|
19722.43043 103018
|
||||||
|
20062.47234 105434
|
||||||
|
20402.51424 107857
|
||||||
|
20742.55614 110286
|
||||||
|
21082.59805 112721
|
||||||
|
21422.63995 115162
|
||||||
|
21762.68186 117608
|
||||||
|
22102.72376 120059
|
||||||
|
22442.76566 122514
|
||||||
|
22782.80757 124975
|
||||||
|
23122.84947 127439
|
||||||
|
23462.89138 129908
|
||||||
|
23802.93328 132380
|
||||||
|
24142.97518 134856
|
||||||
|
24483.01709 137335
|
||||||
|
24823.05899 139817
|
||||||
|
25163.1009 142303
|
||||||
|
25503.1428 144791
|
||||||
|
25843.1847 147281
|
||||||
|
26183.22661 149774
|
||||||
|
26523.26851 152270
|
||||||
|
26863.31042 154767
|
||||||
|
27203.35232 157266
|
||||||
|
27543.39422 159767
|
||||||
|
27883.43613 162270
|
||||||
|
28223.47803 164774
|
||||||
|
28563.51994 167279
|
||||||
|
28903.56184 169786
|
||||||
|
29753.6666 176056
|
||||||
|
30603.77136 182331
|
||||||
|
31453.87612 188609
|
||||||
|
32303.98088 194888
|
||||||
|
33154.08564 201166
|
||||||
|
34004.1904 207442
|
||||||
|
35704.39992 219984
|
||||||
|
37404.60944 232503
|
||||||
|
39104.81896 244992
|
||||||
|
40805.02848 257444
|
||||||
|
42505.238 269853
|
||||||
|
44205.44752 282214
|
||||||
|
45905.65704 294523
|
||||||
|
47605.86656 306775
|
||||||
|
49306.07608 318968
|
||||||
|
51006.2856 331099
|
||||||
|
54406.70464 355166
|
||||||
|
57807.12368 378963
|
||||||
|
61207.54272 402479
|
||||||
|
64607.96176 425709
|
||||||
|
68008.3808 448649
|
||||||
|
71408.79984 471298
|
||||||
|
74809.21888 493655
|
||||||
|
78209.63792 515723
|
||||||
|
81610.05696 537503
|
||||||
|
85010.476 558999
|
||||||
|
89260.9998 585475
|
||||||
|
93511.5236 611522
|
||||||
|
102012.5712 662361
|
||||||
|
110513.6188 711594
|
||||||
|
119014.6664 759299
|
||||||
|
127515.714 805555
|
||||||
|
136016.7616 850436
|
||||||
|
144517.8092 894016
|
||||||
|
153018.8568 936363
|
||||||
|
161519.9044 977541
|
||||||
|
170020.952 1.02E+06
|
||||||
|
187023.0472 1.09E+06
|
||||||
|
204025.1424 1.17E+06
|
||||||
|
221027.2376 1.24E+06
|
||||||
|
238029.3328 1.30E+06
|
||||||
|
255031.428 1.37E+06
|
||||||
|
272033.5232 1.43E+06
|
||||||
|
289035.6184 1.49E+06
|
||||||
|
306037.7136 1.54E+06
|
||||||
|
323039.8088 1.60E+06
|
||||||
|
340041.904 1.65E+06
|
||||||
|
357043.9992 1.70E+06
|
||||||
|
374046.0944 1.75E+06
|
||||||
|
391048.1896 1.80E+06
|
||||||
|
408050.2848 1.84E+06
|
||||||
|
425052.38 1.89E+06
|
||||||
|
442054.4752 1.93E+06
|
||||||
|
459056.5704 1.98E+06
|
||||||
|
476058.6656 2.02E+06
|
||||||
|
493060.7608 2.06E+06
|
||||||
|
510062.856 2.10E+06
|
||||||
|
544067.0464 2.17E+06
|
||||||
|
578071.2368 2.24E+06
|
||||||
|
612075.4272 2.31E+06
|
||||||
|
646079.6176 2.38E+06
|
||||||
|
680083.808 2.44E+06
|
||||||
|
714087.9984 2.50E+06
|
||||||
|
748092.1888 2.56E+06
|
||||||
|
782096.3792 2.61E+06
|
||||||
|
816100.5696 2.67E+06
|
||||||
|
850104.76 2.72E+06
|
||||||
268
ELoss/Eloss_27Al
Normal file
268
ELoss/Eloss_27Al
Normal file
|
|
@ -0,0 +1,268 @@
|
||||||
|
0.026981539 1087.74
|
||||||
|
0.053963078 2175.49
|
||||||
|
0.134907695 5438.8
|
||||||
|
0.215852312 8557.19
|
||||||
|
0.26981539 10540.7
|
||||||
|
0.404723085 15079.2
|
||||||
|
0.53963078 19011.9
|
||||||
|
0.674538475 22467.9
|
||||||
|
0.80944617 25531.3
|
||||||
|
0.944353865 28303.5
|
||||||
|
1.07926156 30859.2
|
||||||
|
1.214169255 33253.7
|
||||||
|
1.34907695 35529.1
|
||||||
|
1.483984645 37685.6
|
||||||
|
1.61889234 39719.2
|
||||||
|
1.88870773 43505.2
|
||||||
|
2.15852312 46980.1
|
||||||
|
2.42833851 50199.6
|
||||||
|
2.6981539 53228.6
|
||||||
|
3.23778468 58941.2
|
||||||
|
3.77741546 64372.8
|
||||||
|
4.31704624 69606.4
|
||||||
|
4.85667702 74683.1
|
||||||
|
5.3963078 79618
|
||||||
|
6.74538475 91580.1
|
||||||
|
8.0944617 103093
|
||||||
|
9.44353865 114105
|
||||||
|
10.7926156 124746
|
||||||
|
12.14169255 135119
|
||||||
|
13.4907695 145269
|
||||||
|
16.1889234 165367
|
||||||
|
18.8870773 185754
|
||||||
|
21.5852312 206324
|
||||||
|
24.2833851 226926
|
||||||
|
26.981539 247688
|
||||||
|
33.72692375 300998
|
||||||
|
40.4723085 357029
|
||||||
|
47.21769325 416359
|
||||||
|
53.963078 478956
|
||||||
|
60.70846275 544719
|
||||||
|
67.4538475 613499
|
||||||
|
80.944617 759812
|
||||||
|
94.4353865 917732
|
||||||
|
107.926156 1.09E+06
|
||||||
|
121.4169255 1.27E+06
|
||||||
|
134.907695 1.46E+06
|
||||||
|
148.3984645 1.67E+06
|
||||||
|
161.889234 1.88E+06
|
||||||
|
175.3800035 2.11E+06
|
||||||
|
188.870773 2.35E+06
|
||||||
|
202.3615425 2.60E+06
|
||||||
|
215.852312 2.86E+06
|
||||||
|
229.3430815 3.13E+06
|
||||||
|
242.833851 3.41E+06
|
||||||
|
256.3246205 3.71E+06
|
||||||
|
269.81539 4.01E+06
|
||||||
|
296.796929 4.64E+06
|
||||||
|
323.778468 5.30E+06
|
||||||
|
350.760007 6.00E+06
|
||||||
|
377.741546 6.74E+06
|
||||||
|
404.723085 7.53E+06
|
||||||
|
431.704624 8.35E+06
|
||||||
|
458.686163 9.21E+06
|
||||||
|
485.667702 1.01E+07
|
||||||
|
512.649241 1.10E+07
|
||||||
|
539.63078 1.20E+07
|
||||||
|
566.612319 1.30E+07
|
||||||
|
593.593858 1.41E+07
|
||||||
|
620.575397 1.52E+07
|
||||||
|
647.556936 1.63E+07
|
||||||
|
674.538475 1.75E+07
|
||||||
|
728.501553 1.99E+07
|
||||||
|
782.464631 2.25E+07
|
||||||
|
836.427709 2.52E+07
|
||||||
|
890.390787 2.81E+07
|
||||||
|
944.353865 3.11E+07
|
||||||
|
1025.298482 3.59E+07
|
||||||
|
1106.243099 4.10E+07
|
||||||
|
1187.187716 4.64E+07
|
||||||
|
1268.132333 5.21E+07
|
||||||
|
1349.07695 5.81E+07
|
||||||
|
1483.984645 6.88E+07
|
||||||
|
1618.89234 8.02E+07
|
||||||
|
1753.800035 9.24E+07
|
||||||
|
1888.70773 1.05E+08
|
||||||
|
2023.615425 1.19E+08
|
||||||
|
2158.52312 1.34E+08
|
||||||
|
2293.430815 1.49E+08
|
||||||
|
2428.33851 1.65E+08
|
||||||
|
2563.246205 1.81E+08
|
||||||
|
2698.1539 1.98E+08
|
||||||
|
2833.061595 2.16E+08
|
||||||
|
2967.96929 2.35E+08
|
||||||
|
3102.876985 2.54E+08
|
||||||
|
3237.78468 2.73E+08
|
||||||
|
3372.692375 2.94E+08
|
||||||
|
3507.60007 3.15E+08
|
||||||
|
3642.507765 3.36E+08
|
||||||
|
3777.41546 3.58E+08
|
||||||
|
3912.323155 3.81E+08
|
||||||
|
4047.23085 4.04E+08
|
||||||
|
4182.138545 4.27E+08
|
||||||
|
4317.04624 4.52E+08
|
||||||
|
4451.953935 4.76E+08
|
||||||
|
4586.86163 5.02E+08
|
||||||
|
4721.769325 5.27E+08
|
||||||
|
4856.67702 5.54E+08
|
||||||
|
4991.584715 5.80E+08
|
||||||
|
5126.49241 6.08E+08
|
||||||
|
5261.400105 6.35E+08
|
||||||
|
5396.3078 6.64E+08
|
||||||
|
5666.12319 7.21E+08
|
||||||
|
5935.93858 7.81E+08
|
||||||
|
6205.75397 8.42E+08
|
||||||
|
6475.56936 9.04E+08
|
||||||
|
6745.38475 9.69E+08
|
||||||
|
7015.20014 1.03E+09
|
||||||
|
7285.01553 1.10E+09
|
||||||
|
7554.83092 1.17E+09
|
||||||
|
7824.64631 1.24E+09
|
||||||
|
8094.4617 1.31E+09
|
||||||
|
8364.27709 1.39E+09
|
||||||
|
8634.09248 1.46E+09
|
||||||
|
8903.90787 1.54E+09
|
||||||
|
9173.72326 1.61E+09
|
||||||
|
9443.53865 1.69E+09
|
||||||
|
9713.35404 1.77E+09
|
||||||
|
9983.16943 1.85E+09
|
||||||
|
10252.98482 1.93E+09
|
||||||
|
10522.80021 2.02E+09
|
||||||
|
10792.6156 2.10E+09
|
||||||
|
11062.43099 2.18E+09
|
||||||
|
11332.24638 2.27E+09
|
||||||
|
11602.06177 2.36E+09
|
||||||
|
11871.87716 2.44E+09
|
||||||
|
12141.69255 2.53E+09
|
||||||
|
12411.50794 2.62E+09
|
||||||
|
12681.32333 2.71E+09
|
||||||
|
12951.13872 2.80E+09
|
||||||
|
13220.95411 2.89E+09
|
||||||
|
13490.7695 2.99E+09
|
||||||
|
14030.40028 3.18E+09
|
||||||
|
14570.03106 3.37E+09
|
||||||
|
15109.66184 3.56E+09
|
||||||
|
15649.29262 3.76E+09
|
||||||
|
16188.9234 3.96E+09
|
||||||
|
16728.55418 4.16E+09
|
||||||
|
17268.18496 4.36E+09
|
||||||
|
17807.81574 4.57E+09
|
||||||
|
18347.44652 4.78E+09
|
||||||
|
18887.0773 4.99E+09
|
||||||
|
19426.70808 5.20E+09
|
||||||
|
19966.33886 5.41E+09
|
||||||
|
20505.96964 5.63E+09
|
||||||
|
21045.60042 5.85E+09
|
||||||
|
21585.2312 6.07E+09
|
||||||
|
22124.86198 6.29E+09
|
||||||
|
22664.49276 6.51E+09
|
||||||
|
23204.12354 6.74E+09
|
||||||
|
23743.75432 6.96E+09
|
||||||
|
24283.3851 7.19E+09
|
||||||
|
24823.01588 7.42E+09
|
||||||
|
25362.64666 7.65E+09
|
||||||
|
25902.27744 7.88E+09
|
||||||
|
26441.90822 8.11E+09
|
||||||
|
26981.539 8.34E+09
|
||||||
|
27521.16978 8.57E+09
|
||||||
|
28060.80056 8.81E+09
|
||||||
|
28600.43134 9.04E+09
|
||||||
|
29140.06212 9.28E+09
|
||||||
|
29679.6929 9.52E+09
|
||||||
|
30219.32368 9.75E+09
|
||||||
|
30758.95446 9.99E+09
|
||||||
|
31298.58524 1.02E+10
|
||||||
|
31838.21602 1.05E+10
|
||||||
|
32377.8468 1.07E+10
|
||||||
|
32917.47758 1.10E+10
|
||||||
|
33457.10836 1.12E+10
|
||||||
|
33996.73914 1.14E+10
|
||||||
|
34536.36992 1.17E+10
|
||||||
|
35076.0007 1.19E+10
|
||||||
|
35615.63148 1.22E+10
|
||||||
|
36155.26226 1.24E+10
|
||||||
|
36694.89304 1.27E+10
|
||||||
|
37234.52382 1.29E+10
|
||||||
|
37774.1546 1.31E+10
|
||||||
|
38313.78538 1.34E+10
|
||||||
|
38853.41616 1.36E+10
|
||||||
|
39393.04694 1.39E+10
|
||||||
|
39932.67772 1.41E+10
|
||||||
|
40472.3085 1.44E+10
|
||||||
|
41011.93928 1.46E+10
|
||||||
|
41551.57006 1.49E+10
|
||||||
|
42091.20084 1.51E+10
|
||||||
|
42630.83162 1.54E+10
|
||||||
|
43170.4624 1.56E+10
|
||||||
|
43710.09318 1.59E+10
|
||||||
|
44249.72396 1.61E+10
|
||||||
|
44789.35474 1.64E+10
|
||||||
|
45328.98552 1.66E+10
|
||||||
|
45868.6163 1.69E+10
|
||||||
|
47217.69325 1.75E+10
|
||||||
|
48566.7702 1.81E+10
|
||||||
|
49915.84715 1.87E+10
|
||||||
|
51264.9241 1.94E+10
|
||||||
|
52614.00105 2.00E+10
|
||||||
|
53963.078 2.06E+10
|
||||||
|
56661.2319 2.19E+10
|
||||||
|
59359.3858 2.31E+10
|
||||||
|
62057.5397 2.43E+10
|
||||||
|
64755.6936 2.56E+10
|
||||||
|
67453.8475 2.68E+10
|
||||||
|
70152.0014 2.80E+10
|
||||||
|
72850.1553 2.93E+10
|
||||||
|
75548.3092 3.05E+10
|
||||||
|
78246.4631 3.17E+10
|
||||||
|
80944.617 3.29E+10
|
||||||
|
86340.9248 3.53E+10
|
||||||
|
91737.2326 3.76E+10
|
||||||
|
97133.5404 4.00E+10
|
||||||
|
102529.8482 4.23E+10
|
||||||
|
107926.156 4.46E+10
|
||||||
|
113322.4638 4.68E+10
|
||||||
|
118718.7716 4.90E+10
|
||||||
|
124115.0794 5.12E+10
|
||||||
|
129511.3872 5.34E+10
|
||||||
|
134907.695 5.55E+10
|
||||||
|
141653.0798 5.82E+10
|
||||||
|
148398.4645 6.07E+10
|
||||||
|
161889.234 6.58E+10
|
||||||
|
175380.0035 7.07E+10
|
||||||
|
188870.773 7.54E+10
|
||||||
|
202361.5425 8.00E+10
|
||||||
|
215852.312 8.45E+10
|
||||||
|
229343.0815 8.88E+10
|
||||||
|
242833.851 9.30E+10
|
||||||
|
256324.6205 9.71E+10
|
||||||
|
269815.39 1.01E+11
|
||||||
|
296796.929 1.09E+11
|
||||||
|
323778.468 1.16E+11
|
||||||
|
350760.007 1.23E+11
|
||||||
|
377741.546 1.30E+11
|
||||||
|
404723.085 1.36E+11
|
||||||
|
431704.624 1.42E+11
|
||||||
|
458686.163 1.48E+11
|
||||||
|
485667.702 1.53E+11
|
||||||
|
512649.241 1.59E+11
|
||||||
|
539630.78 1.64E+11
|
||||||
|
566612.319 1.69E+11
|
||||||
|
593593.858 1.74E+11
|
||||||
|
620575.397 1.79E+11
|
||||||
|
647556.936 1.83E+11
|
||||||
|
674538.475 1.88E+11
|
||||||
|
701520.014 1.92E+11
|
||||||
|
728501.553 1.96E+11
|
||||||
|
755483.092 2.00E+11
|
||||||
|
782464.631 2.04E+11
|
||||||
|
809446.17 2.08E+11
|
||||||
|
863409.248 2.16E+11
|
||||||
|
917372.326 2.23E+11
|
||||||
|
971335.404 2.29E+11
|
||||||
|
1025298.482 2.36E+11
|
||||||
|
1079261.56 2.42E+11
|
||||||
|
1133224.638 2.48E+11
|
||||||
|
1187187.716 2.54E+11
|
||||||
|
1241150.794 2.59E+11
|
||||||
|
1295113.872 2.65E+11
|
||||||
|
1349076.95 2.70E+11
|
||||||
345
ELoss/Eloss_alpha
Normal file
345
ELoss/Eloss_alpha
Normal file
|
|
@ -0,0 +1,345 @@
|
||||||
|
0.053103695 11959.9
|
||||||
|
0.116582129 19201.1
|
||||||
|
0.180060563 24466.2
|
||||||
|
0.243538998 28696
|
||||||
|
0.307017432 32395.8
|
||||||
|
0.370495866 35815.8
|
||||||
|
0.4339739 39049.4
|
||||||
|
0.497451133 42211.1
|
||||||
|
0.560932369 45315.6
|
||||||
|
0.624409603 48392.9
|
||||||
|
0.687886836 51473.4
|
||||||
|
0.751368072 54567.7
|
||||||
|
0.814845305 57693.8
|
||||||
|
0.878322539 60883.5
|
||||||
|
0.941803775 64073.2
|
||||||
|
1.005281008 67274.6
|
||||||
|
1.068758242 70625.6
|
||||||
|
1.132235475 73976.6
|
||||||
|
1.195716711 77327.7
|
||||||
|
1.259193944 80859
|
||||||
|
1.322671178 84405.9
|
||||||
|
1.386152414 87952.9
|
||||||
|
1.449629647 91666.6
|
||||||
|
1.513106881 95430.9
|
||||||
|
1.576588117 99195.1
|
||||||
|
1.64006535 103102
|
||||||
|
1.703542583 107097
|
||||||
|
1.767019817 111093
|
||||||
|
1.830501053 115200
|
||||||
|
1.893978286 119436
|
||||||
|
1.95745552 123672
|
||||||
|
2.020936756 128023
|
||||||
|
2.084413989 132632
|
||||||
|
2.147891222 137241
|
||||||
|
2.211372458 141849
|
||||||
|
2.274849692 146458
|
||||||
|
2.338326925 151067
|
||||||
|
2.401804159 155677
|
||||||
|
2.465285395 160793
|
||||||
|
2.528762628 165908
|
||||||
|
2.592239861 171023
|
||||||
|
2.655721097 176139
|
||||||
|
2.719198331 181254
|
||||||
|
2.782675564 186369
|
||||||
|
2.8461568 191841
|
||||||
|
2.909634034 197468
|
||||||
|
2.973111267 203094
|
||||||
|
3.0365885 208721
|
||||||
|
3.100069736 214347
|
||||||
|
3.16354697 219973
|
||||||
|
3.227024203 225800
|
||||||
|
3.290505439 231938
|
||||||
|
3.353982673 238075
|
||||||
|
3.417459906 244212
|
||||||
|
3.480941142 250349
|
||||||
|
3.544418375 256486
|
||||||
|
3.607895609 262668
|
||||||
|
3.671372842 269313
|
||||||
|
3.734854078 275958
|
||||||
|
3.798331312 282603
|
||||||
|
3.861808545 289248
|
||||||
|
3.925289781 295893
|
||||||
|
3.988767014 302538
|
||||||
|
4.05223224 309870
|
||||||
|
4.115713476 317394
|
||||||
|
4.179194712 324917
|
||||||
|
4.242675948 332441
|
||||||
|
4.306157184 339965
|
||||||
|
4.36963842 347488
|
||||||
|
4.433119656 355012
|
||||||
|
4.496600892 362535
|
||||||
|
4.560082128 370059
|
||||||
|
4.623563364 377583
|
||||||
|
4.6870446 385106
|
||||||
|
4.750525836 392630
|
||||||
|
4.813967046 400154
|
||||||
|
4.877448282 407677
|
||||||
|
4.940929518 415201
|
||||||
|
5.004410754 422747
|
||||||
|
5.06789199 431506
|
||||||
|
5.131373226 440265
|
||||||
|
5.194854462 449023
|
||||||
|
5.258335698 457782
|
||||||
|
5.321816934 466541
|
||||||
|
5.38529817 475299
|
||||||
|
5.448779406 484058
|
||||||
|
5.512260642 492817
|
||||||
|
5.575741878 501575
|
||||||
|
5.639223114 510334
|
||||||
|
5.70270435 519093
|
||||||
|
5.76614556 527851
|
||||||
|
5.829626796 536610
|
||||||
|
5.893108032 545369
|
||||||
|
5.956589268 554127
|
||||||
|
6.020070504 563195
|
||||||
|
6.08355174 573167
|
||||||
|
6.147032976 583139
|
||||||
|
6.210514212 593110
|
||||||
|
6.273995448 603082
|
||||||
|
6.337476684 613054
|
||||||
|
6.40095792 623026
|
||||||
|
6.464439156 632997
|
||||||
|
6.527920392 642969
|
||||||
|
6.591401628 652941
|
||||||
|
6.654842838 662913
|
||||||
|
6.718324074 672885
|
||||||
|
6.78180531 682856
|
||||||
|
6.845286546 692828
|
||||||
|
6.908767782 702800
|
||||||
|
6.972249018 712772
|
||||||
|
7.035730254 723331
|
||||||
|
7.09921149 734498
|
||||||
|
7.162692726 745666
|
||||||
|
7.226173962 756833
|
||||||
|
7.289655198 768000
|
||||||
|
7.353136434 779168
|
||||||
|
7.41661767 790335
|
||||||
|
7.480098906 801502
|
||||||
|
7.543540116 812670
|
||||||
|
7.607021352 823837
|
||||||
|
7.670502588 835004
|
||||||
|
7.733983824 846172
|
||||||
|
7.79746506 857339
|
||||||
|
7.860946296 868507
|
||||||
|
7.924427532 879674
|
||||||
|
7.987908768 890841
|
||||||
|
8.051390004 902868
|
||||||
|
8.11487124 915217
|
||||||
|
8.178352476 927566
|
||||||
|
8.241833712 939915
|
||||||
|
8.305314948 952263
|
||||||
|
8.368796184 964612
|
||||||
|
8.43227742 976961
|
||||||
|
8.49571863 989310
|
||||||
|
8.559199866 1.00E+06
|
||||||
|
8.622681102 1.01E+06
|
||||||
|
8.686162338 1.03E+06
|
||||||
|
8.749643574 1.04E+06
|
||||||
|
8.81312481 1.05E+06
|
||||||
|
8.876606046 1.06E+06
|
||||||
|
8.940087282 1.08E+06
|
||||||
|
9.003568518 1.09E+06
|
||||||
|
9.067049754 1.10E+06
|
||||||
|
9.13053099 1.12E+06
|
||||||
|
9.194012226 1.13E+06
|
||||||
|
9.257493462 1.14E+06
|
||||||
|
9.320974698 1.16E+06
|
||||||
|
9.384415908 1.17E+06
|
||||||
|
9.447897144 1.18E+06
|
||||||
|
9.51137838 1.20E+06
|
||||||
|
9.574859616 1.21E+06
|
||||||
|
9.638340852 1.22E+06
|
||||||
|
9.701822088 1.24E+06
|
||||||
|
9.765303324 1.25E+06
|
||||||
|
9.82878456 1.26E+06
|
||||||
|
9.892265796 1.28E+06
|
||||||
|
9.955747032 1.29E+06
|
||||||
|
10.01922827 1.30E+06
|
||||||
|
10.0827095 1.32E+06
|
||||||
|
10.14619074 1.34E+06
|
||||||
|
10.20967198 1.35E+06
|
||||||
|
10.27311319 1.37E+06
|
||||||
|
10.33659442 1.38E+06
|
||||||
|
10.40007566 1.40E+06
|
||||||
|
10.46355689 1.41E+06
|
||||||
|
10.52703813 1.43E+06
|
||||||
|
10.59051937 1.44E+06
|
||||||
|
10.6540006 1.46E+06
|
||||||
|
10.71748184 1.47E+06
|
||||||
|
10.78096307 1.49E+06
|
||||||
|
10.84444431 1.50E+06
|
||||||
|
10.90792555 1.52E+06
|
||||||
|
10.97140678 1.53E+06
|
||||||
|
11.03488802 1.55E+06
|
||||||
|
11.09836925 1.56E+06
|
||||||
|
11.16185049 1.58E+06
|
||||||
|
11.2252917 1.59E+06
|
||||||
|
11.28877294 1.61E+06
|
||||||
|
11.35225417 1.62E+06
|
||||||
|
11.41573541 1.64E+06
|
||||||
|
11.47921664 1.66E+06
|
||||||
|
11.54269788 1.67E+06
|
||||||
|
11.60617912 1.69E+06
|
||||||
|
11.66966035 1.70E+06
|
||||||
|
11.73314159 1.72E+06
|
||||||
|
11.79662282 1.73E+06
|
||||||
|
11.86010406 1.75E+06
|
||||||
|
11.9235853 1.76E+06
|
||||||
|
11.98706653 1.78E+06
|
||||||
|
12.05054777 1.79E+06
|
||||||
|
12.11398898 1.81E+06
|
||||||
|
12.17747021 1.83E+06
|
||||||
|
12.24095145 1.85E+06
|
||||||
|
12.30443269 1.86E+06
|
||||||
|
12.36791392 1.88E+06
|
||||||
|
12.43139516 1.90E+06
|
||||||
|
12.49487639 1.92E+06
|
||||||
|
12.55835763 1.93E+06
|
||||||
|
12.62183887 1.95E+06
|
||||||
|
12.6853201 1.97E+06
|
||||||
|
12.74880134 1.99E+06
|
||||||
|
12.81228257 2.00E+06
|
||||||
|
12.87576381 2.02E+06
|
||||||
|
12.93924505 2.04E+06
|
||||||
|
13.00268626 2.06E+06
|
||||||
|
13.06616749 2.07E+06
|
||||||
|
13.12964873 2.09E+06
|
||||||
|
13.19312996 2.11E+06
|
||||||
|
13.2566112 2.13E+06
|
||||||
|
13.32009244 2.14E+06
|
||||||
|
13.38357367 2.16E+06
|
||||||
|
13.44705491 2.18E+06
|
||||||
|
13.51053614 2.20E+06
|
||||||
|
13.57401738 2.22E+06
|
||||||
|
13.63749862 2.23E+06
|
||||||
|
13.70097985 2.25E+06
|
||||||
|
13.76446109 2.27E+06
|
||||||
|
13.82794232 2.29E+06
|
||||||
|
13.89142356 2.30E+06
|
||||||
|
13.95486477 2.32E+06
|
||||||
|
14.01834601 2.34E+06
|
||||||
|
14.08182724 2.36E+06
|
||||||
|
14.14530848 2.38E+06
|
||||||
|
14.20878971 2.40E+06
|
||||||
|
14.27227095 2.42E+06
|
||||||
|
14.33575219 2.44E+06
|
||||||
|
14.39923342 2.46E+06
|
||||||
|
14.46271466 2.48E+06
|
||||||
|
14.52619589 2.50E+06
|
||||||
|
14.58967713 2.52E+06
|
||||||
|
14.65315837 2.54E+06
|
||||||
|
14.7166396 2.56E+06
|
||||||
|
14.78012084 2.58E+06
|
||||||
|
14.84356205 2.60E+06
|
||||||
|
14.90704328 2.62E+06
|
||||||
|
14.97052452 2.63E+06
|
||||||
|
15.03400576 2.65E+06
|
||||||
|
15.09748699 2.67E+06
|
||||||
|
15.16096823 2.69E+06
|
||||||
|
15.22444946 2.71E+06
|
||||||
|
15.2879307 2.73E+06
|
||||||
|
15.35141194 2.75E+06
|
||||||
|
15.41489317 2.77E+06
|
||||||
|
15.47837441 2.79E+06
|
||||||
|
15.54185564 2.81E+06
|
||||||
|
15.60533688 2.83E+06
|
||||||
|
15.66881812 2.85E+06
|
||||||
|
15.73225933 2.87E+06
|
||||||
|
15.79574056 2.89E+06
|
||||||
|
15.8592218 2.91E+06
|
||||||
|
15.92270303 2.93E+06
|
||||||
|
15.98618427 2.95E+06
|
||||||
|
16.04966551 2.97E+06
|
||||||
|
16.11314674 2.99E+06
|
||||||
|
16.17662798 3.02E+06
|
||||||
|
16.24010921 3.04E+06
|
||||||
|
16.30359045 3.06E+06
|
||||||
|
16.36707169 3.08E+06
|
||||||
|
16.43055292 3.10E+06
|
||||||
|
16.49403416 3.13E+06
|
||||||
|
16.55751539 3.15E+06
|
||||||
|
16.6209566 3.17E+06
|
||||||
|
16.68443784 3.19E+06
|
||||||
|
16.74791908 3.21E+06
|
||||||
|
16.81140031 3.24E+06
|
||||||
|
16.87488155 3.26E+06
|
||||||
|
16.93836278 3.28E+06
|
||||||
|
17.00184402 3.30E+06
|
||||||
|
17.06532526 3.32E+06
|
||||||
|
17.12880649 3.35E+06
|
||||||
|
17.19228773 3.37E+06
|
||||||
|
17.25576896 3.39E+06
|
||||||
|
17.3192502 3.41E+06
|
||||||
|
17.38273144 3.43E+06
|
||||||
|
17.44621267 3.46E+06
|
||||||
|
17.50969391 3.48E+06
|
||||||
|
17.57313512 3.50E+06
|
||||||
|
17.63661635 3.52E+06
|
||||||
|
17.70009759 3.54E+06
|
||||||
|
17.76357883 3.57E+06
|
||||||
|
17.82706006 3.59E+06
|
||||||
|
17.8905413 3.61E+06
|
||||||
|
17.95402253 3.63E+06
|
||||||
|
18.01750377 3.65E+06
|
||||||
|
18.08098501 3.68E+06
|
||||||
|
18.14446624 3.70E+06
|
||||||
|
18.20794748 3.73E+06
|
||||||
|
18.27142871 3.75E+06
|
||||||
|
18.33490995 3.78E+06
|
||||||
|
18.39839119 3.80E+06
|
||||||
|
18.4618324 3.82E+06
|
||||||
|
18.52531363 3.85E+06
|
||||||
|
18.58879487 3.87E+06
|
||||||
|
18.6522761 3.90E+06
|
||||||
|
18.71575734 3.92E+06
|
||||||
|
18.77923858 3.95E+06
|
||||||
|
18.84271981 3.97E+06
|
||||||
|
18.90620105 3.99E+06
|
||||||
|
18.96968228 4.02E+06
|
||||||
|
19.03316352 4.04E+06
|
||||||
|
19.09664476 4.07E+06
|
||||||
|
19.16012599 4.09E+06
|
||||||
|
19.22360723 4.11E+06
|
||||||
|
19.28708846 4.14E+06
|
||||||
|
19.35052967 4.16E+06
|
||||||
|
19.41401091 4.19E+06
|
||||||
|
19.47749215 4.21E+06
|
||||||
|
19.54097338 4.24E+06
|
||||||
|
19.60445462 4.26E+06
|
||||||
|
19.66793585 4.28E+06
|
||||||
|
19.73141709 4.31E+06
|
||||||
|
19.79489833 4.33E+06
|
||||||
|
19.85837956 4.36E+06
|
||||||
|
19.9218608 4.38E+06
|
||||||
|
19.98534203 4.41E+06
|
||||||
|
20.04882327 4.43E+06
|
||||||
|
20.11230451 4.46E+06
|
||||||
|
20.17578574 4.48E+06
|
||||||
|
20.23926698 4.51E+06
|
||||||
|
20.30270819 4.54E+06
|
||||||
|
20.36618942 4.56E+06
|
||||||
|
20.42967066 4.59E+06
|
||||||
|
20.4931519 4.62E+06
|
||||||
|
20.55663313 4.64E+06
|
||||||
|
20.62011437 4.67E+06
|
||||||
|
20.6835956 4.69E+06
|
||||||
|
20.74707684 4.72E+06
|
||||||
|
20.81055808 4.75E+06
|
||||||
|
20.87403931 4.77E+06
|
||||||
|
20.93752055 4.80E+06
|
||||||
|
21.00100178 4.83E+06
|
||||||
|
21.06448302 4.85E+06
|
||||||
|
21.12796426 4.88E+06
|
||||||
|
21.19140547 4.91E+06
|
||||||
|
21.2548867 4.93E+06
|
||||||
|
21.31836794 4.96E+06
|
||||||
|
21.38184917 4.98E+06
|
||||||
|
21.44533041 5.01E+06
|
||||||
|
21.50881165 5.04E+06
|
||||||
|
21.57229288 5.06E+06
|
||||||
|
21.63577412 5.09E+06
|
||||||
|
21.69925535 5.12E+06
|
||||||
|
21.76273659 5.14E+06
|
||||||
|
21.82621783 5.17E+06
|
||||||
|
21.88969906 5.20E+06
|
||||||
268
ELoss/Eloss_p
Normal file
268
ELoss/Eloss_p
Normal file
|
|
@ -0,0 +1,268 @@
|
||||||
|
0.00100784 0.00455783
|
||||||
|
0.00201568 0.00911567
|
||||||
|
0.0050392 0.0197891
|
||||||
|
0.00806272 0.0284591
|
||||||
|
0.0100784 0.0336328
|
||||||
|
0.0151176 0.0449321
|
||||||
|
0.0201568 0.0545806
|
||||||
|
0.025196 0.0631952
|
||||||
|
0.0302352 0.071111
|
||||||
|
0.0352744 0.0785363
|
||||||
|
0.0403136 0.0856119
|
||||||
|
0.0453528 0.0924397
|
||||||
|
0.050392 0.0990962
|
||||||
|
0.0554312 0.105641
|
||||||
|
0.0604704 0.112122
|
||||||
|
0.0705488 0.125041
|
||||||
|
0.0806272 0.138091
|
||||||
|
0.0907056 0.151435
|
||||||
|
0.100784 0.16519
|
||||||
|
0.1209408 0.194217
|
||||||
|
0.1410976 0.225513
|
||||||
|
0.1612544 0.25917
|
||||||
|
0.1814112 0.295144
|
||||||
|
0.201568 0.333333
|
||||||
|
0.25196 0.4377
|
||||||
|
0.302352 0.55345
|
||||||
|
0.352744 0.679377
|
||||||
|
0.403136 0.814707
|
||||||
|
0.453528 0.958947
|
||||||
|
0.50392 1.11177
|
||||||
|
0.604704 1.44231
|
||||||
|
0.705488 1.80513
|
||||||
|
0.806272 2.19946
|
||||||
|
0.907056 2.62475
|
||||||
|
1.00784 3.08057
|
||||||
|
1.2598 4.35139
|
||||||
|
1.51176 5.80613
|
||||||
|
1.76372 7.44108
|
||||||
|
2.01568 9.25315
|
||||||
|
2.26764 11.2397
|
||||||
|
2.5196 13.3984
|
||||||
|
3.02352 18.2246
|
||||||
|
3.52744 23.7179
|
||||||
|
4.03136 29.8671
|
||||||
|
4.53528 36.6625
|
||||||
|
5.0392 44.0961
|
||||||
|
5.54312 52.1607
|
||||||
|
6.04704 60.8501
|
||||||
|
6.55096 70.1587
|
||||||
|
7.05488 80.0814
|
||||||
|
7.5588 90.6136
|
||||||
|
8.06272 101.751
|
||||||
|
8.56664 113.49
|
||||||
|
9.07056 125.827
|
||||||
|
9.57448 138.759
|
||||||
|
10.0784 152.267
|
||||||
|
11.08624 180.081
|
||||||
|
12.09408 209.992
|
||||||
|
13.10192 241.974
|
||||||
|
14.10976 276.006
|
||||||
|
15.1176 312.066
|
||||||
|
16.12544 350.134
|
||||||
|
17.13328 390.189
|
||||||
|
18.14112 432.214
|
||||||
|
19.14896 476.19
|
||||||
|
20.1568 522.101
|
||||||
|
21.16464 569.93
|
||||||
|
22.17248 619.661
|
||||||
|
23.18032 671.279
|
||||||
|
24.18816 724.77
|
||||||
|
25.196 780.118
|
||||||
|
27.21168 896.334
|
||||||
|
29.22736 1019.82
|
||||||
|
31.24304 1150.48
|
||||||
|
33.25872 1288.2
|
||||||
|
35.2744 1432.91
|
||||||
|
38.29792 1662.88
|
||||||
|
41.32144 1908.07
|
||||||
|
44.34496 2168.23
|
||||||
|
47.36848 2443.1
|
||||||
|
50.392 2732.43
|
||||||
|
55.4312 3246.18
|
||||||
|
60.4704 3798.47
|
||||||
|
65.5096 4388.33
|
||||||
|
70.5488 5014.87
|
||||||
|
75.588 5677.25
|
||||||
|
80.6272 6374.65
|
||||||
|
85.6664 7106.3
|
||||||
|
90.7056 7871.46
|
||||||
|
95.7448 8669.43
|
||||||
|
100.784 9499.52
|
||||||
|
105.8232 10361.1
|
||||||
|
110.8624 11253.5
|
||||||
|
115.9016 12176.2
|
||||||
|
120.9408 13128.5
|
||||||
|
125.98 14109.9
|
||||||
|
131.0192 15119.8
|
||||||
|
136.0584 16157.8
|
||||||
|
141.0976 17223.3
|
||||||
|
146.1368 18315.7
|
||||||
|
151.176 19434.7
|
||||||
|
156.2152 20579.8
|
||||||
|
161.2544 21750.4
|
||||||
|
166.2936 22946.2
|
||||||
|
171.3328 24166.7
|
||||||
|
176.372 25411.6
|
||||||
|
181.4112 26680.3
|
||||||
|
186.4504 27972.5
|
||||||
|
191.4896 29287.8
|
||||||
|
196.5288 30625.8
|
||||||
|
201.568 31986.2
|
||||||
|
211.6464 34772.7
|
||||||
|
221.7248 37644.4
|
||||||
|
231.8032 40598.6
|
||||||
|
241.8816 43632.8
|
||||||
|
251.96 46744.7
|
||||||
|
262.0384 49931.8
|
||||||
|
272.1168 53192
|
||||||
|
282.1952 56523.1
|
||||||
|
292.2736 59923.1
|
||||||
|
302.352 63390
|
||||||
|
312.4304 66921.8
|
||||||
|
322.5088 70516.9
|
||||||
|
332.5872 74173.4
|
||||||
|
342.6656 77889.7
|
||||||
|
352.744 81664
|
||||||
|
362.8224 85494.9
|
||||||
|
372.9008 89380.9
|
||||||
|
382.9792 93320.4
|
||||||
|
393.0576 97312.1
|
||||||
|
403.136 101355
|
||||||
|
413.2144 105447
|
||||||
|
423.2928 109587
|
||||||
|
433.3712 113774
|
||||||
|
443.4496 118007
|
||||||
|
453.528 122284
|
||||||
|
463.6064 126605
|
||||||
|
473.6848 130969
|
||||||
|
483.7632 135373
|
||||||
|
493.8416 139818
|
||||||
|
503.92 144303
|
||||||
|
524.0768 153386
|
||||||
|
544.2336 162615
|
||||||
|
564.3904 171984
|
||||||
|
584.5472 181485
|
||||||
|
604.704 191113
|
||||||
|
624.8608 200861
|
||||||
|
645.0176 210724
|
||||||
|
665.1744 220697
|
||||||
|
685.3312 230775
|
||||||
|
705.488 240953
|
||||||
|
725.6448 251226
|
||||||
|
745.8016 261591
|
||||||
|
765.9584 272043
|
||||||
|
786.1152 282578
|
||||||
|
806.272 293192
|
||||||
|
826.4288 303883
|
||||||
|
846.5856 314646
|
||||||
|
866.7424 325478
|
||||||
|
886.8992 336377
|
||||||
|
907.056 347338
|
||||||
|
927.2128 358361
|
||||||
|
947.3696 369441
|
||||||
|
967.5264 380577
|
||||||
|
987.6832 391765
|
||||||
|
1007.84 403003
|
||||||
|
1027.9968 414290
|
||||||
|
1048.1536 425622
|
||||||
|
1068.3104 436998
|
||||||
|
1088.4672 448416
|
||||||
|
1108.624 459874
|
||||||
|
1128.7808 471370
|
||||||
|
1148.9376 482902
|
||||||
|
1169.0944 494468
|
||||||
|
1189.2512 506067
|
||||||
|
1209.408 517698
|
||||||
|
1229.5648 529358
|
||||||
|
1249.7216 541047
|
||||||
|
1269.8784 552762
|
||||||
|
1290.0352 564502
|
||||||
|
1310.192 576267
|
||||||
|
1330.3488 588055
|
||||||
|
1350.5056 599864
|
||||||
|
1370.6624 611694
|
||||||
|
1390.8192 623543
|
||||||
|
1410.976 635410
|
||||||
|
1431.1328 647295
|
||||||
|
1451.2896 659195
|
||||||
|
1471.4464 671111
|
||||||
|
1491.6032 683041
|
||||||
|
1511.76 694984
|
||||||
|
1531.9168 706940
|
||||||
|
1552.0736 718907
|
||||||
|
1572.2304 730885
|
||||||
|
1592.3872 742872
|
||||||
|
1612.544 754869
|
||||||
|
1632.7008 766874
|
||||||
|
1652.8576 778887
|
||||||
|
1673.0144 790907
|
||||||
|
1693.1712 802933
|
||||||
|
1713.328 814964
|
||||||
|
1763.72 845063
|
||||||
|
1814.112 875184
|
||||||
|
1864.504 905318
|
||||||
|
1914.896 935457
|
||||||
|
1965.288 965594
|
||||||
|
2015.68 995721
|
||||||
|
2116.464 1.06E+06
|
||||||
|
2217.248 1.12E+06
|
||||||
|
2318.032 1.18E+06
|
||||||
|
2418.816 1.24E+06
|
||||||
|
2519.6 1.30E+06
|
||||||
|
2620.384 1.35E+06
|
||||||
|
2721.168 1.41E+06
|
||||||
|
2821.952 1.47E+06
|
||||||
|
2922.736 1.53E+06
|
||||||
|
3023.52 1.59E+06
|
||||||
|
3225.088 1.70E+06
|
||||||
|
3426.656 1.82E+06
|
||||||
|
3628.224 1.93E+06
|
||||||
|
3829.792 2.04E+06
|
||||||
|
4031.36 2.15E+06
|
||||||
|
4232.928 2.26E+06
|
||||||
|
4434.496 2.37E+06
|
||||||
|
4636.064 2.48E+06
|
||||||
|
4837.632 2.58E+06
|
||||||
|
5039.2 2.68E+06
|
||||||
|
5291.16 2.81E+06
|
||||||
|
5543.12 2.94E+06
|
||||||
|
6047.04 3.18E+06
|
||||||
|
6550.96 3.42E+06
|
||||||
|
7054.88 3.64E+06
|
||||||
|
7558.8 3.87E+06
|
||||||
|
8062.72 4.08E+06
|
||||||
|
8566.64 4.29E+06
|
||||||
|
9070.56 4.49E+06
|
||||||
|
9574.48 4.69E+06
|
||||||
|
10078.4 4.88E+06
|
||||||
|
11086.24 5.25E+06
|
||||||
|
12094.08 5.61E+06
|
||||||
|
13101.92 5.94E+06
|
||||||
|
14109.76 6.26E+06
|
||||||
|
15117.6 6.57E+06
|
||||||
|
16125.44 6.86E+06
|
||||||
|
17133.28 7.14E+06
|
||||||
|
18141.12 7.41E+06
|
||||||
|
19148.96 7.67E+06
|
||||||
|
20156.8 7.93E+06
|
||||||
|
21164.64 8.17E+06
|
||||||
|
22172.48 8.41E+06
|
||||||
|
23180.32 8.63E+06
|
||||||
|
24188.16 8.86E+06
|
||||||
|
25196 9.07E+06
|
||||||
|
26203.84 9.28E+06
|
||||||
|
27211.68 9.48E+06
|
||||||
|
28219.52 9.68E+06
|
||||||
|
29227.36 9.87E+06
|
||||||
|
30235.2 1.01E+07
|
||||||
|
32250.88 1.04E+07
|
||||||
|
34266.56 1.08E+07
|
||||||
|
36282.24 1.11E+07
|
||||||
|
38297.92 1.14E+07
|
||||||
|
40313.6 1.17E+07
|
||||||
|
42329.28 1.20E+07
|
||||||
|
44344.96 1.23E+07
|
||||||
|
46360.64 1.25E+07
|
||||||
|
48376.32 1.28E+07
|
||||||
|
50392 1.30E+07
|
||||||
124
FitHistogramsWithTSpectrum_Sequential_Improved.C
Normal file
124
FitHistogramsWithTSpectrum_Sequential_Improved.C
Normal file
|
|
@ -0,0 +1,124 @@
|
||||||
|
#include <TFile.h>
|
||||||
|
#include <TH1.h>
|
||||||
|
#include <TSpectrum.h>
|
||||||
|
#include <TF1.h>
|
||||||
|
#include <TCanvas.h>
|
||||||
|
#include <vector>
|
||||||
|
#include <iostream>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <fstream>
|
||||||
|
#include <TText.h>
|
||||||
|
|
||||||
|
void FitHistogramsWithTSpectrum_Sequential_Improved() {
|
||||||
|
TFile *inputFile = new TFile("Histograms_anodes.root", "READ");
|
||||||
|
if (!inputFile || inputFile->IsZombie()) {
|
||||||
|
std::cerr << "Error opening the input file!" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
TCanvas *c1 = new TCanvas("c1", "Histogram Viewer", 800, 600);
|
||||||
|
|
||||||
|
// Open the output ASCII file to save the centroids
|
||||||
|
std::ofstream outFile("centroids.txt");
|
||||||
|
if (!outFile.is_open()) {
|
||||||
|
std::cerr << "Error opening output file!" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
outFile << "HistogramIndex\tPeakNumber\tCentroid\tAmplitude\tSigma" << std::endl;
|
||||||
|
|
||||||
|
for (int i = 0; i < 24; ++i) {
|
||||||
|
TH1 *histogram = dynamic_cast<TH1*>(inputFile->Get(Form("hCathode_%d", i)));
|
||||||
|
if (!histogram) {
|
||||||
|
std::cerr << "Failed to retrieve histogram_" << i << " from the file." << std::endl;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set range for peak search
|
||||||
|
double minX = 700;
|
||||||
|
double maxX = 25000;
|
||||||
|
histogram->GetXaxis()->SetRangeUser(minX, maxX);
|
||||||
|
|
||||||
|
// Draw the histogram
|
||||||
|
c1->cd();
|
||||||
|
histogram->Draw();
|
||||||
|
|
||||||
|
// Peak search using TSpectrum
|
||||||
|
const int maxPeaks = 5;
|
||||||
|
TSpectrum spectrumFinder(maxPeaks);
|
||||||
|
int nFound = spectrumFinder.Search(histogram, 2, "", 0.01);
|
||||||
|
|
||||||
|
if (nFound <= 0) {
|
||||||
|
std::cerr << "No peaks found for histogram " << i << std::endl;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Double_t *xPositions = spectrumFinder.GetPositionX();
|
||||||
|
Double_t *yPositions = spectrumFinder.GetPositionY();
|
||||||
|
std::vector<std::pair<Double_t, Double_t>> peaks;
|
||||||
|
|
||||||
|
// Collect and sort peaks by X position
|
||||||
|
for (int j = 0; j < nFound; ++j) {
|
||||||
|
peaks.emplace_back(xPositions[j], yPositions[j]);
|
||||||
|
}
|
||||||
|
std::sort(peaks.begin(), peaks.end());
|
||||||
|
|
||||||
|
// Fit each peak with a Gaussian
|
||||||
|
for (int j = 0; j < peaks.size(); ++j) {
|
||||||
|
Double_t peakX = peaks[j].first;
|
||||||
|
Double_t peakY = peaks[j].second;
|
||||||
|
Double_t initialAmplitude = peakY; // Better initial guess
|
||||||
|
Double_t initialCentroid = peakX; // Centroid based on peak position
|
||||||
|
Double_t initialSigma = 60.0;
|
||||||
|
// Define Gaussian with initial parameters
|
||||||
|
TF1 *gaussFit = new TF1(Form("gauss_%d", j), "gaus", peakX - 200, peakX + 200);
|
||||||
|
//gaussFit->SetParameters(peakY, peakX, 25.0); // Initial guesses for amplitude, mean, sigma
|
||||||
|
gaussFit->SetParameters(initialAmplitude, initialCentroid, initialSigma);
|
||||||
|
// Perform fit
|
||||||
|
int fitStatus = histogram->Fit(gaussFit, "RQ+");
|
||||||
|
if (fitStatus != 0) {
|
||||||
|
std::cerr << "Fit failed for peak " << j + 1 << " in histogram " << i << std::endl;
|
||||||
|
delete gaussFit;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Retrieve fit parameters
|
||||||
|
double amplitude = gaussFit->GetParameter(0);
|
||||||
|
double centroid = gaussFit->GetParameter(1);
|
||||||
|
double sigma = gaussFit->GetParameter(2);
|
||||||
|
double amplitudeError = gaussFit->GetParError(0);
|
||||||
|
double centroidError = gaussFit->GetParError(1);
|
||||||
|
double sigmaError = gaussFit->GetParError(2);
|
||||||
|
|
||||||
|
// Chi-squared value
|
||||||
|
double chi2 = gaussFit->GetChisquare();
|
||||||
|
int ndf = gaussFit->GetNDF();
|
||||||
|
outFile << i << "\t" << j + 1 << "\t" << centroid << std::endl;
|
||||||
|
gaussFit->SetLineColor(kRed);
|
||||||
|
gaussFit->Draw("SAME");
|
||||||
|
TText *text = new TText();
|
||||||
|
text->SetNDC();
|
||||||
|
text->SetTextSize(0.03);
|
||||||
|
text->SetTextColor(kRed);
|
||||||
|
//text->DrawText(0.15, 0.8 - j * 0.05, Form("Peak %d: Amp=%.2f, Mean=%.2f, Sigma=%.2f", j + 1, amplitude, centroid, sigma));
|
||||||
|
text->DrawText(0.15, 0.8 - j * 0.05,
|
||||||
|
Form("Peak %d: Amp=%.2f±%.2f, Mean=%.2f±%.2f, Sigma=%.2f±%.2f, Chi2/NDF=%.2f",
|
||||||
|
j + 1, amplitude, amplitudeError, centroid, centroidError, sigma, sigmaError, chi2 / ndf));
|
||||||
|
// Save results
|
||||||
|
|
||||||
|
|
||||||
|
// Clean up
|
||||||
|
delete gaussFit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update canvas for visualization
|
||||||
|
c1->Update();
|
||||||
|
std::cout << "Press Enter to view the next histogram..." << std::endl;
|
||||||
|
c1->WaitPrimitive(); // Wait until Enter is pressed in the ROOT console
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close resources
|
||||||
|
inputFile->Close();
|
||||||
|
outFile.close();
|
||||||
|
delete c1;
|
||||||
|
}
|
||||||
|
|
||||||
309
GainMatchQQQ.C
Normal file
309
GainMatchQQQ.C
Normal file
|
|
@ -0,0 +1,309 @@
|
||||||
|
#define GainMatchQQQ_cxx
|
||||||
|
|
||||||
|
#include "GainMatchQQQ.h"
|
||||||
|
#include <TH2.h>
|
||||||
|
#include <TF1.h>
|
||||||
|
#include <TStyle.h>
|
||||||
|
#include <TCanvas.h>
|
||||||
|
#include <TMath.h>
|
||||||
|
#include <TCutG.h>
|
||||||
|
#include <fstream>
|
||||||
|
#include <utility>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <cmath>
|
||||||
|
#include <numeric>
|
||||||
|
#include "Armory/HistPlotter.h"
|
||||||
|
#include "TVector3.h"
|
||||||
|
#include "TGraphErrors.h"
|
||||||
|
#include "TF1.h"
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
TH2F *hQQQFVB;
|
||||||
|
HistPlotter *plotter;
|
||||||
|
|
||||||
|
int padID = 0;
|
||||||
|
|
||||||
|
TCutG *cut;
|
||||||
|
std::map<std::tuple<int, int, int>, std::vector<std::pair<double, double>>> dataPoints;
|
||||||
|
|
||||||
|
void GainMatchQQQ::Begin(TTree * /*tree*/)
|
||||||
|
{
|
||||||
|
plotter = new HistPlotter("GainQQQ.root", "TFILE");
|
||||||
|
TString option = GetOption();
|
||||||
|
|
||||||
|
hQQQFVB = new TH2F("hQQQFVB", "QQQ Front vs Back; Front E; Back E", 800, 0, 16000, 800, 0, 16000);
|
||||||
|
|
||||||
|
// Load the TCutG object
|
||||||
|
TFile *cutFile = TFile::Open("qqqcorr.root");
|
||||||
|
if (!cutFile || cutFile->IsZombie())
|
||||||
|
{
|
||||||
|
std::cerr << "Error: Could not open qqqcorr.root" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cut = dynamic_cast<TCutG *>(cutFile->Get("qqqcorr"));
|
||||||
|
if (!cut)
|
||||||
|
{
|
||||||
|
std::cerr << "Error: Could not find TCutG named 'qqqcorr' in qqqcorr.root" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cut->SetName("qqqcorr"); // Ensure the cut has the correct name
|
||||||
|
}
|
||||||
|
|
||||||
|
Bool_t GainMatchQQQ::Process(Long64_t entry)
|
||||||
|
{
|
||||||
|
|
||||||
|
int ringMults[16] = {0};
|
||||||
|
int wedgeMults[16] = {0};
|
||||||
|
std::vector<std::tuple<int, int, int, double, double>> events;
|
||||||
|
|
||||||
|
b_qqqMulti->GetEntry(entry);
|
||||||
|
b_qqqID->GetEntry(entry);
|
||||||
|
b_qqqCh->GetEntry(entry);
|
||||||
|
b_qqqE->GetEntry(entry);
|
||||||
|
b_qqqT->GetEntry(entry);
|
||||||
|
|
||||||
|
qqq.CalIndex();
|
||||||
|
|
||||||
|
for (int i = 0; i < qqq.multi; i++)
|
||||||
|
{
|
||||||
|
for (int j = i + 1; j < qqq.multi; j++)
|
||||||
|
{
|
||||||
|
if (qqq.id[i] == qqq.id[j])
|
||||||
|
{
|
||||||
|
int chWedge = -1;
|
||||||
|
int chRing = -1;
|
||||||
|
float eWedge = 0.0;
|
||||||
|
float eRing = 0.0;
|
||||||
|
if (qqq.ch[i] < 16 && qqq.ch[j] >= 16)
|
||||||
|
{
|
||||||
|
chWedge = qqq.ch[i];
|
||||||
|
eWedge = qqq.e[i];
|
||||||
|
chRing = qqq.ch[j] - 16;
|
||||||
|
eRing = qqq.e[j];
|
||||||
|
}
|
||||||
|
else if (qqq.ch[j] < 16 && qqq.ch[i] >= 16)
|
||||||
|
{
|
||||||
|
chWedge = qqq.ch[j];
|
||||||
|
eWedge = qqq.e[j];
|
||||||
|
chRing = qqq.ch[i] - 16;
|
||||||
|
eRing = qqq.e[i];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
continue;
|
||||||
|
ringMults[chRing]++;
|
||||||
|
wedgeMults[chWedge]++;
|
||||||
|
hQQQFVB->Fill(eWedge, eRing);
|
||||||
|
events.emplace_back(qqq.id[i], chRing, chWedge, eRing, eWedge);
|
||||||
|
plotter->Fill2D(Form("hRaw_qqq%d_ring%d_wedge%d", qqq.id[i], chRing, chWedge), 800, 0, 3000, 800, 0, 3000, eWedge, eRing, "hRawQQQ");
|
||||||
|
// double ratio = (eWedge > 0.0) ? (eRing / eWedge) : 0.0;
|
||||||
|
// double maxslope = 1.5;
|
||||||
|
|
||||||
|
// bool validPoint = false;
|
||||||
|
// if (ratio < maxslope && ratio > 1. / maxslope)
|
||||||
|
// {
|
||||||
|
// // Accumulate data for gain matching
|
||||||
|
// dataPoints[{qqq.id[i], chRing, chWedge}].emplace_back(eWedge, eRing);
|
||||||
|
// plotter->Fill2D("hAll_in", 4000, 0, 16000, 4000, 0, 16000, eWedge, eRing);
|
||||||
|
// validPoint = true;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (!validPoint)
|
||||||
|
// {
|
||||||
|
// plotter->Fill2D("hAll_out", 4000, 0, 16000, 4000, 0, 16000, eWedge, eRing);
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto tuple : events)
|
||||||
|
{
|
||||||
|
auto [id, chr, chw, er, ew] = tuple;
|
||||||
|
if (ringMults[chr] > 1 || wedgeMults[chw] > 1)
|
||||||
|
continue; // ignore multiplicity > 1 events
|
||||||
|
double ratio = (ew > 0.0) ? (er / ew) : 0.0;
|
||||||
|
double maxslope = 1.5;
|
||||||
|
|
||||||
|
bool validPoint = false;
|
||||||
|
if (ratio < maxslope && ratio > 1. / maxslope)
|
||||||
|
{
|
||||||
|
// Accumulate data for gain matching
|
||||||
|
dataPoints[{id, chr, chw}].emplace_back(ew, er);
|
||||||
|
plotter->Fill2D("hAll_in", 4000, 0, 16000, 4000, 0, 16000, ew, er);
|
||||||
|
validPoint = true;
|
||||||
|
}
|
||||||
|
if (!validPoint)
|
||||||
|
{
|
||||||
|
plotter->Fill2D("hAll_out", 4000, 0, 16000, 4000, 0, 16000, ew, er);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return kTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void GainMatchQQQ::Terminate()
|
||||||
|
{
|
||||||
|
const int MAX_DET = 4;
|
||||||
|
const int MAX_RING = 16;
|
||||||
|
const int MAX_WEDGE = 16;
|
||||||
|
|
||||||
|
// We store gains locally just for the "corrected" plot,
|
||||||
|
// but the file will output Slopes for the global minimizer.
|
||||||
|
double gainW[MAX_DET][MAX_RING][MAX_WEDGE] = {{{0}}};
|
||||||
|
double gainR[MAX_DET][MAX_RING][MAX_WEDGE] = {{{0}}};
|
||||||
|
bool gainValid[MAX_DET][MAX_RING][MAX_WEDGE] = {{{false}}};
|
||||||
|
|
||||||
|
// Output file for the Minimizer
|
||||||
|
std::ofstream outFile("qqq_GainMatch.txt");
|
||||||
|
|
||||||
|
// Benchmark/Debug file
|
||||||
|
std::ofstream benchFile("benchmark_diff.txt");
|
||||||
|
benchFile << "ID Wedge Ring Chi2NDF Slope SlopeErr" << std::endl;
|
||||||
|
|
||||||
|
if (!outFile.is_open()) { std::cerr << "Error opening output file!" << std::endl; return; }
|
||||||
|
|
||||||
|
const int MIN_POINTS = 50;
|
||||||
|
const int MAX_ITER = 3; // Outlier rejection passes
|
||||||
|
const double CLIP_SIGMA = 2.5; // Sigma threshold for outliers
|
||||||
|
|
||||||
|
for (const auto &kv : dataPoints)
|
||||||
|
{
|
||||||
|
auto key = kv.first;
|
||||||
|
auto [id, ring, wedge] = key;
|
||||||
|
const auto &pts = kv.second;
|
||||||
|
|
||||||
|
if (pts.size() < (size_t)MIN_POINTS) continue;
|
||||||
|
|
||||||
|
std::vector<std::pair<double, double>> current_pts = pts;
|
||||||
|
|
||||||
|
double finalSlope = 0.0;
|
||||||
|
double finalSlopeErr = 0.0;
|
||||||
|
bool converged = false;
|
||||||
|
|
||||||
|
// --- Iterative Fitting ---
|
||||||
|
for (int iter = 0; iter < MAX_ITER; ++iter)
|
||||||
|
{
|
||||||
|
if (current_pts.size() < (size_t)MIN_POINTS) break;
|
||||||
|
|
||||||
|
std::vector<double> x, y, ex, ey;
|
||||||
|
|
||||||
|
for (const auto &p : current_pts)
|
||||||
|
{
|
||||||
|
x.push_back(p.first); // Wedge E
|
||||||
|
y.push_back(p.second); // Ring E
|
||||||
|
ex.push_back(std::sqrt(std::abs(p.first))); // Error in X (Poisson)
|
||||||
|
ey.push_back(std::sqrt(std::abs(p.second))); // Error in Y (Poisson)
|
||||||
|
|
||||||
|
// Sanity check to avoid 0 error
|
||||||
|
if(ex.back() < 1.0) ex.back() = 1.0;
|
||||||
|
if(ey.back() < 1.0) ey.back() = 1.0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Create Graph
|
||||||
|
TGraphErrors *gr = new TGraphErrors(current_pts.size(), x.data(), y.data(), ex.data(), ey.data());
|
||||||
|
|
||||||
|
// 3. Fit Linear Function through Origin
|
||||||
|
TF1 *f1= new TF1("calibFit", "[0]*x", 0, 16000);
|
||||||
|
f1->SetParameter(0, 1.0);
|
||||||
|
|
||||||
|
// "Q"=Quiet, "N"=NoDraw, "S"=ResultPtr
|
||||||
|
// We do NOT use "W" (Ignore weights), we want to use the errors we set.
|
||||||
|
int fitStatus = gr->Fit(f1, "QNS");
|
||||||
|
|
||||||
|
if (fitStatus != 0) {
|
||||||
|
delete gr; delete f1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
finalSlope = f1->GetParameter(0);
|
||||||
|
double chi2 = f1->GetChisquare();
|
||||||
|
double ndf = f1->GetNDF();
|
||||||
|
|
||||||
|
// Get the statistical error on the slope
|
||||||
|
double rawErr = f1->GetParError(0);
|
||||||
|
|
||||||
|
// SCALING ERROR:
|
||||||
|
// If Chi2/NDF > 1, the data scatters more than Poisson stats predict.
|
||||||
|
// // We inflate the error by sqrt(Chi2/NDF) to be conservative for the Minimizer.
|
||||||
|
// double redChi2 = (ndf > 0) ? (chi2 / ndf) : 1.0;
|
||||||
|
// double inflation = (redChi2 > 1.0) ? std::sqrt(redChi2) : 1.0;
|
||||||
|
|
||||||
|
// finalSlopeErr = rawErr * inflation;
|
||||||
|
|
||||||
|
// 4. Outlier Rejection
|
||||||
|
if (iter == MAX_ITER - 1) {
|
||||||
|
converged = true;
|
||||||
|
delete gr; delete f1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate Residuals
|
||||||
|
std::vector<double> residuals;
|
||||||
|
double sumSqResid = 0.0;
|
||||||
|
for(size_t k=0; k<current_pts.size(); ++k) {
|
||||||
|
double val = f1->Eval(current_pts[k].first);
|
||||||
|
double res = current_pts[k].second - val;
|
||||||
|
residuals.push_back(res);
|
||||||
|
sumSqResid += res*res;
|
||||||
|
}
|
||||||
|
// double sigma = std::sqrt(sumSqResid / current_pts.size());
|
||||||
|
|
||||||
|
// // Filter
|
||||||
|
// std::vector<std::pair<double, double>> next_pts;
|
||||||
|
// for(size_t k=0; k<current_pts.size(); ++k) {
|
||||||
|
// if(std::abs(residuals[k]) < CLIP_SIGMA * sigma) {
|
||||||
|
// next_pts.push_back(current_pts[k]);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if (next_pts.size() == current_pts.size()) {
|
||||||
|
// converged = true;
|
||||||
|
// delete gr; delete f1;
|
||||||
|
// break;
|
||||||
|
// }
|
||||||
|
// current_pts = next_pts;
|
||||||
|
// delete gr; delete f1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!converged || finalSlope <= 0) continue;
|
||||||
|
|
||||||
|
// --- Store/Output ---
|
||||||
|
|
||||||
|
// 1. Save locally for the verification plot (hAll)
|
||||||
|
// Approximate local gain for plotting purposes only
|
||||||
|
double gW_local = std::sqrt(finalSlope);
|
||||||
|
double gR_local = 1.0 / gW_local;
|
||||||
|
gainW[id][ring][wedge] = gW_local;
|
||||||
|
gainR[id][ring][wedge] = gR_local;
|
||||||
|
gainValid[id][ring][wedge] = true;
|
||||||
|
|
||||||
|
// 2. Write to File for Minimizer
|
||||||
|
// Format: ID Wedge Ring Slope Error
|
||||||
|
outFile << id << " " << wedge << " " << ring << " " << finalSlope << " " << finalSlopeErr << std::endl;
|
||||||
|
|
||||||
|
// 3. Benchmark Info
|
||||||
|
benchFile << id << " " << wedge << " " << ring << " "
|
||||||
|
<< finalSlope << " " << finalSlopeErr << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
outFile.close();
|
||||||
|
benchFile.close();
|
||||||
|
std::cout << "Gain matching with Errors complete." << std::endl;
|
||||||
|
|
||||||
|
// Plotting the corrected data (Visual check using local approx gains)
|
||||||
|
for (auto &kv : dataPoints)
|
||||||
|
{
|
||||||
|
int id, ring, wedge;
|
||||||
|
std::tie(id, ring, wedge) = kv.first;
|
||||||
|
if (!gainValid[id][ring][wedge]) continue;
|
||||||
|
auto &pts = kv.second;
|
||||||
|
for (auto &pr : pts)
|
||||||
|
{
|
||||||
|
double corrWedge = pr.first * gainW[id][ring][wedge];
|
||||||
|
double corrRing = pr.second * gainR[id][ring][wedge];
|
||||||
|
plotter->Fill2D("hAll", 4000, 0, 16000, 4000, 0, 16000, corrWedge, corrRing);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
plotter->FlushToDisk();
|
||||||
|
}
|
||||||
114
GainMatchQQQ.h
Normal file
114
GainMatchQQQ.h
Normal file
|
|
@ -0,0 +1,114 @@
|
||||||
|
#ifndef GainMatchQQQ_h
|
||||||
|
#define GainMatchQQQ_h
|
||||||
|
|
||||||
|
#include <TROOT.h>
|
||||||
|
#include <TChain.h>
|
||||||
|
#include <TFile.h>
|
||||||
|
#include <TSelector.h>
|
||||||
|
|
||||||
|
#include "Armory/ClassDet.h"
|
||||||
|
|
||||||
|
class GainMatchQQQ : public TSelector {
|
||||||
|
public :
|
||||||
|
TTree *fChain; //!pointer to the analyzed TTree or TChain
|
||||||
|
|
||||||
|
// Fixed size dimensions of array or collections stored in the TTree if any.
|
||||||
|
|
||||||
|
// Declaration of leaf types
|
||||||
|
Det sx3;
|
||||||
|
Det qqq;
|
||||||
|
Det pc ;
|
||||||
|
|
||||||
|
ULong64_t evID;
|
||||||
|
UInt_t run;
|
||||||
|
|
||||||
|
// List of branches
|
||||||
|
TBranch *b_eventID; //!
|
||||||
|
TBranch *b_run; //!
|
||||||
|
TBranch *b_sx3Multi; //!
|
||||||
|
TBranch *b_sx3ID; //!
|
||||||
|
TBranch *b_sx3Ch; //!
|
||||||
|
TBranch *b_sx3E; //!
|
||||||
|
TBranch *b_sx3T; //!
|
||||||
|
TBranch *b_qqqMulti; //!
|
||||||
|
TBranch *b_qqqID; //!
|
||||||
|
TBranch *b_qqqCh; //!
|
||||||
|
TBranch *b_qqqE; //!
|
||||||
|
TBranch *b_qqqT; //!
|
||||||
|
TBranch *b_pcMulti; //!
|
||||||
|
TBranch *b_pcID; //!
|
||||||
|
TBranch *b_pcCh; //!
|
||||||
|
TBranch *b_pcE; //!
|
||||||
|
TBranch *b_pcT; //!
|
||||||
|
|
||||||
|
GainMatchQQQ(TTree * /*tree*/ =0) : fChain(0) { }
|
||||||
|
virtual ~GainMatchQQQ() { }
|
||||||
|
virtual Int_t Version() const { return 2; }
|
||||||
|
virtual void Begin(TTree *tree);
|
||||||
|
virtual void SlaveBegin(TTree *tree);
|
||||||
|
virtual void Init(TTree *tree);
|
||||||
|
virtual Bool_t Notify();
|
||||||
|
virtual Bool_t Process(Long64_t entry);
|
||||||
|
virtual Int_t GetEntry(Long64_t entry, Int_t getall = 0) { return fChain ? fChain->GetTree()->GetEntry(entry, getall) : 0; }
|
||||||
|
virtual void SetOption(const char *option) { fOption = option; }
|
||||||
|
virtual void SetObject(TObject *obj) { fObject = obj; }
|
||||||
|
virtual void SetInputList(TList *input) { fInput = input; }
|
||||||
|
virtual TList *GetOutputList() const { return fOutput; }
|
||||||
|
virtual void SlaveTerminate();
|
||||||
|
virtual void Terminate();
|
||||||
|
|
||||||
|
ClassDef(GainMatchQQQ,0);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef GainMatchQQQ_cxx
|
||||||
|
void GainMatchQQQ::Init(TTree *tree){
|
||||||
|
|
||||||
|
// Set branch addresses and branch pointers
|
||||||
|
if (!tree) return;
|
||||||
|
fChain = tree;
|
||||||
|
fChain->SetMakeClass(1);
|
||||||
|
|
||||||
|
fChain->SetBranchAddress("evID", &evID, &b_eventID);
|
||||||
|
fChain->SetBranchAddress("run", &run, &b_run);
|
||||||
|
|
||||||
|
sx3.SetDetDimension(24,12);
|
||||||
|
qqq.SetDetDimension(4,32);
|
||||||
|
pc.SetDetDimension(2,24);
|
||||||
|
|
||||||
|
fChain->SetBranchAddress("sx3Multi", &sx3.multi, &b_sx3Multi);
|
||||||
|
fChain->SetBranchAddress("sx3ID", &sx3.id, &b_sx3ID);
|
||||||
|
fChain->SetBranchAddress("sx3Ch", &sx3.ch, &b_sx3Ch);
|
||||||
|
fChain->SetBranchAddress("sx3E", &sx3.e, &b_sx3E);
|
||||||
|
fChain->SetBranchAddress("sx3T", &sx3.t, &b_sx3T);
|
||||||
|
fChain->SetBranchAddress("qqqMulti", &qqq.multi, &b_qqqMulti);
|
||||||
|
fChain->SetBranchAddress("qqqID", &qqq.id, &b_qqqID);
|
||||||
|
fChain->SetBranchAddress("qqqCh", &qqq.ch, &b_qqqCh);
|
||||||
|
fChain->SetBranchAddress("qqqE", &qqq.e, &b_qqqE);
|
||||||
|
fChain->SetBranchAddress("qqqT", &qqq.t, &b_qqqT);
|
||||||
|
fChain->SetBranchAddress("pcMulti", &pc.multi, &b_pcMulti);
|
||||||
|
fChain->SetBranchAddress("pcID", &pc.id, &b_pcID);
|
||||||
|
fChain->SetBranchAddress("pcCh", &pc.ch, &b_pcCh);
|
||||||
|
fChain->SetBranchAddress("pcE", &pc.e, &b_pcE);
|
||||||
|
fChain->SetBranchAddress("pcT", &pc.t, &b_pcT);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Bool_t GainMatchQQQ::Notify(){
|
||||||
|
|
||||||
|
return kTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GainMatchQQQ::SlaveBegin(TTree * /*tree*/){
|
||||||
|
|
||||||
|
TString option = GetOption();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void GainMatchQQQ::SlaveTerminate(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif // #ifdef GainMatchQQQ_cxx
|
||||||
432
GainMatchSX3.C
Normal file
432
GainMatchSX3.C
Normal file
|
|
@ -0,0 +1,432 @@
|
||||||
|
#define GainMatchSX3_cxx
|
||||||
|
|
||||||
|
#include "GainMatchSX3.h"
|
||||||
|
#include <TH2.h>
|
||||||
|
#include <TF1.h>
|
||||||
|
#include <TStyle.h>
|
||||||
|
#include <TCanvas.h>
|
||||||
|
#include <TMath.h>
|
||||||
|
#include <TCutG.h>
|
||||||
|
#include <fstream>
|
||||||
|
#include <utility>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <TProfile.h>
|
||||||
|
#include "Armory/ClassSX3.h"
|
||||||
|
#include "Armory/HistPlotter.h"
|
||||||
|
#include <TGraphErrors.h>
|
||||||
|
#include "TVector3.h"
|
||||||
|
|
||||||
|
TH2F *hSX3FvsB;
|
||||||
|
TH2F *hSX3FvsB_g;
|
||||||
|
TH2F *hsx3IndexVE;
|
||||||
|
TH2F *hsx3IndexVE_g;
|
||||||
|
TH2F *hSX3;
|
||||||
|
TH2F *hsx3Coin;
|
||||||
|
|
||||||
|
int padID = 0;
|
||||||
|
|
||||||
|
SX3 sx3_contr;
|
||||||
|
TCutG *cut;
|
||||||
|
TCutG *cut1;
|
||||||
|
std::map<std::tuple<int, int, int, int>, std::vector<std::tuple<double, double, double>>> dataPoints;
|
||||||
|
std::map<std::tuple<int, int, int, int>, int> comboCounts;
|
||||||
|
|
||||||
|
const int MAX_DET = 24;
|
||||||
|
const int MAX_UP = 4;
|
||||||
|
const int MAX_DOWN = 4;
|
||||||
|
const int MAX_BK = 4;
|
||||||
|
|
||||||
|
double frontGainUp[MAX_DET][MAX_BK][MAX_UP][MAX_DOWN] = {{{{0}}}};
|
||||||
|
double frontGainDown[MAX_DET][MAX_BK][MAX_UP][MAX_DOWN] = {{{{0}}}};
|
||||||
|
bool frontGainValid[MAX_DET][MAX_BK][MAX_UP][MAX_DOWN] = {{{{false}}}};
|
||||||
|
TCanvas c("canvas", "canvas", 800, 600);
|
||||||
|
|
||||||
|
// ==== Configuration Flags ====
|
||||||
|
const bool interactiveMode = true; // If true: show canvas + wait for user
|
||||||
|
const bool verboseFit = true; // If true: print fit summary and chi²
|
||||||
|
const bool drawCanvases = true; // If false: canvases won't be drawn at all
|
||||||
|
|
||||||
|
// HistPlotter plotter("SX3GainMatchBack.root");
|
||||||
|
|
||||||
|
void GainMatchSX3::Begin(TTree * /*tree*/)
|
||||||
|
{
|
||||||
|
TString option = GetOption();
|
||||||
|
|
||||||
|
hSX3FvsB = new TH2F("hSX3FvsB", "SX3 Front vs Back; Front E; Back E", 400, 0, 16000, 400, 0, 16000);
|
||||||
|
hSX3FvsB_g = new TH2F("hSX3FvsB_g", "SX3 Front vs Back; Front E; Back E", 400, 0, 16000, 400, 0, 16000);
|
||||||
|
hsx3IndexVE = new TH2F("hsx3IndexVE", "SX3 index vs Energy; sx3 index ; Energy", 24 * 12, 0, 24 * 12, 400, 0, 5000);
|
||||||
|
hsx3IndexVE_g = new TH2F("hsx3IndexVE_g", "SX3 index vs Energy; sx3 index ; Energy", 24 * 12, 0, 24 * 12, 400, 0, 5000);
|
||||||
|
hSX3 = new TH2F("hSX3", "SX3 Front v Back; Fronts; Backs", 8, 0, 8, 4, 0, 4);
|
||||||
|
|
||||||
|
hsx3Coin = new TH2F("hsx3Coin", "SX3 Coincident", 24 * 12, 0, 24 * 12, 24 * 12, 0, 24 * 12);
|
||||||
|
|
||||||
|
sx3_contr.ConstructGeo();
|
||||||
|
|
||||||
|
// Load the TCutG object
|
||||||
|
TFile *cutFile = TFile::Open("sx3cut.root");
|
||||||
|
if (!cutFile || cutFile->IsZombie())
|
||||||
|
{
|
||||||
|
std::cerr << "Error: Could not open sx3cut.root" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cut = dynamic_cast<TCutG *>(cutFile->Get("sx3cut"));
|
||||||
|
if (!cut)
|
||||||
|
{
|
||||||
|
std::cerr << "Error: Could not find TCutG named 'sx3cut' in sx3cut.root" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cut->SetName("sx3cut"); // Ensure the cut has the correct name
|
||||||
|
|
||||||
|
// Load the TCutG object
|
||||||
|
TFile *cutFile1 = TFile::Open("UvD.root");
|
||||||
|
bool cut1Loaded = (cut1 != nullptr);
|
||||||
|
cut1 = dynamic_cast<TCutG *>(cutFile1->Get("UvD"));
|
||||||
|
if (!cut1)
|
||||||
|
{
|
||||||
|
std::cerr << "Error: Could not find TCutG named 'UvD' in UvD.root" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cut1->SetName("UvD");
|
||||||
|
|
||||||
|
// plotter.ReadCuts("cuts.txt");
|
||||||
|
|
||||||
|
std::string filename = "sx3_GainMatchfront.txt";
|
||||||
|
// std::string filename = "sx3_GainMatchfront.txt";
|
||||||
|
|
||||||
|
std::ifstream infile(filename);
|
||||||
|
if (!infile.is_open())
|
||||||
|
{
|
||||||
|
std::cerr << "Error opening " << filename << "!" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int id, bk, u, d;
|
||||||
|
double gainup, gaindown;
|
||||||
|
while (infile >> id >> bk >> u >> d >> gainup >> gaindown)
|
||||||
|
{
|
||||||
|
frontGainUp[id][bk][u][d] = gainup;
|
||||||
|
frontGainDown[id][bk][u][d] = gaindown;
|
||||||
|
frontGainValid[id][bk][u][d] = true;
|
||||||
|
if(frontGainValid[id][bk][u][d]) {
|
||||||
|
// std::cout << "Loaded front gain for Det" << id << " Bk" << bk << " U" << u << " D" << d
|
||||||
|
// << ": Up=" << gainup << ", Down=" << gaindown << std::endl;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
std::cout << "No valid front gain for Det" << id << " Bk" << bk << " U" << u << " D" << d << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Bool_t GainMatchSX3::Process(Long64_t entry)
|
||||||
|
{
|
||||||
|
|
||||||
|
b_sx3Multi->GetEntry(entry);
|
||||||
|
b_sx3ID->GetEntry(entry);
|
||||||
|
b_sx3Ch->GetEntry(entry);
|
||||||
|
b_sx3E->GetEntry(entry);
|
||||||
|
b_sx3T->GetEntry(entry);
|
||||||
|
b_qqqMulti->GetEntry(entry);
|
||||||
|
b_qqqID->GetEntry(entry);
|
||||||
|
b_qqqCh->GetEntry(entry);
|
||||||
|
b_qqqE->GetEntry(entry);
|
||||||
|
b_qqqT->GetEntry(entry);
|
||||||
|
b_pcMulti->GetEntry(entry);
|
||||||
|
b_pcID->GetEntry(entry);
|
||||||
|
b_pcCh->GetEntry(entry);
|
||||||
|
b_pcE->GetEntry(entry);
|
||||||
|
b_pcT->GetEntry(entry);
|
||||||
|
|
||||||
|
sx3.CalIndex();
|
||||||
|
qqq.CalIndex();
|
||||||
|
pc.CalIndex();
|
||||||
|
|
||||||
|
std::vector<std::pair<int, int>> ID;
|
||||||
|
for (int i = 0; i < sx3.multi; i++)
|
||||||
|
{
|
||||||
|
|
||||||
|
// for (int j = i + 1; j < sx3.multi; j++)
|
||||||
|
// {
|
||||||
|
// if (sx3.id[i] == 3)
|
||||||
|
// hsx3Coin->Fill(sx3.index[i], sx3.index[j]);
|
||||||
|
// }
|
||||||
|
if (sx3.e[i] > 100)
|
||||||
|
{
|
||||||
|
ID.push_back(std::pair<int, int>(sx3.id[i], i));
|
||||||
|
hsx3IndexVE->Fill(sx3.index[i], sx3.e[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ID.size() > 0)
|
||||||
|
{
|
||||||
|
std::sort(ID.begin(), ID.end(), [](const std::pair<int, int> &a, const std::pair<int, int> &b)
|
||||||
|
{ return a.first < b.first; });
|
||||||
|
|
||||||
|
// start with the first entry in the sorted array: channels that belong to the same detector are together in sequenmce
|
||||||
|
std::vector<std::pair<int, int>> sx3ID;
|
||||||
|
sx3ID.push_back(ID[0]);
|
||||||
|
bool found = false;
|
||||||
|
|
||||||
|
for (size_t i = 1; i < ID.size(); i++)
|
||||||
|
{ // Check if id of i belongs to the same detector and then add it to the detector ID vector
|
||||||
|
if (ID[i].first == sx3ID.back().first)
|
||||||
|
{ // count the nunmber of hits that belong to the same detector
|
||||||
|
sx3ID.push_back(ID[i]);
|
||||||
|
|
||||||
|
if (sx3ID.size() >= 3)
|
||||||
|
{
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // the next event does not belong to the same detector, abandon the first event and continue with the next one
|
||||||
|
if (!found)
|
||||||
|
{
|
||||||
|
sx3ID.clear();
|
||||||
|
sx3ID.push_back(ID[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (found)
|
||||||
|
{
|
||||||
|
int sx3ChUp = -1, sx3ChDn = -1, sx3ChBk = -1;
|
||||||
|
float sx3EUp = 0.0, sx3EDn = 0.0, sx3EBk = 0.0;
|
||||||
|
|
||||||
|
// Build the correlated set once
|
||||||
|
for (size_t i = 0; i < sx3ID.size(); i++)
|
||||||
|
{
|
||||||
|
if (sx3.e[i] > 100)
|
||||||
|
{
|
||||||
|
int index = sx3ID[i].second;
|
||||||
|
if (sx3.ch[index] < 8)
|
||||||
|
{
|
||||||
|
if (sx3.ch[index] % 2 == 0)
|
||||||
|
{
|
||||||
|
sx3ChDn = sx3.ch[index];
|
||||||
|
sx3EDn = sx3.e[index];
|
||||||
|
//
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sx3ChUp = sx3.ch[index];
|
||||||
|
sx3EUp = sx3.e[index];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sx3ChBk = sx3.ch[index] - 8;
|
||||||
|
sx3EBk = sx3.e[index];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
// Only if we found all three channels do we proceed
|
||||||
|
if (sx3ChUp >= 0 && sx3ChDn >= 0 && sx3ChBk >= 0)
|
||||||
|
{
|
||||||
|
// Fill once per correlated set
|
||||||
|
hSX3->Fill(sx3ChDn + 4, sx3ChBk);
|
||||||
|
hSX3->Fill(sx3ChUp, sx3ChBk);
|
||||||
|
hSX3FvsB->Fill(sx3EUp + sx3EDn, sx3EBk);
|
||||||
|
|
||||||
|
if (frontGainValid[sx3ID[0].first][sx3ChBk][sx3ChUp / 2][sx3ChDn / 2])
|
||||||
|
{
|
||||||
|
sx3EUp *= frontGainUp[sx3ID[0].first][sx3ChBk][sx3ChUp / 2][sx3ChDn / 2];
|
||||||
|
sx3EDn *= frontGainDown[sx3ID[0].first][sx3ChBk][sx3ChUp / 2][sx3ChDn / 2];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// printf("No front gain for Det%d Bk%d U%d D%d\n", sx3ID[0].first, sx3ChBk, sx3ChUp / 2, sx3ChDn / 2);
|
||||||
|
sx3EUp = sx3EDn = 0.;
|
||||||
|
}
|
||||||
|
// plotter.Fill2D("hSX3F", 400, 0, 16000, 400, 0, 16000, sx3EUp + sx3EDn, sx3EBk);
|
||||||
|
|
||||||
|
// Pick detector ID from one of the correlated hits (all same detector)
|
||||||
|
int detID = sx3ID[0].first;
|
||||||
|
|
||||||
|
TString histName = Form("hSX3FVB_id%d_U%d_D%d_B%d", detID, sx3ChUp, sx3ChDn, sx3ChBk);
|
||||||
|
TString histName1 = Form("UnCorr_id%d_U%d-D%dvsB%d", detID, sx3ChUp, sx3ChDn, sx3ChBk);
|
||||||
|
|
||||||
|
TH2F *hist2d = (TH2F *)gDirectory->Get(histName);
|
||||||
|
TH2F *hist2d1 = (TH2F *)gDirectory->Get(histName1);
|
||||||
|
if (!hist2d)
|
||||||
|
{
|
||||||
|
hist2d = new TH2F(histName, histName,
|
||||||
|
400, 0, 16000, 400, 0, 16000);
|
||||||
|
}
|
||||||
|
if (!hist2d1)
|
||||||
|
{
|
||||||
|
hist2d1 = new TH2F(histName1, histName1,
|
||||||
|
800, -1, 1, 800, 0, 4000);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sx3EBk > 100 || sx3EUp > 100 || sx3EDn > 100)
|
||||||
|
{
|
||||||
|
hSX3FvsB_g->Fill(sx3EUp + sx3EDn, sx3EBk);
|
||||||
|
|
||||||
|
// Use the correlated triplet directly
|
||||||
|
dataPoints[{detID, sx3ChBk, sx3ChUp, sx3ChDn}]
|
||||||
|
.emplace_back(sx3EBk, sx3EUp, sx3EDn);
|
||||||
|
}
|
||||||
|
|
||||||
|
hist2d->Fill(sx3EUp + sx3EDn, sx3EBk);
|
||||||
|
hist2d1->Fill((sx3EUp - sx3EDn) / (sx3EUp + sx3EDn), sx3EBk);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return kTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
const double GAIN_ACCEPTANCE_THRESHOLD = 0.3;
|
||||||
|
void GainMatchSX3::Terminate()
|
||||||
|
{
|
||||||
|
double backSlope[MAX_DET][MAX_BK] = {{0}};
|
||||||
|
bool backSlopeValid[MAX_DET][MAX_BK] = {{false}};
|
||||||
|
|
||||||
|
std::ofstream outFile("sx3_BackGains0.txt");
|
||||||
|
if (!outFile.is_open())
|
||||||
|
{
|
||||||
|
std::cerr << "Error opening sx3_BackGains.txt for writing!" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// === Gain fit: (Up+Dn) vs Back, grouped by [id][bk] ===
|
||||||
|
for (int id = 0; id < MAX_DET; id++)
|
||||||
|
{
|
||||||
|
for (int bk = 0; bk < MAX_BK; bk++)
|
||||||
|
{
|
||||||
|
std::vector<double> bkE, udE;
|
||||||
|
|
||||||
|
// Collect all (Up+Dn, Back) for this id,bk
|
||||||
|
for (const auto &kv : dataPoints)
|
||||||
|
{
|
||||||
|
auto [cid, cbk, u, d] = kv.first;
|
||||||
|
if (cid != id || cbk != bk)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
for (const auto &pr : kv.second)
|
||||||
|
{
|
||||||
|
double eBk, eUp, eDn;
|
||||||
|
std::tie(eBk, eUp, eDn) = pr;
|
||||||
|
if ((eBk < 100) || (eUp < 100) || (eDn < 100))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
bkE.push_back(eBk);
|
||||||
|
udE.push_back(eUp + eDn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bkE.size() < 5)
|
||||||
|
continue; // not enough statistics
|
||||||
|
|
||||||
|
// Build graph with errors
|
||||||
|
const double fixedError = 0.0; // ADC channels
|
||||||
|
std::vector<double> exVals(udE.size(), 0.0); // no x error
|
||||||
|
std::vector<double> eyVals(udE.size(), fixedError); // constant y error
|
||||||
|
|
||||||
|
TGraphErrors g(udE.size(), udE.data(), bkE.data(),
|
||||||
|
exVals.data(), eyVals.data());
|
||||||
|
|
||||||
|
TF1 f("f", "[0]*x", 0, 16000);
|
||||||
|
// f.SetParameter(0, 1.0); // initial slope
|
||||||
|
|
||||||
|
if (drawCanvases)
|
||||||
|
{
|
||||||
|
g.SetTitle(Form("Detector %d Back %d: (Up+Dn) vs Back", id, bk));
|
||||||
|
g.SetMarkerStyle(20);
|
||||||
|
g.SetMarkerColor(kBlue);
|
||||||
|
g.Draw("AP");
|
||||||
|
|
||||||
|
g.Fit(&f, interactiveMode ? "Q" : "QNR");
|
||||||
|
|
||||||
|
if (verboseFit)
|
||||||
|
{
|
||||||
|
double chi2 = f.GetChisquare();
|
||||||
|
int ndf = f.GetNDF();
|
||||||
|
double reducedChi2 = (ndf != 0) ? chi2 / ndf : -1;
|
||||||
|
|
||||||
|
std::cout << Form("Det%d Back%d → Slope: %.4f | χ²/ndf = %.2f/%d = %.2f",
|
||||||
|
id, bk, f.GetParameter(0), chi2, ndf, reducedChi2)
|
||||||
|
<< std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (interactiveMode)
|
||||||
|
{
|
||||||
|
c.Update();
|
||||||
|
gPad->WaitPrimitive();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
c.Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g.Fit(&f, "QNR");
|
||||||
|
}
|
||||||
|
|
||||||
|
double slope = 1 / f.GetParameter(0);
|
||||||
|
if (std::abs(slope - 1.0) < 0.3) // sanity check
|
||||||
|
{
|
||||||
|
backSlope[id][bk] = slope;
|
||||||
|
backSlopeValid[id][bk] = true;
|
||||||
|
outFile << id << " " << bk << " " << slope << "\n";
|
||||||
|
printf("Back slope Det%d Bk%d → %.4f\n", id, bk, slope);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cerr << "Warning: Bad slope for Det" << id << " Bk" << bk
|
||||||
|
<< " slope=" << slope << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
outFile.close();
|
||||||
|
std::cout << "Back gain matching complete." << std::endl;
|
||||||
|
|
||||||
|
// === Create histograms ===
|
||||||
|
TH2F *hFVB = new TH2F("hFVB", "Corrected Up+Dn vs Corrected Back;Up+Dn E;Corrected Back E",
|
||||||
|
600, 0, 16000, 600, 0, 16000);
|
||||||
|
TH2F *hAsym = new TH2F("hAsym", "Up vs Dn divide corrected back;Up/Back E;Dn/Back E",
|
||||||
|
400, 0.0, 1.0, 400, 0.0, 1.0);
|
||||||
|
TH2F *hAsymUnorm = new TH2F("hAsymUnorm", "Up vs Dn;Up E;Dn E",
|
||||||
|
800, 0.0, 4000.0, 800, 0.0, 4000.0);
|
||||||
|
|
||||||
|
// Fill histograms using corrected back energies
|
||||||
|
for (const auto &kv : dataPoints)
|
||||||
|
{
|
||||||
|
auto [id, bk, u, d] = kv.first;
|
||||||
|
if (!backSlopeValid[id][bk])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
double slope = backSlope[id][bk];
|
||||||
|
|
||||||
|
for (const auto &pr : kv.second)
|
||||||
|
{
|
||||||
|
double eBk, eUp, eDn;
|
||||||
|
std::tie(eBk, eUp, eDn) = pr;
|
||||||
|
|
||||||
|
double updn = eUp + eDn;
|
||||||
|
if (updn == 0 || eBk == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
double correctedBack = eBk * slope;
|
||||||
|
double asym = (eUp - eDn) / updn;
|
||||||
|
|
||||||
|
hFVB->Fill(updn, correctedBack);
|
||||||
|
hAsym->Fill(eUp / correctedBack, eDn / correctedBack);
|
||||||
|
hAsymUnorm->Fill(eUp, eDn);
|
||||||
|
TString histNamex = Form("CorrBack_id%d_U%d-D%dvsB%d", id, u, d, bk);
|
||||||
|
|
||||||
|
TH2F *hist2dx = (TH2F *)gDirectory->Get(histNamex);
|
||||||
|
if (!hist2dx)
|
||||||
|
{
|
||||||
|
hist2dx = new TH2F(histNamex, histNamex,
|
||||||
|
800, -1, 1, 800, 0, 4000);
|
||||||
|
}
|
||||||
|
|
||||||
|
hist2dx->Fill((eUp - eDn) / (eUp + eDn), correctedBack);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// plotter.FlushToDisk();
|
||||||
|
}
|
||||||
114
GainMatchSX3.h
Normal file
114
GainMatchSX3.h
Normal file
|
|
@ -0,0 +1,114 @@
|
||||||
|
#ifndef GainMatchSX3_h
|
||||||
|
#define GainMatchSX3_h
|
||||||
|
|
||||||
|
#include <TROOT.h>
|
||||||
|
#include <TChain.h>
|
||||||
|
#include <TFile.h>
|
||||||
|
#include <TSelector.h>
|
||||||
|
|
||||||
|
#include "Armory/ClassDet.h"
|
||||||
|
|
||||||
|
class GainMatchSX3 : public TSelector {
|
||||||
|
public :
|
||||||
|
TTree *fChain; //!pointer to the analyzed TTree or TChain
|
||||||
|
|
||||||
|
// Fixed size dimensions of array or collections stored in the TTree if any.
|
||||||
|
|
||||||
|
// Declaration of leaf types
|
||||||
|
Det sx3;
|
||||||
|
Det qqq;
|
||||||
|
Det pc ;
|
||||||
|
|
||||||
|
ULong64_t evID;
|
||||||
|
UInt_t run;
|
||||||
|
|
||||||
|
// List of branches
|
||||||
|
TBranch *b_eventID; //!
|
||||||
|
TBranch *b_run; //!
|
||||||
|
TBranch *b_sx3Multi; //!
|
||||||
|
TBranch *b_sx3ID; //!
|
||||||
|
TBranch *b_sx3Ch; //!
|
||||||
|
TBranch *b_sx3E; //!
|
||||||
|
TBranch *b_sx3T; //!
|
||||||
|
TBranch *b_qqqMulti; //!
|
||||||
|
TBranch *b_qqqID; //!
|
||||||
|
TBranch *b_qqqCh; //!
|
||||||
|
TBranch *b_qqqE; //!
|
||||||
|
TBranch *b_qqqT; //!
|
||||||
|
TBranch *b_pcMulti; //!
|
||||||
|
TBranch *b_pcID; //!
|
||||||
|
TBranch *b_pcCh; //!
|
||||||
|
TBranch *b_pcE; //!
|
||||||
|
TBranch *b_pcT; //!
|
||||||
|
|
||||||
|
GainMatchSX3(TTree * /*tree*/ =0) : fChain(0) { }
|
||||||
|
virtual ~GainMatchSX3() { }
|
||||||
|
virtual Int_t Version() const { return 2; }
|
||||||
|
virtual void Begin(TTree *tree);
|
||||||
|
virtual void SlaveBegin(TTree *tree);
|
||||||
|
virtual void Init(TTree *tree);
|
||||||
|
virtual Bool_t Notify();
|
||||||
|
virtual Bool_t Process(Long64_t entry);
|
||||||
|
virtual Int_t GetEntry(Long64_t entry, Int_t getall = 0) { return fChain ? fChain->GetTree()->GetEntry(entry, getall) : 0; }
|
||||||
|
virtual void SetOption(const char *option) { fOption = option; }
|
||||||
|
virtual void SetObject(TObject *obj) { fObject = obj; }
|
||||||
|
virtual void SetInputList(TList *input) { fInput = input; }
|
||||||
|
virtual TList *GetOutputList() const { return fOutput; }
|
||||||
|
virtual void SlaveTerminate();
|
||||||
|
virtual void Terminate();
|
||||||
|
|
||||||
|
ClassDef(GainMatchSX3,0);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef GainMatchSX3_cxx
|
||||||
|
void GainMatchSX3::Init(TTree *tree){
|
||||||
|
|
||||||
|
// Set branch addresses and branch pointers
|
||||||
|
if (!tree) return;
|
||||||
|
fChain = tree;
|
||||||
|
fChain->SetMakeClass(1);
|
||||||
|
|
||||||
|
fChain->SetBranchAddress("evID", &evID, &b_eventID);
|
||||||
|
fChain->SetBranchAddress("run", &run, &b_run);
|
||||||
|
|
||||||
|
sx3.SetDetDimension(24,12);
|
||||||
|
qqq.SetDetDimension(4,32);
|
||||||
|
pc.SetDetDimension(2,24);
|
||||||
|
|
||||||
|
fChain->SetBranchAddress("sx3Multi", &sx3.multi, &b_sx3Multi);
|
||||||
|
fChain->SetBranchAddress("sx3ID", &sx3.id, &b_sx3ID);
|
||||||
|
fChain->SetBranchAddress("sx3Ch", &sx3.ch, &b_sx3Ch);
|
||||||
|
fChain->SetBranchAddress("sx3E", &sx3.e, &b_sx3E);
|
||||||
|
fChain->SetBranchAddress("sx3T", &sx3.t, &b_sx3T);
|
||||||
|
fChain->SetBranchAddress("qqqMulti", &qqq.multi, &b_qqqMulti);
|
||||||
|
fChain->SetBranchAddress("qqqID", &qqq.id, &b_qqqID);
|
||||||
|
fChain->SetBranchAddress("qqqCh", &qqq.ch, &b_qqqCh);
|
||||||
|
fChain->SetBranchAddress("qqqE", &qqq.e, &b_qqqE);
|
||||||
|
fChain->SetBranchAddress("qqqT", &qqq.t, &b_qqqT);
|
||||||
|
fChain->SetBranchAddress("pcMulti", &pc.multi, &b_pcMulti);
|
||||||
|
fChain->SetBranchAddress("pcID", &pc.id, &b_pcID);
|
||||||
|
fChain->SetBranchAddress("pcCh", &pc.ch, &b_pcCh);
|
||||||
|
fChain->SetBranchAddress("pcE", &pc.e, &b_pcE);
|
||||||
|
fChain->SetBranchAddress("pcT", &pc.t, &b_pcT);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Bool_t GainMatchSX3::Notify(){
|
||||||
|
|
||||||
|
return kTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GainMatchSX3::SlaveBegin(TTree * /*tree*/){
|
||||||
|
|
||||||
|
TString option = GetOption();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void GainMatchSX3::SlaveTerminate(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif // #ifdef GainMatchSX3_cxx
|
||||||
420
GainMatchSX3Front.C
Normal file
420
GainMatchSX3Front.C
Normal file
|
|
@ -0,0 +1,420 @@
|
||||||
|
#define GainMatchSX3Front_cxx
|
||||||
|
|
||||||
|
#include "GainMatchSX3Front.h"
|
||||||
|
#include <TH2.h>
|
||||||
|
#include <TF1.h>
|
||||||
|
#include <TStyle.h>
|
||||||
|
#include <TCanvas.h>
|
||||||
|
#include <TMath.h>
|
||||||
|
#include <TCutG.h>
|
||||||
|
#include <fstream>
|
||||||
|
#include <utility>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <TProfile.h>
|
||||||
|
#include "Armory/ClassSX3.h"
|
||||||
|
#include "TGraphErrors.h"
|
||||||
|
#include "TMultiDimFit.h"
|
||||||
|
|
||||||
|
#include "TVector3.h"
|
||||||
|
|
||||||
|
TH2F *hSX3FvsB;
|
||||||
|
TH2F *hSX3FvsB_g;
|
||||||
|
TH2F *hsx3IndexVE;
|
||||||
|
TH2F *hsx3IndexVE_g;
|
||||||
|
TH2F *hSX3;
|
||||||
|
TH2F *hsx3Coin;
|
||||||
|
|
||||||
|
int padID = 0;
|
||||||
|
|
||||||
|
SX3 sx3_contr;
|
||||||
|
TCutG *cut;
|
||||||
|
TCutG *cut1;
|
||||||
|
std::map<std::tuple<int, int, int, int>, std::vector<std::tuple<double, double, double>>> dataPoints;
|
||||||
|
TCanvas c(Form("canvas"), "Fit", 800, 600);
|
||||||
|
|
||||||
|
// Gain arrays
|
||||||
|
|
||||||
|
const int MAX_DET = 24;
|
||||||
|
const int MAX_UP = 4;
|
||||||
|
const int MAX_DOWN = 4;
|
||||||
|
const int MAX_BK = 4;
|
||||||
|
double backGain[MAX_DET][MAX_BK] = {{0}};
|
||||||
|
bool backGainValid[MAX_DET][MAX_BK] = {{false}};
|
||||||
|
double frontGain[MAX_DET][MAX_BK][MAX_UP][MAX_DOWN] = {{{{0}}}};
|
||||||
|
bool frontGainValid[MAX_DET][MAX_BK][MAX_UP][MAX_DOWN] = {{{{false}}}};
|
||||||
|
double uvdslope[MAX_DET][MAX_BK][MAX_UP][MAX_DOWN] = {{{{0}}}};
|
||||||
|
// ==== Configuration Flags ====
|
||||||
|
const bool interactiveMode = true; // If true: show canvas + wait for user
|
||||||
|
const bool verboseFit = true; // If true: print fit summary and chi²
|
||||||
|
const bool drawCanvases = true; // If false: canvases won't be drawn at all
|
||||||
|
|
||||||
|
void GainMatchSX3Front::Begin(TTree * /*tree*/)
|
||||||
|
{
|
||||||
|
TString option = GetOption();
|
||||||
|
|
||||||
|
hSX3FvsB = new TH2F("hSX3FvsB", "SX3 Front vs Back; Front E; Back E", 800, 0, 16000, 800, 0, 16000);
|
||||||
|
hSX3FvsB_g = new TH2F("hSX3FvsB_g", "SX3 Front vs Back; Front E; Back E", 800, 0, 16000, 800, 0, 16000);
|
||||||
|
hsx3IndexVE = new TH2F("hsx3IndexVE", "SX3 index vs Energy; sx3 index ; Energy", 24 * 12, 0, 24 * 12, 400, 0, 5000);
|
||||||
|
hsx3IndexVE_g = new TH2F("hsx3IndexVE_g", "SX3 index vs Energy; sx3 index ; Energy", 24 * 12, 0, 24 * 12, 400, 0, 5000);
|
||||||
|
hSX3 = new TH2F("hSX3", "SX3 Front v Back; Fronts; Backs", 8, 0, 8, 4, 0, 4);
|
||||||
|
|
||||||
|
hsx3Coin = new TH2F("hsx3Coin", "SX3 Coincident", 24 * 12, 0, 24 * 12, 24 * 12, 0, 24 * 12);
|
||||||
|
|
||||||
|
sx3_contr.ConstructGeo();
|
||||||
|
|
||||||
|
// Load the TCutG object
|
||||||
|
TFile *cutFile = TFile::Open("sx3cut.root");
|
||||||
|
bool cutLoaded = (cut != nullptr);
|
||||||
|
cut = dynamic_cast<TCutG *>(cutFile->Get("sx3cut"));
|
||||||
|
if (!cut)
|
||||||
|
{
|
||||||
|
std::cerr << "Error: Could not find TCutG named 'sx3cut' in sx3cut.root" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cut->SetName("sx3cut"); // Ensure the cut has the correct name
|
||||||
|
|
||||||
|
// Load the TCutG object
|
||||||
|
TFile *cutFile1 = TFile::Open("UvD.root");
|
||||||
|
bool cut1Loaded = (cut1 != nullptr);
|
||||||
|
cut1 = dynamic_cast<TCutG *>(cutFile1->Get("UvD"));
|
||||||
|
if (!cut1)
|
||||||
|
{
|
||||||
|
std::cerr << "Error: Could not find TCutG named 'UvD' in UvD.root" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
cut1->SetName("UvD");
|
||||||
|
|
||||||
|
std::string filename = "sx3_BackGains.txt";
|
||||||
|
|
||||||
|
std::ifstream infile(filename);
|
||||||
|
if (!infile.is_open())
|
||||||
|
{
|
||||||
|
std::cerr << "Error opening " << filename << "!" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int id, bk;
|
||||||
|
double gain;
|
||||||
|
while (infile >> id >> bk >> gain)
|
||||||
|
{
|
||||||
|
backGain[id][bk] = gain;
|
||||||
|
if (backGain[id][bk] > 0)
|
||||||
|
backGainValid[id][bk] = true;
|
||||||
|
else
|
||||||
|
backGainValid[id][bk] = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
SX3 sx3_contr;
|
||||||
|
}
|
||||||
|
|
||||||
|
Bool_t GainMatchSX3Front::Process(Long64_t entry)
|
||||||
|
{
|
||||||
|
|
||||||
|
b_sx3Multi->GetEntry(entry);
|
||||||
|
b_sx3ID->GetEntry(entry);
|
||||||
|
b_sx3Ch->GetEntry(entry);
|
||||||
|
b_sx3E->GetEntry(entry);
|
||||||
|
b_sx3T->GetEntry(entry);
|
||||||
|
|
||||||
|
sx3.CalIndex();
|
||||||
|
|
||||||
|
std::vector<std::pair<int, int>> ID;
|
||||||
|
for (int i = 0; i < sx3.multi; i++)
|
||||||
|
{
|
||||||
|
|
||||||
|
for (int j = i + 1; j < sx3.multi; j++)
|
||||||
|
{
|
||||||
|
// if (sx3.id[i] == 3)
|
||||||
|
hsx3Coin->Fill(sx3.index[i], sx3.index[j]);
|
||||||
|
}
|
||||||
|
if (sx3.e[i] > 100)
|
||||||
|
{
|
||||||
|
ID.push_back(std::pair<int, int>(sx3.id[i], i));
|
||||||
|
hsx3IndexVE->Fill(sx3.index[i], sx3.e[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ID.size() > 0)
|
||||||
|
{
|
||||||
|
std::sort(ID.begin(), ID.end(), [](const std::pair<int, int> &a, const std::pair<int, int> &b)
|
||||||
|
{ return a.first < b.first; });
|
||||||
|
|
||||||
|
// start with the first entry in the sorted array: channels that belong to the same detector are together in sequenmce
|
||||||
|
std::vector<std::pair<int, int>> sx3ID;
|
||||||
|
sx3ID.push_back(ID[0]);
|
||||||
|
bool found = false;
|
||||||
|
|
||||||
|
for (size_t i = 1; i < ID.size(); i++)
|
||||||
|
{ // Check if id of i belongs to the same detector and then add it to the detector ID vector
|
||||||
|
if (ID[i].first == sx3ID.back().first)
|
||||||
|
{ // count the nunmber of hits that belong to the same detector
|
||||||
|
sx3ID.push_back(ID[i]);
|
||||||
|
|
||||||
|
if (sx3ID.size() >= 3)
|
||||||
|
{
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{ // the next event does not belong to the same detector, abandon the first event and continue with the next one
|
||||||
|
if (!found)
|
||||||
|
{
|
||||||
|
sx3ID.clear();
|
||||||
|
sx3ID.push_back(ID[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (found)
|
||||||
|
{
|
||||||
|
int sx3ChUp = -1, sx3ChDn = -1, sx3ChBk = -1;
|
||||||
|
float sx3EUp = 0.0, sx3EDn = 0.0, sx3EBk = 0.0;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < sx3ID.size(); i++)
|
||||||
|
{
|
||||||
|
int index = sx3ID[i].second;
|
||||||
|
// Check the channel number and assign it to the appropriate channel type
|
||||||
|
if (sx3.ch[index] < 8)
|
||||||
|
{
|
||||||
|
if (sx3.ch[index] % 2 == 0)
|
||||||
|
{
|
||||||
|
sx3ChDn = sx3.ch[index] / 2;
|
||||||
|
sx3EDn = sx3.e[index];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sx3ChUp = sx3.ch[index] / 2;
|
||||||
|
sx3EUp = sx3.e[index];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sx3ChBk = sx3.ch[index] - 8;
|
||||||
|
// if (sx3ChBk == 2)
|
||||||
|
// printf("Found back channel Det %d Back %d \n", sx3.id[index], sx3ChBk);
|
||||||
|
sx3EBk = sx3.e[index];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < sx3.multi; i++)
|
||||||
|
{
|
||||||
|
// If we have a valid front and back channel, fill the histograms
|
||||||
|
hSX3->Fill(sx3ChDn + 4, sx3ChBk);
|
||||||
|
hSX3->Fill(sx3ChUp, sx3ChBk);
|
||||||
|
|
||||||
|
// Fill the histogram for the front vs back
|
||||||
|
hSX3FvsB->Fill(sx3EUp + sx3EDn, sx3EBk);
|
||||||
|
|
||||||
|
if (sx3.e[i] > 100 && sx3.id[i] == 3)
|
||||||
|
{
|
||||||
|
// back gain correction
|
||||||
|
|
||||||
|
// Fill the histogram for the front vs back with gain correction
|
||||||
|
// hSX3FvsB_g->Fill(sx3EUp + sx3EDn, sx3EBk);
|
||||||
|
// // Fill the index vs energy histogram
|
||||||
|
// hsx3IndexVE_g->Fill(sx3.index[i], sx3.e[i]);
|
||||||
|
// }
|
||||||
|
// {
|
||||||
|
TString histName = Form("hSX3FVB_id%d_U%d_D%d_B%d", sx3.id[i], sx3ChUp, sx3ChDn, sx3ChBk);
|
||||||
|
TH2F *hist2d = (TH2F *)gDirectory->Get(histName);
|
||||||
|
if (!hist2d)
|
||||||
|
{
|
||||||
|
hist2d = new TH2F(histName, Form("hSX3FVB_id%d_U%d_D%d_B%d", sx3.id[i], sx3ChUp, sx3ChDn, sx3ChBk), 400, 0, 16000, 400, 0, 16000);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if (sx3ChBk == 2)
|
||||||
|
// printf("Found back channel Det %d Back %d \n", sx3.id[i], sx3ChBk);
|
||||||
|
hsx3IndexVE_g->Fill(sx3.index[i], sx3.e[i]);
|
||||||
|
hSX3FvsB_g->Fill(sx3EUp + sx3EDn, sx3EBk);
|
||||||
|
|
||||||
|
hist2d->Fill(sx3EUp + sx3EDn, sx3EBk);
|
||||||
|
|
||||||
|
if (cut && cut->IsInside(sx3EUp + sx3EDn, sx3EBk) && cut1 && cut1->IsInside(sx3EUp / sx3EBk, sx3EDn / sx3EBk))
|
||||||
|
{
|
||||||
|
|
||||||
|
if (backGainValid[sx3.id[i]][sx3ChBk])
|
||||||
|
{
|
||||||
|
sx3EBk *= backGain[sx3.id[i]][sx3ChBk];
|
||||||
|
}
|
||||||
|
// Accumulate data for gain matching
|
||||||
|
dataPoints[{sx3.id[i], sx3ChBk, sx3ChUp, sx3ChDn}].emplace_back(sx3EBk, sx3EUp, sx3EDn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return kTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GainMatchSX3Front::Terminate()
|
||||||
|
{
|
||||||
|
|
||||||
|
std::map<std::tuple<int, int, int, int>, TVectorD> fitCoefficients;
|
||||||
|
|
||||||
|
// === Gain matching ===
|
||||||
|
|
||||||
|
std::ofstream outFile("sx3_GainMatchfront.txt");
|
||||||
|
if (!outFile.is_open())
|
||||||
|
{
|
||||||
|
std::cerr << "Error opening output file!" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
TH2F *hUvD = new TH2F("hUvD", " UvD; Up/CorrBack; Down/CorrBack", 600, 0, 1, 600, 0, 1);
|
||||||
|
|
||||||
|
for (const auto &kv : dataPoints)
|
||||||
|
{
|
||||||
|
auto [id, bk, u, d] = kv.first;
|
||||||
|
const auto &pts = kv.second;
|
||||||
|
|
||||||
|
if (pts.size() < 50)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
std::vector<double> uE, dE, udE, corrBkE;
|
||||||
|
|
||||||
|
for (const auto &pr : pts)
|
||||||
|
{
|
||||||
|
double eBkCorr, eUp, eDn;
|
||||||
|
std::tie(eBkCorr, eUp, eDn) = pr;
|
||||||
|
if ((eBkCorr < 100) || (eUp < 100) || (eDn < 100))
|
||||||
|
continue; // Skip if any energy is zero
|
||||||
|
uE.push_back(eUp / eBkCorr);
|
||||||
|
dE.push_back(eDn / eBkCorr);
|
||||||
|
udE.push_back(eUp + eDn);
|
||||||
|
corrBkE.push_back(eBkCorr);
|
||||||
|
hUvD->Fill(eUp / eBkCorr, eDn / eBkCorr);
|
||||||
|
}
|
||||||
|
if (uE.size() < 5 || dE.size() < 5 || corrBkE.size() < 5)
|
||||||
|
continue; // Ensure we have enough points for fitting
|
||||||
|
// TGraph g(udE.size(), udE.data(), corrBkE.data());
|
||||||
|
|
||||||
|
// TF1 f("f", "[0]*x", 0, 20000);
|
||||||
|
// f.SetParameter(0, 1.0); // Initial guess for the gain
|
||||||
|
// g.Fit(&f, "R");
|
||||||
|
|
||||||
|
const double fixedError = 0.0; // in ADC channels
|
||||||
|
|
||||||
|
std::vector<double> xVals, yVals, exVals, eyVals;
|
||||||
|
|
||||||
|
// Build data with fixed error
|
||||||
|
for (size_t i = 0; i < udE.size(); ++i)
|
||||||
|
{
|
||||||
|
double x = uE[i]; // front energy
|
||||||
|
double y = dE[i]; // back energy
|
||||||
|
|
||||||
|
xVals.push_back(x);
|
||||||
|
yVals.push_back(y);
|
||||||
|
exVals.push_back(fixedError); // error in up energy
|
||||||
|
eyVals.push_back(0.); // error in down energy
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build TGraphErrors with errors
|
||||||
|
TGraphErrors g(xVals.size(), xVals.data(), yVals.data(), exVals.data(), eyVals.data());
|
||||||
|
|
||||||
|
TF1 f("f", "[0]*x+[1]", 0, 16000);
|
||||||
|
f.SetParameter(0, -1.0); // Initial guess
|
||||||
|
|
||||||
|
if (drawCanvases)
|
||||||
|
{
|
||||||
|
g.SetTitle(Form("Detector %d: U%d D%d B%d", id, u, d, bk));
|
||||||
|
g.SetMarkerStyle(20);
|
||||||
|
g.SetMarkerColor(kBlue);
|
||||||
|
g.Draw("AP");
|
||||||
|
|
||||||
|
g.Fit(&f, interactiveMode ? "Q" : "QNR"); // 'R' avoids refit, 'N' skips drawing
|
||||||
|
|
||||||
|
if (verboseFit)
|
||||||
|
{
|
||||||
|
double chi2 = f.GetChisquare();
|
||||||
|
int ndf = f.GetNDF();
|
||||||
|
double reducedChi2 = (ndf != 0) ? chi2 / ndf : -1;
|
||||||
|
|
||||||
|
std::cout << Form("Det%d U%d D%d B%d → Gain: %.4f | χ²/ndf = %.2f/%d = %.2f",
|
||||||
|
id, u, d, bk, f.GetParameter(0), chi2, ndf, reducedChi2)
|
||||||
|
<< std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (interactiveMode)
|
||||||
|
{
|
||||||
|
c.Update();
|
||||||
|
gPad->WaitPrimitive();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
c.Close(); // Optionally avoid clutter in batch
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
g.Fit(&f, "QNR");
|
||||||
|
}
|
||||||
|
|
||||||
|
double slope = f.GetParameter(0);
|
||||||
|
double intercept = f.GetParameter(1);
|
||||||
|
|
||||||
|
// printf("Front gain Det%d Back%d Up%dDn%d → %.4f\n", id, bk, u, d, frontGain[id][bk][u][d]);
|
||||||
|
if (std::abs(slope + 1.0) < 0.3) // sanity check
|
||||||
|
{
|
||||||
|
frontGain[id][bk][u][d] = slope;
|
||||||
|
|
||||||
|
frontGainValid[id][bk][u][d] = true;
|
||||||
|
outFile << id << " " << bk << " " << u << " " << d << " " << TMath::Abs(slope)/intercept << " " << 1.0/intercept << std::endl;
|
||||||
|
printf("Back slope Det%d Bk%d → %.4f\n", id, bk, slope);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cerr << "Warning: Bad slope for Det" << id << " Bk" << bk
|
||||||
|
<< " slope=" << f.GetParameter(0) << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
outFile.close();
|
||||||
|
std::cout << "Gain matching complete." << std::endl;
|
||||||
|
|
||||||
|
// === Stage 3: Create corrected histogram ===
|
||||||
|
TH2F *hCorrectedFvB = new TH2F("hCorrectedFvB", "Corrected;Corrected Front Sum;Corrected Back", 800, 0, 8000, 800, 0, 8000);
|
||||||
|
TH2F *hCorrectedUvD = new TH2F("hCorrectedUvD", "Corrected UvD; UvD Up; UvD Down", 600, 0, 1, 600, 0, 1);
|
||||||
|
|
||||||
|
for (const auto &kv : dataPoints)
|
||||||
|
{
|
||||||
|
|
||||||
|
auto [id, bk, u, d] = kv.first;
|
||||||
|
double front;
|
||||||
|
if (frontGainValid[id][bk][u][d])
|
||||||
|
front = frontGain[id][bk][u][d];
|
||||||
|
else
|
||||||
|
continue;
|
||||||
|
for (const auto &pr : kv.second)
|
||||||
|
{
|
||||||
|
double eBk, eUp, eDn;
|
||||||
|
std::tie(eBk, eUp, eDn) = pr;
|
||||||
|
double corrUp = eUp * front;
|
||||||
|
// double corrDn = eDn * front;
|
||||||
|
|
||||||
|
hCorrectedFvB->Fill(corrUp + eDn, eBk);
|
||||||
|
hCorrectedUvD->Fill(corrUp / eBk, eDn / eBk);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// // === Final canvas ===
|
||||||
|
// gStyle->SetOptStat(1110);
|
||||||
|
// TCanvas *c1 = new TCanvas("c1", "Gain Correction Results", 1200, 600);
|
||||||
|
// c1->Divide(2, 1);
|
||||||
|
|
||||||
|
// c1->cd(1);
|
||||||
|
// hSX3FvsB_g->SetTitle("Before Correction (Gated)");
|
||||||
|
// hSX3FvsB_g->GetXaxis()->SetTitle("Measured Front Sum (E_Up + E_Dn)");
|
||||||
|
// hSX3FvsB_g->GetYaxis()->SetTitle("Measured Back E");
|
||||||
|
// hSX3FvsB_g->Draw("colz");
|
||||||
|
|
||||||
|
// c1->cd(2);
|
||||||
|
// hCorrectedFvB->SetTitle("After Correction");
|
||||||
|
// hCorrectedFvB->Draw("colz");
|
||||||
|
// TF1 *diag = new TF1("diag", "x", 0, 40000);
|
||||||
|
// diag->SetLineColor(kRed);
|
||||||
|
// diag->SetLineWidth(2);
|
||||||
|
// diag->Draw("same");
|
||||||
|
|
||||||
|
std::cout << "Terminate() completed successfully." << std::endl;
|
||||||
|
}
|
||||||
104
GainMatchSX3Front.h
Normal file
104
GainMatchSX3Front.h
Normal file
|
|
@ -0,0 +1,104 @@
|
||||||
|
#ifndef GainMatchSX3Front_h
|
||||||
|
#define GainMatchSX3Front_h
|
||||||
|
|
||||||
|
#include <TROOT.h>
|
||||||
|
#include <TChain.h>
|
||||||
|
#include <TFile.h>
|
||||||
|
#include <TSelector.h>
|
||||||
|
|
||||||
|
#include "Armory/ClassDet.h"
|
||||||
|
|
||||||
|
class GainMatchSX3Front : public TSelector {
|
||||||
|
public :
|
||||||
|
TTree *fChain; //!pointer to the analyzed TTree or TChain
|
||||||
|
|
||||||
|
// Fixed size dimensions of array or collections stored in the TTree if any.
|
||||||
|
|
||||||
|
// Declaration of leaf types
|
||||||
|
Det sx3;
|
||||||
|
Det qqq;
|
||||||
|
Det pc ;
|
||||||
|
|
||||||
|
ULong64_t evID;
|
||||||
|
UInt_t run;
|
||||||
|
|
||||||
|
// List of branches
|
||||||
|
TBranch *b_eventID; //!
|
||||||
|
TBranch *b_run; //!
|
||||||
|
TBranch *b_sx3Multi; //!
|
||||||
|
TBranch *b_sx3ID; //!
|
||||||
|
TBranch *b_sx3Ch; //!
|
||||||
|
TBranch *b_sx3E; //!
|
||||||
|
TBranch *b_sx3T; //!
|
||||||
|
TBranch *b_qqqMulti; //!
|
||||||
|
TBranch *b_qqqID; //!
|
||||||
|
TBranch *b_qqqCh; //!
|
||||||
|
TBranch *b_qqqE; //!
|
||||||
|
TBranch *b_qqqT; //!
|
||||||
|
TBranch *b_pcMulti; //!
|
||||||
|
TBranch *b_pcID; //!
|
||||||
|
TBranch *b_pcCh; //!
|
||||||
|
TBranch *b_pcE; //!
|
||||||
|
TBranch *b_pcT; //!
|
||||||
|
|
||||||
|
GainMatchSX3Front(TTree * /*tree*/ =0) : fChain(0) { }
|
||||||
|
virtual ~GainMatchSX3Front() { }
|
||||||
|
virtual Int_t Version() const { return 2; }
|
||||||
|
virtual void Begin(TTree *tree);
|
||||||
|
virtual void SlaveBegin(TTree *tree);
|
||||||
|
virtual void Init(TTree *tree);
|
||||||
|
virtual Bool_t Notify();
|
||||||
|
virtual Bool_t Process(Long64_t entry);
|
||||||
|
virtual Int_t GetEntry(Long64_t entry, Int_t getall = 0) { return fChain ? fChain->GetTree()->GetEntry(entry, getall) : 0; }
|
||||||
|
virtual void SetOption(const char *option) { fOption = option; }
|
||||||
|
virtual void SetObject(TObject *obj) { fObject = obj; }
|
||||||
|
virtual void SetInputList(TList *input) { fInput = input; }
|
||||||
|
virtual TList *GetOutputList() const { return fOutput; }
|
||||||
|
virtual void SlaveTerminate();
|
||||||
|
virtual void Terminate();
|
||||||
|
|
||||||
|
ClassDef(GainMatchSX3Front,0);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef GainMatchSX3Front_cxx
|
||||||
|
void GainMatchSX3Front::Init(TTree *tree){
|
||||||
|
|
||||||
|
// Set branch addresses and branch pointers
|
||||||
|
if (!tree) return;
|
||||||
|
fChain = tree;
|
||||||
|
fChain->SetMakeClass(1);
|
||||||
|
|
||||||
|
fChain->SetBranchAddress("evID", &evID, &b_eventID);
|
||||||
|
fChain->SetBranchAddress("run", &run, &b_run);
|
||||||
|
|
||||||
|
sx3.SetDetDimension(24,12);
|
||||||
|
qqq.SetDetDimension(4,32);
|
||||||
|
pc.SetDetDimension(2,24);
|
||||||
|
|
||||||
|
fChain->SetBranchAddress("sx3Multi", &sx3.multi, &b_sx3Multi);
|
||||||
|
fChain->SetBranchAddress("sx3ID", &sx3.id, &b_sx3ID);
|
||||||
|
fChain->SetBranchAddress("sx3Ch", &sx3.ch, &b_sx3Ch);
|
||||||
|
fChain->SetBranchAddress("sx3E", &sx3.e, &b_sx3E);
|
||||||
|
fChain->SetBranchAddress("sx3T", &sx3.t, &b_sx3T);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Bool_t GainMatchSX3Front::Notify(){
|
||||||
|
|
||||||
|
return kTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GainMatchSX3Front::SlaveBegin(TTree * /*tree*/){
|
||||||
|
|
||||||
|
TString option = GetOption();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void GainMatchSX3Front::SlaveTerminate(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif // #ifdef GainMatchSX3Front_cxx
|
||||||
245
GainMatchSX3Front1.C
Normal file
245
GainMatchSX3Front1.C
Normal file
|
|
@ -0,0 +1,245 @@
|
||||||
|
#define GainMatchSX3_cxx
|
||||||
|
|
||||||
|
#include "GainMatchSX3.h"
|
||||||
|
#include "Armory/ClassSX3.h"
|
||||||
|
#include <TFile.h>
|
||||||
|
#include <TTree.h>
|
||||||
|
#include <TGraph.h>
|
||||||
|
#include <TF1.h>
|
||||||
|
#include <TH2F.h>
|
||||||
|
#include <TCanvas.h>
|
||||||
|
#include <TStyle.h>
|
||||||
|
#include <TApplication.h>
|
||||||
|
#include <map>
|
||||||
|
#include <vector>
|
||||||
|
#include <tuple>
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
// Constants
|
||||||
|
const int MAX_DET = 24;
|
||||||
|
const int MAX_BK = 4;
|
||||||
|
const int MAX_UP = 4;
|
||||||
|
const int MAX_DOWN = 4;
|
||||||
|
|
||||||
|
// Gain arrays
|
||||||
|
double backGain[MAX_DET][MAX_BK][MAX_UP][MAX_DOWN] = {{{{0}}}};
|
||||||
|
bool backGainValid[MAX_DET][MAX_BK][MAX_UP][MAX_DOWN] = {{{{false}}}};
|
||||||
|
|
||||||
|
double frontGain[MAX_DET][MAX_BK][MAX_UP][MAX_DOWN] = {{{{0}}}};
|
||||||
|
bool frontGainValid[MAX_DET][MAX_BK][MAX_UP][MAX_DOWN] = {{{{false}}}};
|
||||||
|
|
||||||
|
// Data container
|
||||||
|
std::map<std::tuple<int, int, int, int>, std::vector<std::tuple<double, double, double>>> dataPoints;
|
||||||
|
|
||||||
|
// Load back gains
|
||||||
|
void LoadBackGains(const std::string &filename)
|
||||||
|
{
|
||||||
|
std::ifstream infile(filename);
|
||||||
|
if (!infile.is_open())
|
||||||
|
{
|
||||||
|
std::cerr << "Error opening " << filename << "!" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int id, bk, u, d;
|
||||||
|
double gain;
|
||||||
|
while (infile >> id >> bk >> u >> d >> gain)
|
||||||
|
{
|
||||||
|
backGain[id][bk][u][d] = gain;
|
||||||
|
backGainValid[id][bk][u][d] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
infile.close();
|
||||||
|
std::cout << "Loaded back gains from " << filename << std::endl;
|
||||||
|
SX3 sx3_contr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Front gain matching function
|
||||||
|
Bool_t GainMatchSX3::Process(Long64_t entry)
|
||||||
|
{
|
||||||
|
// Link SX3 branches
|
||||||
|
|
||||||
|
b_sx3Multi->GetEntry(entry);
|
||||||
|
b_sx3ID->GetEntry(entry);
|
||||||
|
b_sx3Ch->GetEntry(entry);
|
||||||
|
b_sx3E->GetEntry(entry);
|
||||||
|
b_sx3T->GetEntry(entry);
|
||||||
|
|
||||||
|
sx3.CalIndex();
|
||||||
|
|
||||||
|
Long64_t nentries = tree->GetEntries(Long64_t entry);
|
||||||
|
std::cout << "Total entries: " << nentries << std::endl;
|
||||||
|
|
||||||
|
TH2F *hBefore = new TH2F("hBefore", "Before Correction;E_Up+E_Dn;Back Energy", 400, 0, 40000, 400, 0, 40000);
|
||||||
|
TH2F *hAfter = new TH2F("hAfter", "After Correction;E_Up+E_Dn;Corrected Back Energy", 400, 0, 40000, 400, 0, 40000);
|
||||||
|
|
||||||
|
for (Long64_t entry = 0; entry < nentries; ++entry)
|
||||||
|
{
|
||||||
|
tree->GetEntry(entry);
|
||||||
|
sx3.CalIndex();
|
||||||
|
|
||||||
|
std::vector<std::pair<int, int>> ID;
|
||||||
|
|
||||||
|
for (int i = 0; i < sx3.multi; i++)
|
||||||
|
{
|
||||||
|
if (sx3.e[i] > 100)
|
||||||
|
{
|
||||||
|
ID.push_back({sx3.id[i], i});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ID.empty())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Sort by id
|
||||||
|
std::sort(ID.begin(), ID.end(), [](auto &a, auto &b) { return a.first < b.first; });
|
||||||
|
|
||||||
|
std::vector<std::pair<int, int>> sx3ID;
|
||||||
|
sx3ID.push_back(ID[0]);
|
||||||
|
bool found = false;
|
||||||
|
|
||||||
|
for (size_t i = 1; i < ID.size(); i++)
|
||||||
|
{
|
||||||
|
if (ID[i].first == sx3ID.back().first)
|
||||||
|
{
|
||||||
|
sx3ID.push_back(ID[i]);
|
||||||
|
if (sx3ID.size() >= 3)
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
else if (!found)
|
||||||
|
{
|
||||||
|
sx3ID.clear();
|
||||||
|
sx3ID.push_back(ID[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!found)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
int sx3ChUp = -1, sx3ChDn = -1, sx3ChBk = -1;
|
||||||
|
float sx3EUp = 0.0, sx3EDn = 0.0, sx3EBk = 0.0;
|
||||||
|
int sx3id = sx3ID[0].first;
|
||||||
|
|
||||||
|
for (auto &[id, idx] : sx3ID)
|
||||||
|
{
|
||||||
|
if (sx3.ch[idx] < 8)
|
||||||
|
{
|
||||||
|
if (sx3.ch[idx] % 2 == 0)
|
||||||
|
{
|
||||||
|
sx3ChDn = sx3.ch[idx] / 2;
|
||||||
|
sx3EDn = sx3.e[idx];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sx3ChUp = sx3.ch[idx] / 2;
|
||||||
|
sx3EUp = sx3.e[idx];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sx3ChBk = sx3.ch[idx] - 8;
|
||||||
|
sx3EBk = sx3.e[idx];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sx3ChUp < 0 || sx3ChDn < 0 || sx3ChBk < 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!backGainValid[sx3id][sx3ChBk][sx3ChUp][sx3ChDn])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
double corrBk = sx3EBk * backGain[sx3id][sx3ChBk][sx3ChUp][sx3ChDn];
|
||||||
|
|
||||||
|
hBefore->Fill(sx3EUp + sx3EDn, sx3EBk);
|
||||||
|
hAfter->Fill(sx3EUp + sx3EDn, corrBk);
|
||||||
|
|
||||||
|
dataPoints[{sx3id, sx3ChBk, sx3ChUp, sx3ChDn}].emplace_back(corrBk, sx3EUp, sx3EDn);
|
||||||
|
}
|
||||||
|
|
||||||
|
// === Fit front gains ===
|
||||||
|
std::ofstream outFile("sx3_GainMatchfront.txt");
|
||||||
|
if (!outFile.is_open())
|
||||||
|
{
|
||||||
|
std::cerr << "Error opening sx3_GainMatchfront.txt!" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto &kv : dataPoints)
|
||||||
|
{
|
||||||
|
auto [id, bk, u, d] = kv.first;
|
||||||
|
const auto &pts = kv.second;
|
||||||
|
|
||||||
|
if (pts.size() < 5)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
std::vector<double> udE, corrBkE;
|
||||||
|
|
||||||
|
for (const auto &pr : pts)
|
||||||
|
{
|
||||||
|
double eBkCorr, eUp, eDn;
|
||||||
|
std::tie(eBkCorr, eUp, eDn) = pr;
|
||||||
|
udE.push_back(eUp + eDn);
|
||||||
|
corrBkE.push_back(eBkCorr);
|
||||||
|
}
|
||||||
|
|
||||||
|
TGraph g(udE.size(), udE.data(), corrBkE.data());
|
||||||
|
TF1 f("f", "[0]*x", 0, 40000);
|
||||||
|
g.Fit(&f, "QNR");
|
||||||
|
|
||||||
|
frontGain[id][bk][u][d] = f.GetParameter(0);
|
||||||
|
frontGainValid[id][bk][u][d] = true;
|
||||||
|
|
||||||
|
outFile << id << " " << bk << " " << u << " " << d << " " << frontGain[id][bk][u][d] << std::endl;
|
||||||
|
printf("Front gain Det%d Back%d Up%dDn%d → %.4f\n", id, bk, u, d, frontGain[id][bk][u][d]);
|
||||||
|
}
|
||||||
|
|
||||||
|
outFile.close();
|
||||||
|
std::cout << "Front gain matching complete." << std::endl;
|
||||||
|
|
||||||
|
// === Draw diagnostic plots ===
|
||||||
|
gStyle->SetOptStat(1110);
|
||||||
|
TCanvas *c = new TCanvas("c", "Gain Matching Diagnostics", 1200, 600);
|
||||||
|
c->Divide(2, 1);
|
||||||
|
|
||||||
|
c->cd(1);
|
||||||
|
hBefore->Draw("colz");
|
||||||
|
TF1 *diag1 = new TF1("diag1", "x", 0, 40000);
|
||||||
|
diag1->SetLineColor(kRed);
|
||||||
|
diag1->Draw("same");
|
||||||
|
|
||||||
|
c->cd(2);
|
||||||
|
hAfter->Draw("colz");
|
||||||
|
TF1 *diag2 = new TF1("diag2", "x", 0, 40000);
|
||||||
|
diag2->SetLineColor(kRed);
|
||||||
|
diag2->Draw("same");
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
TApplication app("app", &argc, argv);
|
||||||
|
|
||||||
|
// Load back gains
|
||||||
|
LoadBackGains("sx3_GainMatchback.txt");
|
||||||
|
|
||||||
|
// Open tree
|
||||||
|
TFile *f = TFile::Open("input_tree.root"); // <<< Change file name
|
||||||
|
if (!f || f->IsZombie())
|
||||||
|
{
|
||||||
|
std::cerr << "Cannot open input_tree.root!" << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
TTree *tree = (TTree *)f->Get("tree");
|
||||||
|
if (!tree)
|
||||||
|
{
|
||||||
|
std::cerr << "Tree not found!" << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run front gain matching
|
||||||
|
GainMatchSX3(tree);
|
||||||
|
|
||||||
|
app.Run();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
3664
MakeVertex.C
Normal file
3664
MakeVertex.C
Normal file
File diff suppressed because it is too large
Load Diff
155
MakeVertex.h
Normal file
155
MakeVertex.h
Normal file
|
|
@ -0,0 +1,155 @@
|
||||||
|
#ifndef MakeVertex_h
|
||||||
|
#define MakeVertex_h
|
||||||
|
|
||||||
|
#include <TROOT.h>
|
||||||
|
#include <TChain.h>
|
||||||
|
#include <TApplication.h>
|
||||||
|
#include <TFile.h>
|
||||||
|
#include <TSelector.h>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <vector> // Required for vectors
|
||||||
|
#include <utility> // Required for std::pair
|
||||||
|
|
||||||
|
#include "Armory/ClassDet.h"
|
||||||
|
#include "Armory/ClassPW.h" // YOU ADDED THIS (Correct! Defines Coord)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
std::string dataset;
|
||||||
|
double source_vertex=53.0;
|
||||||
|
bool reactiondata=false;
|
||||||
|
|
||||||
|
class MakeVertex : public TSelector {
|
||||||
|
public :
|
||||||
|
TTree *fChain; //!pointer to the analyzed TTree or TChain
|
||||||
|
|
||||||
|
// Declaration of leaf types
|
||||||
|
Det sx3;
|
||||||
|
Det qqq;
|
||||||
|
Det pc ;
|
||||||
|
Det misc;
|
||||||
|
|
||||||
|
ULong64_t evID;
|
||||||
|
UInt_t run;
|
||||||
|
|
||||||
|
// List of branches
|
||||||
|
TBranch *b_eventID; //!
|
||||||
|
TBranch *b_run; //!
|
||||||
|
TBranch *b_sx3Multi; //!
|
||||||
|
TBranch *b_sx3ID; //!
|
||||||
|
TBranch *b_sx3Ch; //!
|
||||||
|
TBranch *b_sx3E; //!
|
||||||
|
TBranch *b_sx3T; //!
|
||||||
|
TBranch *b_qqqMulti; //!
|
||||||
|
TBranch *b_qqqID; //!
|
||||||
|
TBranch *b_qqqCh; //!
|
||||||
|
TBranch *b_qqqE; //!
|
||||||
|
TBranch *b_qqqT; //!
|
||||||
|
TBranch *b_pcMulti; //!
|
||||||
|
TBranch *b_pcID; //!
|
||||||
|
TBranch *b_pcCh; //!
|
||||||
|
TBranch *b_pcE; //!
|
||||||
|
TBranch *b_pcT; //!
|
||||||
|
TBranch *b_miscMulti; //!
|
||||||
|
TBranch *b_miscID; //!
|
||||||
|
TBranch *b_miscCh; //!
|
||||||
|
TBranch *b_miscE; //!
|
||||||
|
TBranch *b_miscT; //!
|
||||||
|
TBranch *b_miscTf; //!
|
||||||
|
|
||||||
|
|
||||||
|
// 2. Persistent Vectors (REQUIRED for the optimized .cxx to work)
|
||||||
|
std::vector<std::pair<int, double>> anodeHits;
|
||||||
|
std::vector<std::pair<int, double>> cathodeHits;
|
||||||
|
std::vector<std::pair<int, double>> corrcatMax;
|
||||||
|
std::vector<std::pair<int, double>> corranoMax;
|
||||||
|
std::vector<double> cathodeTimes;
|
||||||
|
std::vector<double> anodeTimes;
|
||||||
|
|
||||||
|
MakeVertex(TTree * /*tree*/ =0) : fChain(0) { }
|
||||||
|
virtual ~MakeVertex() { }
|
||||||
|
virtual Int_t Version() const {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
virtual void Begin(TTree *tree);
|
||||||
|
virtual void SlaveBegin(TTree *tree);
|
||||||
|
virtual void Init(TTree *tree);
|
||||||
|
virtual Bool_t Notify();
|
||||||
|
virtual Bool_t Process(Long64_t entry);
|
||||||
|
virtual Int_t GetEntry(Long64_t entry, Int_t getall = 0) {
|
||||||
|
return fChain ? fChain->GetTree()->GetEntry(entry, getall) : 0;
|
||||||
|
}
|
||||||
|
virtual void SetOption(const char *option) {
|
||||||
|
fOption = option;
|
||||||
|
}
|
||||||
|
virtual void SetObject(TObject *obj) {
|
||||||
|
fObject = obj;
|
||||||
|
}
|
||||||
|
virtual void SetInputList(TList *input) {
|
||||||
|
fInput = input;
|
||||||
|
}
|
||||||
|
virtual TList *GetOutputList() const {
|
||||||
|
return fOutput;
|
||||||
|
}
|
||||||
|
virtual void SlaveTerminate();
|
||||||
|
virtual void Terminate();
|
||||||
|
|
||||||
|
void MakeAnalysisHistograms();
|
||||||
|
void MakeDiagnosticHistograms();
|
||||||
|
|
||||||
|
ClassDef(MakeVertex,0);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef MakeVertex_cxx
|
||||||
|
void MakeVertex::Init(TTree *tree) {
|
||||||
|
|
||||||
|
if (!tree) return;
|
||||||
|
fChain = tree;
|
||||||
|
fChain->SetMakeClass(1);
|
||||||
|
|
||||||
|
fChain->SetBranchAddress("evID", &evID, &b_eventID);
|
||||||
|
fChain->SetBranchAddress("run", &run, &b_run);
|
||||||
|
|
||||||
|
sx3.SetDetDimension(24,12);
|
||||||
|
qqq.SetDetDimension(4,32);
|
||||||
|
pc.SetDetDimension(2,24);
|
||||||
|
|
||||||
|
fChain->SetBranchAddress("sx3Multi", &sx3.multi, &b_sx3Multi);
|
||||||
|
fChain->SetBranchAddress("sx3ID", &sx3.id, &b_sx3ID);
|
||||||
|
fChain->SetBranchAddress("sx3Ch", &sx3.ch, &b_sx3Ch);
|
||||||
|
fChain->SetBranchAddress("sx3E", &sx3.e, &b_sx3E);
|
||||||
|
fChain->SetBranchAddress("sx3T", &sx3.t, &b_sx3T);
|
||||||
|
fChain->SetBranchAddress("qqqMulti", &qqq.multi, &b_qqqMulti);
|
||||||
|
fChain->SetBranchAddress("qqqID", &qqq.id, &b_qqqID);
|
||||||
|
fChain->SetBranchAddress("qqqCh", &qqq.ch, &b_qqqCh);
|
||||||
|
fChain->SetBranchAddress("qqqE", &qqq.e, &b_qqqE);
|
||||||
|
fChain->SetBranchAddress("qqqT", &qqq.t, &b_qqqT);
|
||||||
|
fChain->SetBranchAddress("pcMulti", &pc.multi, &b_pcMulti);
|
||||||
|
fChain->SetBranchAddress("pcID", &pc.id, &b_pcID);
|
||||||
|
fChain->SetBranchAddress("pcCh", &pc.ch, &b_pcCh);
|
||||||
|
fChain->SetBranchAddress("pcE", &pc.e, &b_pcE);
|
||||||
|
fChain->SetBranchAddress("pcT", &pc.t, &b_pcT);
|
||||||
|
|
||||||
|
#ifdef ADD_NEW_BRANCHES
|
||||||
|
fChain->SetBranchAddress("miscMulti", &misc.multi, &b_miscMulti);
|
||||||
|
fChain->SetBranchAddress("miscID", &misc.id, &b_miscID);
|
||||||
|
fChain->SetBranchAddress("miscCh", &misc.ch, &b_miscCh);
|
||||||
|
fChain->SetBranchAddress("miscE", &misc.e, &b_miscE);
|
||||||
|
fChain->SetBranchAddress("miscT", &misc.t, &b_miscT);
|
||||||
|
fChain->SetBranchAddress("miscF", &misc.tf, &b_miscTf);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
Bool_t MakeVertex::Notify() {
|
||||||
|
return kTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MakeVertex::SlaveBegin(TTree * /*tree*/) {
|
||||||
|
// TString option = GetOption();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MakeVertex::SlaveTerminate() {
|
||||||
|
}
|
||||||
|
#endif // #ifdef MakeVertex_cxx
|
||||||
221
MakeVertexSX3.C
Normal file
221
MakeVertexSX3.C
Normal file
|
|
@ -0,0 +1,221 @@
|
||||||
|
#define MakeVertexSX3_cxx
|
||||||
|
|
||||||
|
#include "MakeVertexSX3.h"
|
||||||
|
#include "Armory/ClassPW.h"
|
||||||
|
#include "Armory/HistPlotter.h"
|
||||||
|
#include "Armory/SX3Geom.h"
|
||||||
|
|
||||||
|
#include <TH2.h>
|
||||||
|
#include <TStyle.h>
|
||||||
|
#include <TCanvas.h>
|
||||||
|
#include <TMath.h>
|
||||||
|
#include <TBranch.h>
|
||||||
|
#include "TVector3.h"
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <vector>
|
||||||
|
#include <array>
|
||||||
|
#include <map>
|
||||||
|
#include <utility>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
// Global instances
|
||||||
|
PW pw_contr;
|
||||||
|
PW pwinstance;
|
||||||
|
TVector3 hitPos;
|
||||||
|
double qqqenergy, qqqtimestamp;
|
||||||
|
class Event {
|
||||||
|
public:
|
||||||
|
Event(TVector3 p, double e1, double e2, double t1, double t2) : pos(p), Energy1(e1), Energy2(e2), Time1(t1), Time2(t2) {}
|
||||||
|
Event(TVector3 p, double e1, double e2, double t1, double t2, int c1, int c2) : pos(p), Energy1(e1), Energy2(e2), Time1(t1), Time2(t2), ch1(c1), ch2(c2) {}
|
||||||
|
|
||||||
|
TVector3 pos;
|
||||||
|
int ch1=-1; //int(ch1/16) gives qqq id, ch1%16 gives ring#
|
||||||
|
int ch2=-1; //int(ch2/16) gives qqq id, ch2%16 gives wedge#
|
||||||
|
double Energy1=-1; //Front for QQQ, Anode for PC
|
||||||
|
double Energy2=-1; //Back for QQQ, Cathode for PC
|
||||||
|
double Time1=-1;
|
||||||
|
double Time2=-1;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
// Calibration globals
|
||||||
|
const int MAX_QQQ = 4;
|
||||||
|
const int MAX_RING = 16;
|
||||||
|
const int MAX_WEDGE = 16;
|
||||||
|
double qqqGain[MAX_QQQ][MAX_RING][MAX_WEDGE] = {{{0}}};
|
||||||
|
bool qqqGainValid[MAX_QQQ][MAX_RING][MAX_WEDGE] = {{{false}}};
|
||||||
|
double qqqCalib[MAX_QQQ][MAX_RING][MAX_WEDGE] = {{{0}}};
|
||||||
|
bool qqqCalibValid[MAX_QQQ][MAX_RING][MAX_WEDGE] = {{{false}}};
|
||||||
|
// TCutg *cutQQQ;
|
||||||
|
|
||||||
|
double sx3BackGain[24][4][4] = {{{1.}}};
|
||||||
|
double sx3FrontGain[24][4] = {{1.}};
|
||||||
|
double sx3FrontOffset[24][4] = {{0.}};
|
||||||
|
double sx3RightGain[24][4] = {{1.}};
|
||||||
|
|
||||||
|
// PC Arrays
|
||||||
|
double pcSlope[48];
|
||||||
|
double pcIntercept[48];
|
||||||
|
|
||||||
|
HistPlotter *plotter;
|
||||||
|
|
||||||
|
bool HitNonZero;
|
||||||
|
bool sx3ecut;
|
||||||
|
bool qqqEcut;
|
||||||
|
|
||||||
|
void MakeVertexSX3::Begin(TTree * /*tree*/)
|
||||||
|
{
|
||||||
|
TString option = GetOption();
|
||||||
|
plotter = new HistPlotter("Analyzer_SX3.root", "TFILE");
|
||||||
|
pw_contr.ConstructGeo();
|
||||||
|
pwinstance.ConstructGeo();
|
||||||
|
|
||||||
|
for (int i = 0; i < 48; i++)
|
||||||
|
{
|
||||||
|
pcSlope[i] = 1.0; // Default slope = 1 (preserves Raw energy)
|
||||||
|
pcIntercept[i] = 0.0; // Default intercept = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string dataset = "27Al";
|
||||||
|
{
|
||||||
|
std::ifstream infile("sx3cal/"+dataset+"/backgains.dat");
|
||||||
|
std::string temp;
|
||||||
|
int backpos, frontpos, clkpos;
|
||||||
|
if (infile.is_open())
|
||||||
|
while(infile>>clkpos>>temp>>frontpos>>temp>>backpos>>sx3BackGain[clkpos][frontpos][backpos])
|
||||||
|
;//std::cout << sx3BackGain[clkpos][frontpos][backpos] << std::endl;
|
||||||
|
infile.close();
|
||||||
|
|
||||||
|
infile.open("sx3cal/"+dataset+"/frontgains.dat");
|
||||||
|
if (infile.is_open())
|
||||||
|
while(infile>>clkpos>>temp>>temp>>frontpos>>sx3FrontOffset[clkpos][frontpos]>>sx3FrontGain[clkpos][frontpos])
|
||||||
|
;//std::cout << sx3FrontOffset[clkpos][frontpos] << " " << sx3FrontGain[clkpos][frontpos] << std::endl;
|
||||||
|
infile.close();
|
||||||
|
|
||||||
|
infile.open("sx3cal/"+dataset+"/rightgains.dat");
|
||||||
|
if (infile.is_open())
|
||||||
|
while(infile>>clkpos>>frontpos>>temp>>sx3RightGain[clkpos][frontpos]) {
|
||||||
|
sx3RightGain[clkpos][frontpos]=TMath::Abs(sx3RightGain[clkpos][frontpos]);
|
||||||
|
}
|
||||||
|
infile.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Bool_t MakeVertexSX3::Process(Long64_t entry)
|
||||||
|
{
|
||||||
|
hitPos.Clear();
|
||||||
|
qqqenergy = -1;
|
||||||
|
qqqtimestamp=-1;
|
||||||
|
HitNonZero = false;
|
||||||
|
bool qqq1000cut = false;
|
||||||
|
b_sx3Multi->GetEntry(entry);
|
||||||
|
b_sx3ID->GetEntry(entry);
|
||||||
|
b_sx3Ch->GetEntry(entry);
|
||||||
|
b_sx3E->GetEntry(entry);
|
||||||
|
b_sx3T->GetEntry(entry);
|
||||||
|
b_qqqMulti->GetEntry(entry);
|
||||||
|
b_qqqID->GetEntry(entry);
|
||||||
|
b_qqqCh->GetEntry(entry);
|
||||||
|
b_qqqE->GetEntry(entry);
|
||||||
|
b_qqqT->GetEntry(entry);
|
||||||
|
b_pcMulti->GetEntry(entry);
|
||||||
|
b_pcID->GetEntry(entry);
|
||||||
|
b_pcCh->GetEntry(entry);
|
||||||
|
b_pcE->GetEntry(entry);
|
||||||
|
b_pcT->GetEntry(entry);
|
||||||
|
|
||||||
|
sx3.CalIndex();
|
||||||
|
qqq.CalIndex();
|
||||||
|
pc.CalIndex();
|
||||||
|
|
||||||
|
std::vector<Event> sx3Events;
|
||||||
|
if(sx3.multi>1) {
|
||||||
|
std::array<sx3det,12> Fsx3;
|
||||||
|
//std::cout << "-----" << std::endl;
|
||||||
|
for(int i=0; i<sx3.multi; i++) {
|
||||||
|
if(sx3.id[i]>=12) continue;
|
||||||
|
int id = sx3.id[i];
|
||||||
|
if(sx3.ch[i]>=8) {
|
||||||
|
int sx3ch=sx3.ch[i]-8;
|
||||||
|
sx3ch=(sx3ch+3)%4;
|
||||||
|
//if(sx3ch==0 || sx3ch==3) continue;
|
||||||
|
float value=sx3.e[i];
|
||||||
|
int gch = sx3.id[i]*4+(sx3.ch[i]-8);
|
||||||
|
Fsx3.at(id).fillevent("BACK",sx3ch,value);
|
||||||
|
Fsx3.at(id).ts = static_cast<double>(sx3.t[i]);
|
||||||
|
plotter->Fill2D("sx3backs_raw",100,0,100,800,0,4096,gch,sx3.e[i]);
|
||||||
|
} else {
|
||||||
|
int sx3ch=sx3.ch[i]/2;
|
||||||
|
double value=sx3.e[i];
|
||||||
|
if(sx3.ch[i]%2==0) {
|
||||||
|
Fsx3.at(id).fillevent("FRONT_L",sx3ch,value*sx3RightGain[id][sx3ch]);
|
||||||
|
} else {
|
||||||
|
Fsx3.at(id).fillevent("FRONT_R",sx3ch,value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for(int id=0; id<12; id++) {
|
||||||
|
Fsx3.at(id).validate();
|
||||||
|
auto det = Fsx3.at(id);
|
||||||
|
bool no_charge_sharing_strict = det.valid_front_chans.size()==1 && det.valid_back_chans.size()==1;
|
||||||
|
if(det.valid) {
|
||||||
|
//std::cout << det.frontEL << " " << det.frontEL*sx3RightGain[id][det.stripF] << std::endl;
|
||||||
|
plotter->Fill2D("be_vs_x_sx3_id_"+std::to_string(id)+"_f"+std::to_string(det.stripF)+"_b"+std::to_string(det.stripB),200,-1,1,800,0,8192,
|
||||||
|
det.frontX,det.backE,"evsx");
|
||||||
|
//std::cout << sx3BackGain[id][det.stripF][det.stripB] << " " << sx3FrontGain[id][det.stripF] << std::endl;
|
||||||
|
plotter->Fill2D("matched_be_vs_x_sx3_id_"+std::to_string(id)+"_f"+std::to_string(det.stripF),200,-30,30,800,0,8192,
|
||||||
|
det.frontX*sx3FrontGain[id][det.stripF]+sx3FrontOffset[id][det.stripF],det.backE*sx3BackGain[id][det.stripF][det.stripB],"evsx_matched");
|
||||||
|
//plotter->Fill2D("fe_vs_x_sx3_id_"+std::to_string(id)+"_f"+std::to_string(det.stripF)+"_"+std::to_string(det.stripB),200,-1,1,800,0,4096,det.frontX,det.backE,"evsx");
|
||||||
|
plotter->Fill2D("l_vs_r_sx3_id_"+std::to_string(id)+"_f"+std::to_string(det.stripF),800,0,4096,800,0,4096,det.frontEL,det.frontER,"l_vs_r");
|
||||||
|
}
|
||||||
|
if(det.valid && (id ==9 || id==7 || id == 1 || id==3) && det.stripF!=DEFAULT_NULL && det.stripB!=DEFAULT_NULL) {
|
||||||
|
double z = det.frontX*sx3FrontGain[id][det.stripF]+sx3FrontOffset[id][det.stripF];
|
||||||
|
double backE = det.backE*sx3BackGain[id][det.stripF][det.stripB];
|
||||||
|
Event sx3ev(TVector3(0,0,z),backE,-1,det.ts,-1,det.stripB+4*id,det.stripF+4*id);
|
||||||
|
sx3Events.push_back(sx3ev);
|
||||||
|
}
|
||||||
|
if(!det.valid && det.valid_back_chans.size()) {
|
||||||
|
for(auto bch : det.valid_back_chans) {
|
||||||
|
plotter->Fill1D("good_backs_bad_fronts_id"+std::to_string(id)+"_b"+std::to_string(bch),800,0,4096,det.back[bch].at(0),"good_backs_no_front");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(!det.valid && det.unmatched_front_chans.size()) {
|
||||||
|
for(auto bch : det.valid_back_chans)
|
||||||
|
for(auto fch : det.unmatched_front_chans) {
|
||||||
|
if(det.frontR[fch].size() != 0) {
|
||||||
|
double trial_left = det.back[bch].at(0) - det.frontR[fch].at(0);
|
||||||
|
double frontR = det.frontR[fch].at(0);
|
||||||
|
double backE = det.back[bch].at(0);
|
||||||
|
double frontX = (trial_left - frontR)/(trial_left + frontR);
|
||||||
|
plotter->Fill2D("bad_fronts_id"+std::to_string(id)+"_fR"+std::to_string(fch)+"_b"+std::to_string(bch),800,0,4096,800,0,4096,det.frontR[fch].at(0),det.back[bch].at(0),"bad_fronts_vb");
|
||||||
|
plotter->Fill2D("be_vs_x_sx3_id_"+std::to_string(id)+"_f"+std::to_string(fch)+"R_b"+std::to_string(bch),200,-1,1,800,0,8192,
|
||||||
|
frontX,backE,"evsx_bad_front");
|
||||||
|
|
||||||
|
//double backE = det.back[bch].at(0)*sx3BackGain[id][fch][bch];
|
||||||
|
//double frontE = det.frontR[fch]
|
||||||
|
}
|
||||||
|
if(det.frontL[fch].size() != 0) {
|
||||||
|
double trial_right = det.back[bch].at(0) - det.frontL[fch].at(0);
|
||||||
|
double frontL = det.frontL[fch].at(0);
|
||||||
|
double backE = det.back[bch].at(0);
|
||||||
|
double frontX = (frontL - trial_right)/(frontL + trial_right);
|
||||||
|
plotter->Fill2D("bad_fronts_id"+std::to_string(id)+"_fL"+std::to_string(fch)+"_b"+std::to_string(bch),800,0,4096,800,0,4096,det.frontL[fch].at(0),det.back[bch].at(0),"bad_fronts_vb");
|
||||||
|
plotter->Fill2D("be_vs_x_sx3_id_"+std::to_string(id)+"_f"+std::to_string(fch)+"L_b"+std::to_string(bch),200,-1,1,800,0,8192,
|
||||||
|
frontX,backE,"evsx_bad_front");
|
||||||
|
}
|
||||||
|
}//end for
|
||||||
|
|
||||||
|
}//end if(!det.valid)
|
||||||
|
}//end for id
|
||||||
|
}//end sx3.multi>1
|
||||||
|
return kTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MakeVertexSX3::Terminate()
|
||||||
|
{
|
||||||
|
plotter->FlushToDisk(10);
|
||||||
|
}
|
||||||
1114
MakeVertexSX3.C.backup
Normal file
1114
MakeVertexSX3.C.backup
Normal file
File diff suppressed because it is too large
Load Diff
132
MakeVertexSX3.h
Normal file
132
MakeVertexSX3.h
Normal file
|
|
@ -0,0 +1,132 @@
|
||||||
|
#ifndef MakeVertexSX3_h
|
||||||
|
#define MakeVertexSX3_h
|
||||||
|
|
||||||
|
#include <TROOT.h>
|
||||||
|
#include <TChain.h>
|
||||||
|
#include <TApplication.h>
|
||||||
|
#include <TFile.h>
|
||||||
|
#include <TSelector.h>
|
||||||
|
#include <iomanip>
|
||||||
|
#include <vector> // Required for vectors
|
||||||
|
#include <utility> // Required for std::pair
|
||||||
|
|
||||||
|
#include "Armory/ClassDet.h"
|
||||||
|
#include "Armory/ClassPW.h" // YOU ADDED THIS (Correct! Defines Coord)
|
||||||
|
|
||||||
|
class MakeVertexSX3 : public TSelector {
|
||||||
|
public :
|
||||||
|
TTree *fChain; //!pointer to the analyzed TTree or TChain
|
||||||
|
|
||||||
|
// Declaration of leaf types
|
||||||
|
Det sx3;
|
||||||
|
Det qqq;
|
||||||
|
Det pc ;
|
||||||
|
Det misc;
|
||||||
|
|
||||||
|
ULong64_t evID;
|
||||||
|
UInt_t run;
|
||||||
|
|
||||||
|
// List of branches
|
||||||
|
TBranch *b_eventID; //!
|
||||||
|
TBranch *b_run; //!
|
||||||
|
TBranch *b_sx3Multi; //!
|
||||||
|
TBranch *b_sx3ID; //!
|
||||||
|
TBranch *b_sx3Ch; //!
|
||||||
|
TBranch *b_sx3E; //!
|
||||||
|
TBranch *b_sx3T; //!
|
||||||
|
TBranch *b_qqqMulti; //!
|
||||||
|
TBranch *b_qqqID; //!
|
||||||
|
TBranch *b_qqqCh; //!
|
||||||
|
TBranch *b_qqqE; //!
|
||||||
|
TBranch *b_qqqT; //!
|
||||||
|
TBranch *b_pcMulti; //!
|
||||||
|
TBranch *b_pcID; //!
|
||||||
|
TBranch *b_pcCh; //!
|
||||||
|
TBranch *b_pcE; //!
|
||||||
|
TBranch *b_pcT; //!
|
||||||
|
TBranch *b_miscMulti; //!
|
||||||
|
TBranch *b_miscID; //!
|
||||||
|
TBranch *b_miscCh; //!
|
||||||
|
TBranch *b_miscE; //!
|
||||||
|
TBranch *b_miscT; //!
|
||||||
|
TBranch *b_miscTf; //!
|
||||||
|
|
||||||
|
// 1. Geometry Cache
|
||||||
|
Coord Crossover[24][24][2];
|
||||||
|
|
||||||
|
// 2. Persistent Vectors (REQUIRED for the optimized .cxx to work)
|
||||||
|
std::vector<std::pair<int, double>> anodeHits;
|
||||||
|
std::vector<std::pair<int, double>> cathodeHits;
|
||||||
|
std::vector<std::pair<int, double>> corrcatMax;
|
||||||
|
std::vector<std::pair<int, double>> corranoMax;
|
||||||
|
std::vector<double> cathodeTimes;
|
||||||
|
std::vector<double> anodeTimes;
|
||||||
|
|
||||||
|
MakeVertexSX3(TTree * /*tree*/ =0) : fChain(0) { }
|
||||||
|
virtual ~MakeVertexSX3() { }
|
||||||
|
virtual Int_t Version() const { return 2; }
|
||||||
|
virtual void Begin(TTree *tree);
|
||||||
|
virtual void SlaveBegin(TTree *tree);
|
||||||
|
virtual void Init(TTree *tree);
|
||||||
|
virtual Bool_t Notify();
|
||||||
|
virtual Bool_t Process(Long64_t entry);
|
||||||
|
virtual Int_t GetEntry(Long64_t entry, Int_t getall = 0) { return fChain ? fChain->GetTree()->GetEntry(entry, getall) : 0; }
|
||||||
|
virtual void SetOption(const char *option) { fOption = option; }
|
||||||
|
virtual void SetObject(TObject *obj) { fObject = obj; }
|
||||||
|
virtual void SetInputList(TList *input) { fInput = input; }
|
||||||
|
virtual TList *GetOutputList() const { return fOutput; }
|
||||||
|
virtual void SlaveTerminate();
|
||||||
|
virtual void Terminate();
|
||||||
|
|
||||||
|
ClassDef(MakeVertexSX3,0);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef MakeVertexSX3_cxx
|
||||||
|
void MakeVertexSX3::Init(TTree *tree){
|
||||||
|
|
||||||
|
if (!tree) return;
|
||||||
|
fChain = tree;
|
||||||
|
fChain->SetMakeClass(1);
|
||||||
|
|
||||||
|
fChain->SetBranchAddress("evID", &evID, &b_eventID);
|
||||||
|
fChain->SetBranchAddress("run", &run, &b_run);
|
||||||
|
|
||||||
|
sx3.SetDetDimension(24,12);
|
||||||
|
qqq.SetDetDimension(4,32);
|
||||||
|
pc.SetDetDimension(2,24);
|
||||||
|
|
||||||
|
fChain->SetBranchAddress("sx3Multi", &sx3.multi, &b_sx3Multi);
|
||||||
|
fChain->SetBranchAddress("sx3ID", &sx3.id, &b_sx3ID);
|
||||||
|
fChain->SetBranchAddress("sx3Ch", &sx3.ch, &b_sx3Ch);
|
||||||
|
fChain->SetBranchAddress("sx3E", &sx3.e, &b_sx3E);
|
||||||
|
fChain->SetBranchAddress("sx3T", &sx3.t, &b_sx3T);
|
||||||
|
fChain->SetBranchAddress("qqqMulti", &qqq.multi, &b_qqqMulti);
|
||||||
|
fChain->SetBranchAddress("qqqID", &qqq.id, &b_qqqID);
|
||||||
|
fChain->SetBranchAddress("qqqCh", &qqq.ch, &b_qqqCh);
|
||||||
|
fChain->SetBranchAddress("qqqE", &qqq.e, &b_qqqE);
|
||||||
|
fChain->SetBranchAddress("qqqT", &qqq.t, &b_qqqT);
|
||||||
|
fChain->SetBranchAddress("pcMulti", &pc.multi, &b_pcMulti);
|
||||||
|
fChain->SetBranchAddress("pcID", &pc.id, &b_pcID);
|
||||||
|
fChain->SetBranchAddress("pcCh", &pc.ch, &b_pcCh);
|
||||||
|
fChain->SetBranchAddress("pcE", &pc.e, &b_pcE);
|
||||||
|
fChain->SetBranchAddress("pcT", &pc.t, &b_pcT);
|
||||||
|
fChain->SetBranchAddress("miscMulti", &misc.multi, &b_miscMulti);
|
||||||
|
fChain->SetBranchAddress("miscID", &misc.id, &b_miscID);
|
||||||
|
fChain->SetBranchAddress("miscCh", &misc.ch, &b_miscCh);
|
||||||
|
fChain->SetBranchAddress("miscE", &misc.e, &b_miscE);
|
||||||
|
fChain->SetBranchAddress("miscT", &misc.t, &b_miscT);
|
||||||
|
}
|
||||||
|
|
||||||
|
Bool_t MakeVertexSX3::Notify(){
|
||||||
|
return kTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MakeVertexSX3::SlaveBegin(TTree * /*tree*/){
|
||||||
|
// TString option = GetOption();
|
||||||
|
}
|
||||||
|
|
||||||
|
void MakeVertexSX3::SlaveTerminate(){
|
||||||
|
}
|
||||||
|
#endif // #ifdef MakeVertexSX3_cxx
|
||||||
133
MatchAndPlotCentroids.C
Normal file
133
MatchAndPlotCentroids.C
Normal file
|
|
@ -0,0 +1,133 @@
|
||||||
|
#include <fstream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
|
#include <iostream>
|
||||||
|
#include <TGraph.h>
|
||||||
|
#include <TF1.h>
|
||||||
|
#include <TCanvas.h>
|
||||||
|
#include <TH1.h>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void MatchAndPlotCentroids() {
|
||||||
|
// Open the centroid data file
|
||||||
|
std::ifstream inputFile("centroids.txt");
|
||||||
|
if (!inputFile.is_open()) {
|
||||||
|
std::cerr << "Error: Could not open Centroids.txt" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Data structure to store centroids by histogram and peak number
|
||||||
|
std::map<int, std::map<int, double>> centroidData;
|
||||||
|
|
||||||
|
// Read data from the file
|
||||||
|
std::string line;
|
||||||
|
while (std::getline(inputFile, line)) {
|
||||||
|
std::istringstream iss(line);
|
||||||
|
int histogramIndex, peakNumber;
|
||||||
|
double centroid;
|
||||||
|
if (iss >> histogramIndex >> peakNumber >> centroid) {
|
||||||
|
centroidData[histogramIndex][peakNumber] = centroid;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inputFile.close();
|
||||||
|
|
||||||
|
// Ensure histogram 24 exists and has data
|
||||||
|
if (centroidData.find(1) == centroidData.end()) {
|
||||||
|
std::cerr << "Error: Histogram 0 not found in the data!" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reference centroids from histogram 24
|
||||||
|
const auto& referenceCentroids = centroidData[1];
|
||||||
|
std::ofstream outputFile("slope_intercept_results.txt");
|
||||||
|
if (!outputFile.is_open()) {
|
||||||
|
std::cerr << "Error: Could not open the output file for writing!" << std::endl;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
outputFile << "Histogram Number\tSlope\tIntercept\n";
|
||||||
|
// Loop through histograms 25 to 47
|
||||||
|
for (int targetHist = 0; targetHist <= 23; targetHist++) {
|
||||||
|
// Ensure the target histogram exists and matches in peak numbers
|
||||||
|
if (centroidData.find(targetHist) == centroidData.end() || centroidData[targetHist].size() != referenceCentroids.size()) {
|
||||||
|
//4th cnetroid data point for 19 was generated using the 3 datqa points for the slope of wires 0 and 19
|
||||||
|
std::cout << "Skipping Histogram " << targetHist << " due to mismatched or missing data." << std::endl;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare x and y values for TGraph
|
||||||
|
std::vector<double> xValues, yValues;
|
||||||
|
for (const auto& [peakNumber, refCentroid] : referenceCentroids) {
|
||||||
|
if (centroidData[targetHist].find(peakNumber) != centroidData[targetHist].end()) {
|
||||||
|
yValues.push_back(refCentroid);
|
||||||
|
xValues.push_back(centroidData[targetHist][peakNumber]);
|
||||||
|
} else {
|
||||||
|
std::cerr << "Warning: Peak " << peakNumber << " missing in histogram " << targetHist << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (xValues.size() < 3) {
|
||||||
|
std::cout << "Skipping Histogram " << targetHist << " as it has less than 3 matching centroids." << std::endl;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a TGraph
|
||||||
|
TCanvas *c1 = new TCanvas(Form("c_centroid_1_vs_%d", targetHist), Form("Centroid 1 vs %d", targetHist), 800, 600);
|
||||||
|
TGraph *graph = new TGraph(xValues.size(), &xValues[0], &yValues[0]);
|
||||||
|
graph->SetTitle(Form("Centroid of Histogram %d vs 1", targetHist));
|
||||||
|
graph->GetYaxis()->SetTitle("Centroid of Histogram 1");
|
||||||
|
graph->GetXaxis()->SetTitle(Form("Centroid of Histogram %d", targetHist));
|
||||||
|
graph->SetMarkerStyle(20); // Full circle marker
|
||||||
|
graph->SetMarkerSize(1.0);
|
||||||
|
graph->SetMarkerColor(kBlue);
|
||||||
|
// Draw the graph
|
||||||
|
graph->Draw("AP");
|
||||||
|
double minX = *std::min_element(xValues.begin(), xValues.end());
|
||||||
|
double maxX = *std::max_element(xValues.begin(), xValues.end());
|
||||||
|
// Fit the data with a linear function
|
||||||
|
TF1 *fitLine = new TF1("fitLine", "pol1", minX, maxX); // Adjust range as needed
|
||||||
|
fitLine->SetLineColor(kRed); // Set the line color to distinguish it
|
||||||
|
fitLine->SetLineWidth(2); // Thicker line for visibility
|
||||||
|
graph->Fit(fitLine, "M");
|
||||||
|
fitLine->Draw("same");
|
||||||
|
fitLine->SetParLimits(0, -10, 10); // Limit intercept between -10 and 10
|
||||||
|
fitLine->SetParLimits(1, 0, 2);
|
||||||
|
// Extract slope and intercept
|
||||||
|
double slope = fitLine->GetParameter(1);
|
||||||
|
double intercept = fitLine->GetParameter(0);
|
||||||
|
outputFile << targetHist << "\t" << slope << "\t" << intercept << "\n";
|
||||||
|
std::cout << "Histogram 24 vs " << targetHist << ": Slope = " << slope << ", Intercept = " << intercept << std::endl;
|
||||||
|
std::vector<double> residuals;
|
||||||
|
for (size_t i = 0; i < xValues.size(); ++i) {
|
||||||
|
double fittedY = fitLine->Eval(xValues[i]); // Evaluate fitted function at x
|
||||||
|
double residual = yValues[i] - fittedY; // Residual = observed - fitted
|
||||||
|
residuals.push_back(residual);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a graph for the residuals
|
||||||
|
/*TGraph *residualGraph = new TGraph(residuals.size(), &xValues[0], &residuals[0]);
|
||||||
|
residualGraph->SetTitle(Form("Residuals for Histogram 24 vs %d", targetHist));
|
||||||
|
residualGraph->GetYaxis()->SetTitle("Residuals");
|
||||||
|
residualGraph->GetXaxis()->SetTitle(Form("Centroid of Histogram %d", targetHist));
|
||||||
|
residualGraph->SetMarkerStyle(20);
|
||||||
|
residualGraph->SetMarkerSize(1.0);
|
||||||
|
residualGraph->SetMarkerColor(kGreen);
|
||||||
|
|
||||||
|
// Draw the residuals plot below the original plot (can be on a new canvas if preferred)
|
||||||
|
TCanvas *c2 = new TCanvas(Form("c_residuals_24_vs_%d", targetHist), Form("Residuals for Centroid 24 vs %d", targetHist), 800, 400);
|
||||||
|
residualGraph->Draw("AP");*/
|
||||||
|
c1->Update();
|
||||||
|
//c2->Update();
|
||||||
|
std::cout << "Press Enter to continue..." << std::endl;
|
||||||
|
|
||||||
|
//std::cin.get();
|
||||||
|
c1->WaitPrimitive();
|
||||||
|
//c2->WaitPrimitive();
|
||||||
|
//std::cin.get();
|
||||||
|
//std::cin.get();
|
||||||
|
}
|
||||||
|
outputFile.close();
|
||||||
|
std::cout << "Results written to slope_intercept_results.txt" << std::endl;
|
||||||
|
}
|
||||||
454
PCGainMatch.C
Normal file
454
PCGainMatch.C
Normal file
|
|
@ -0,0 +1,454 @@
|
||||||
|
#define PCGainMatch_cxx
|
||||||
|
|
||||||
|
#include "PCGainMatch.h"
|
||||||
|
#include <TH2.h>
|
||||||
|
#include <TStyle.h>
|
||||||
|
#include <TCanvas.h>
|
||||||
|
#include <TMath.h>
|
||||||
|
#include <TCutG.h>
|
||||||
|
#include <utility>
|
||||||
|
#include <algorithm>
|
||||||
|
#include "Armory/ClassSX3.h"
|
||||||
|
#include "Armory/ClassPW.h"
|
||||||
|
|
||||||
|
#include "TVector3.h"
|
||||||
|
|
||||||
|
TH2F * hsx3IndexVE;
|
||||||
|
TH2F * hqqqIndexVE;
|
||||||
|
TH2F * hpcIndexVE;
|
||||||
|
|
||||||
|
TH2F * hsx3Coin;
|
||||||
|
TH2F * hqqqCoin;
|
||||||
|
TH2F * hpcCoin;
|
||||||
|
|
||||||
|
TH2F * hqqqPolar;
|
||||||
|
TH2F * hsx3VpcIndex;
|
||||||
|
TH2F * hqqqVpcIndex;
|
||||||
|
TH2F * hqqqVpcE;
|
||||||
|
TH2F * hsx3VpcE;
|
||||||
|
TH2F * hanVScatsum;
|
||||||
|
TH2F * hanVScatsum_a[24];
|
||||||
|
TH2F * hanVScatsum_hcut;
|
||||||
|
TH2F * hanVScatsum_lcut;
|
||||||
|
TH2F * hAnodeHits;
|
||||||
|
TH1F * hAnodeMultiplicity;
|
||||||
|
|
||||||
|
|
||||||
|
int padID = 0;
|
||||||
|
|
||||||
|
SX3 sx3_contr;
|
||||||
|
PW pw_contr;
|
||||||
|
TVector3 hitPos;
|
||||||
|
bool HitNonZero;
|
||||||
|
|
||||||
|
TH1F * hZProj;
|
||||||
|
TCutG *AnCatSum_high;
|
||||||
|
TCutG *AnCatSum_low;
|
||||||
|
TCutG *PCCoinc_cut1;
|
||||||
|
TCutG *PCCoinc_cut2;
|
||||||
|
bool inCuth;
|
||||||
|
bool inCutl;
|
||||||
|
bool inPCCut;
|
||||||
|
|
||||||
|
void PCGainMatch::Begin(TTree * /*tree*/){
|
||||||
|
TString option = GetOption();
|
||||||
|
|
||||||
|
hsx3IndexVE = new TH2F("hsx3IndexVE", "SX3 index vs Energy; sx3 index ; Energy", 24*12, 0, 24*12, 400, 0, 5000); hsx3IndexVE->SetNdivisions( -612, "x");
|
||||||
|
hqqqIndexVE = new TH2F("hqqqIndexVE", "QQQ index vs Energy; QQQ index ; Energy", 4*2*16, 0, 4*2*16, 400, 0, 5000); hqqqIndexVE->SetNdivisions( -1204, "x");
|
||||||
|
hpcIndexVE = new TH2F("hpcIndexVE", "PC index vs Energy; PC index ; Energy", 2*24, 0, 2*24, 800, 0, 16000); hpcIndexVE->SetNdivisions( -1204, "x");
|
||||||
|
|
||||||
|
|
||||||
|
hsx3Coin = new TH2F("hsx3Coin", "SX3 Coincident", 24*12, 0, 24*12, 24*12, 0, 24*12);
|
||||||
|
hqqqCoin = new TH2F("hqqqCoin", "QQQ Coincident", 4*2*16, 0, 4*2*16, 4*2*16, 0, 4*2*16);
|
||||||
|
hpcCoin = new TH2F("hpcCoin", "PC Coincident", 2*24, 0, 2*24, 2*24, 0, 2*24);
|
||||||
|
|
||||||
|
hqqqPolar = new TH2F("hqqqPolar", "QQQ Polar ID", 16*4, -TMath::Pi(), TMath::Pi(),16, 10, 50);
|
||||||
|
|
||||||
|
hsx3VpcIndex = new TH2F("hsx3Vpcindex", "sx3 vs pc; sx3 index; pc index", 24*12, 0, 24*12, 48, 0, 48);
|
||||||
|
hsx3VpcIndex->SetNdivisions( -612, "x");
|
||||||
|
hsx3VpcIndex->SetNdivisions( -12, "y");
|
||||||
|
hqqqVpcIndex = new TH2F("hqqqVpcindex", "qqq vs pc; qqq index; pc index", 4*2*16, 0, 4*2*16, 48, 0, 48);
|
||||||
|
hqqqVpcIndex->SetNdivisions( -612, "x");
|
||||||
|
hqqqVpcIndex->SetNdivisions( -12, "y");
|
||||||
|
|
||||||
|
hqqqVpcE = new TH2F("hqqqVpcEnergy", "qqq vs pc; qqq energy; pc energy", 400, 0, 5000, 400, 0, 5000);
|
||||||
|
hqqqVpcE->SetNdivisions( -612, "x");
|
||||||
|
hqqqVpcE->SetNdivisions( -12, "y");
|
||||||
|
|
||||||
|
hsx3VpcE = new TH2F("hsx3VpcEnergy", "sx3 vs pc; sx3 energy; pc energy", 400, 0, 5000, 400, 0, 5000);
|
||||||
|
hsx3VpcE->SetNdivisions( -612, "x");
|
||||||
|
hsx3VpcE->SetNdivisions( -12, "y");
|
||||||
|
|
||||||
|
hZProj = new TH1F("hZProj", "Nos of anodes", 20, 0, 19);
|
||||||
|
hAnodeHits = new TH2F("hAnodeHits", "Anode vs Anode Energy, Anode ID; Anode E", 24,0 , 23, 400, 0 , 20000);
|
||||||
|
hAnodeMultiplicity = new TH1F("hAnodeMultiplicity", "Number of Anodes/Event", 40, 0, 40);
|
||||||
|
hanVScatsum = new TH2F("hanVScatsum", "Anode vs Cathode Sum; Anode E; Cathode E", 400,0 , 10000, 800, 0 , 16000);
|
||||||
|
for (int i = 0; i < 24; i++) {
|
||||||
|
TString histName = Form("hAnodeVsCathode_%d", i);
|
||||||
|
TString histTitle = Form("Anode %d vs Cathode Sum; Anode E; Cathode Sum E", i);
|
||||||
|
hanVScatsum_a[i] = new TH2F(histName, histTitle, 400, 0, 10000, 400, 0, 16000);
|
||||||
|
}
|
||||||
|
hanVScatsum_lcut = new TH2F("hanVScatsum_LCUT", "Anode vs Cathode Sum; Anode E; Cathode E", 400,0 , 16000, 400, 0 , 16000);
|
||||||
|
hanVScatsum_hcut = new TH2F("hanVScatsum_HCUT", "Anode vs Cathode Sum; Anode E; Cathode E", 400,0 , 16000, 400, 0 , 16000);
|
||||||
|
|
||||||
|
sx3_contr.ConstructGeo();
|
||||||
|
pw_contr.ConstructGeo();
|
||||||
|
// TFile *f1 = new TFile("AnCatSum_high.root");
|
||||||
|
// TFile *f2 = new TFile("AnCatSum_low.root");
|
||||||
|
// TFile *f3 = new TFile("PCCoinc_cut1.root");
|
||||||
|
// TFile *f4 = new TFile("PCCoinc_cut2.root");
|
||||||
|
// AnCatSum_high= (TCutG*)f1->Get("AnCatSum_high");
|
||||||
|
// AnCatSum_low= (TCutG*)f2->Get("AnCatSum_low");
|
||||||
|
// PCCoinc_cut1= (TCutG*)f3->Get("PCCoinc_cut1");
|
||||||
|
// PCCoinc_cut2= (TCutG*)f4->Get("PCCoinc_cut2");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Bool_t PCGainMatch::Process(Long64_t entry){
|
||||||
|
// if (entry % 1000000 == 0) {
|
||||||
|
// std::cout << "Processing entry: " << entry << std::endl;
|
||||||
|
// }
|
||||||
|
// if ( entry > 100 ) return kTRUE;
|
||||||
|
|
||||||
|
hitPos.Clear();
|
||||||
|
HitNonZero = false;
|
||||||
|
|
||||||
|
// if( entry > 1) return kTRUE;
|
||||||
|
// printf("################### ev : %llu \n", entry);
|
||||||
|
|
||||||
|
b_sx3Multi->GetEntry(entry);
|
||||||
|
b_sx3ID->GetEntry(entry);
|
||||||
|
b_sx3Ch->GetEntry(entry);
|
||||||
|
b_sx3E->GetEntry(entry);
|
||||||
|
b_sx3T->GetEntry(entry);
|
||||||
|
b_qqqMulti->GetEntry(entry);
|
||||||
|
b_qqqID->GetEntry(entry);
|
||||||
|
b_qqqCh->GetEntry(entry);
|
||||||
|
b_qqqE->GetEntry(entry);
|
||||||
|
b_qqqT->GetEntry(entry);
|
||||||
|
b_pcMulti->GetEntry(entry);
|
||||||
|
b_pcID->GetEntry(entry);
|
||||||
|
b_pcCh->GetEntry(entry);
|
||||||
|
b_pcE->GetEntry(entry);
|
||||||
|
b_pcT->GetEntry(entry);
|
||||||
|
|
||||||
|
sx3.CalIndex();
|
||||||
|
qqq.CalIndex();
|
||||||
|
pc.CalIndex();
|
||||||
|
|
||||||
|
// sx3.Print();
|
||||||
|
|
||||||
|
//########################################################### Raw data
|
||||||
|
|
||||||
|
// //======================= PC
|
||||||
|
|
||||||
|
std::vector<std::pair<int, double>> anodeHits={};
|
||||||
|
std::vector<std::pair<int, double>> cathodeHits={};
|
||||||
|
int aID = 0;
|
||||||
|
int cID = 0;
|
||||||
|
float aE = 0;
|
||||||
|
float cE = 0;
|
||||||
|
|
||||||
|
// Define the excluded SX3 and QQQ channels
|
||||||
|
// std::unordered_set<int> excludeSX3 = {34, 35, 36, 37, 61, 62, 67, 73, 74, 75, 76, 77, 78, 79, 80, 93, 97, 100, 103, 108, 109, 110, 111, 112};
|
||||||
|
// std::unordered_set<int> excludeQQQ = {0, 17, 109, 110, 111, 112, 113, 119, 127, 128};
|
||||||
|
// inCuth=false;
|
||||||
|
// inCutl=false;
|
||||||
|
// inPCCut=false;
|
||||||
|
for( int i = 0; i < pc.multi; i ++){
|
||||||
|
|
||||||
|
if(pc.e[i]>50 && pc.multi<7){
|
||||||
|
|
||||||
|
float aESum = 0;
|
||||||
|
float cESum = 0;
|
||||||
|
if (pc.index[i] < 24 ) {
|
||||||
|
anodeHits.push_back(std::pair<int, double>(pc.index[i], pc.e[i]));
|
||||||
|
} else if (pc.index[i] >= 24) {
|
||||||
|
cathodeHits.push_back(std::pair<int, double>(pc.index[i], pc.e[i]));
|
||||||
|
}
|
||||||
|
|
||||||
|
for(int j=i+1;j<pc.multi;j++){
|
||||||
|
// if(PCCoinc_cut1->IsInside(pc.index[i], pc.index[j]) || PCCoinc_cut2->IsInside(pc.index[i], pc.index[j])){
|
||||||
|
// // hpcCoin->Fill(pc.index[i], pc.index[j]);
|
||||||
|
// inPCCut = true;
|
||||||
|
// }
|
||||||
|
hpcCoin->Fill(pc.index[i], pc.index[j]);
|
||||||
|
}
|
||||||
|
if (anodeHits.size()==1 && cathodeHits.size() >= 1) {
|
||||||
|
|
||||||
|
for (const auto& anode : anodeHits) {
|
||||||
|
// for(int l=0; l<sx3.multi; l++){
|
||||||
|
// if (sx3.index[l]==80){
|
||||||
|
|
||||||
|
aID = anode.first;
|
||||||
|
aE = anode.second;
|
||||||
|
aESum += aE;
|
||||||
|
// printf("aID : %d, aE : %f\n", aID, aE);
|
||||||
|
}
|
||||||
|
|
||||||
|
// printf("aID : %d, aE : %f, cE : %f\n", aID, aE, cE);
|
||||||
|
for (const auto& cathode : cathodeHits) {
|
||||||
|
cID = cathode.first;
|
||||||
|
cE = cathode.second;
|
||||||
|
// if(cE>cEMax){
|
||||||
|
// cEMax = cE;
|
||||||
|
// cIDMax = cID;
|
||||||
|
// }
|
||||||
|
// if(cE>cEnextMax && cE<cEMax){
|
||||||
|
// cEnextMax = cE;
|
||||||
|
// cIDnextMax = cID;
|
||||||
|
// }
|
||||||
|
|
||||||
|
cESum += cE;
|
||||||
|
}
|
||||||
|
// }
|
||||||
|
|
||||||
|
// inCuth = false;
|
||||||
|
// inCutl = false;
|
||||||
|
// inPCCut = false;
|
||||||
|
// for(int j=i+1;j<pc.multi;j++){
|
||||||
|
// if(PCCoinc_cut1->IsInside(pc.index[i], pc.index[j]) || PCCoinc_cut2->IsInside(pc.index[i], pc.index[j])){
|
||||||
|
// // hpcCoin->Fill(pc.index[i], pc.index[j]);
|
||||||
|
// inPCCut = true;
|
||||||
|
// }
|
||||||
|
// hpcCoin->Fill(pc.index[i], pc.index[j]);
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Check if the accumulated energies are within the defined ranges
|
||||||
|
// if (AnCatSum_high && AnCatSum_high->IsInside(aESum, cESum)) {
|
||||||
|
// inCuth = true;
|
||||||
|
// }
|
||||||
|
// if (AnCatSum_low && AnCatSum_low->IsInside(aESum, cESum)) {
|
||||||
|
// inCutl = true;
|
||||||
|
// }
|
||||||
|
|
||||||
|
// Fill histograms based on the cut conditions
|
||||||
|
// if (inCuth && inPCCut) {
|
||||||
|
// hanVScatsum_hcut->Fill(aESum, cESum);
|
||||||
|
// }
|
||||||
|
// if (inCutl && inPCCut) {
|
||||||
|
// hanVScatsum_lcut->Fill(aESum, cESum);
|
||||||
|
// }
|
||||||
|
// for(auto anode : anodeHits){
|
||||||
|
|
||||||
|
// float aE = anode.second;
|
||||||
|
// aESum += aE;
|
||||||
|
// if(inPCCut){
|
||||||
|
hanVScatsum->Fill(aESum, cESum);
|
||||||
|
// }
|
||||||
|
if (aID < 24 && aE > 50) {
|
||||||
|
hanVScatsum_a[aID]->Fill(aE, cESum);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// }
|
||||||
|
// Fill histograms for the `pc` data
|
||||||
|
hpcIndexVE->Fill(pc.index[i], pc.e[i]);
|
||||||
|
// if(inPCCut){
|
||||||
|
hAnodeMultiplicity->Fill(anodeHits.size());
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// //======================= SX3
|
||||||
|
|
||||||
|
std::vector<std::pair<int, int>> ID; // first = id, 2nd = index
|
||||||
|
for( int i = 0; i < sx3.multi; i ++){
|
||||||
|
if(sx3.e[i]>50){
|
||||||
|
ID.push_back(std::pair<int, int>(sx3.id[i], i));
|
||||||
|
hsx3IndexVE->Fill( sx3.index[i], sx3.e[i] );
|
||||||
|
|
||||||
|
for( int j = i+1; j < sx3.multi; j++){
|
||||||
|
hsx3Coin->Fill( sx3.index[i], sx3.index[j]);
|
||||||
|
}
|
||||||
|
|
||||||
|
for( int j = 0; j < pc.multi; j++){
|
||||||
|
hsx3VpcIndex->Fill( sx3.index[i], pc.index[j] );
|
||||||
|
// if( sx3.ch[index] > 8 ){
|
||||||
|
// hsx3VpcE->Fill( sx3.e[i], pc.e[j] );
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if( ID.size() > 0 ){
|
||||||
|
std::sort(ID.begin(), ID.end(), [](const std::pair<int, int> & a, const std::pair<int, int> & b) {
|
||||||
|
return a.first < b.first;
|
||||||
|
} );
|
||||||
|
// printf("##############################\n");
|
||||||
|
// for( size_t i = 0; i < ID.size(); i++) printf("%zu | %d %d \n", i, ID[i].first, ID[i].second );
|
||||||
|
|
||||||
|
std::vector<std::pair<int, int>> sx3ID;
|
||||||
|
sx3ID.push_back(ID[0]);
|
||||||
|
bool found = false;
|
||||||
|
for( size_t i = 1; i < ID.size(); i++){
|
||||||
|
if( ID[i].first == sx3ID.back().first) {
|
||||||
|
sx3ID.push_back(ID[i]);
|
||||||
|
if( sx3ID.size() >= 3) {
|
||||||
|
found = true;
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
if( !found ){
|
||||||
|
sx3ID.clear();
|
||||||
|
sx3ID.push_back(ID[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// printf("---------- sx3ID Multi : %zu \n", sx3ID.size());
|
||||||
|
|
||||||
|
if( found ){
|
||||||
|
int sx3ChUp, sx3ChDn, sx3ChBk;
|
||||||
|
float sx3EUp, sx3EDn;
|
||||||
|
// printf("------ sx3 ID : %d, multi: %zu\n", sx3ID[0].first, sx3ID.size());
|
||||||
|
for( size_t i = 0; i < sx3ID.size(); i++ ){
|
||||||
|
int index = sx3ID[i].second;
|
||||||
|
// printf(" %zu | index %d | ch : %d, energy : %d \n", i, index, sx3.ch[index], sx3.e[index]);
|
||||||
|
|
||||||
|
|
||||||
|
if( sx3.ch[index] < 8 ){
|
||||||
|
if( sx3.ch[index] % 2 == 0) {
|
||||||
|
sx3ChDn = sx3.ch[index];
|
||||||
|
sx3EDn = sx3.e[index];
|
||||||
|
}else{
|
||||||
|
sx3ChUp = sx3.ch[index];
|
||||||
|
sx3EUp = sx3.e[index];
|
||||||
|
}
|
||||||
|
}else{
|
||||||
|
sx3ChBk = sx3.ch[index];
|
||||||
|
}
|
||||||
|
for( int j = 0; j < pc.multi; j++){
|
||||||
|
|
||||||
|
// hsx3VpcIndex->Fill( sx3.index[i], pc.index[j] );
|
||||||
|
if( sx3.ch[index] > 8 && pc.index[j]<24 && pc.e[j]>50 ){
|
||||||
|
hsx3VpcE->Fill( sx3.e[i], pc.e[j] );
|
||||||
|
// hpcIndexVE->Fill( pc.index[i], pc.e[i] );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sx3_contr.CalSX3Pos(sx3ID[0].first, sx3ChUp, sx3ChDn, sx3ChBk, sx3EUp, sx3EDn);
|
||||||
|
hitPos = sx3_contr.GetHitPos();
|
||||||
|
HitNonZero = true;
|
||||||
|
// hitPos.Print();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// //======================= QQQ
|
||||||
|
for( int i = 0; i < qqq.multi; i ++){
|
||||||
|
|
||||||
|
// for( int j = 0; j < pc.multi; j++){
|
||||||
|
if(qqq.e[i]>50 ){
|
||||||
|
hqqqIndexVE->Fill( qqq.index[i], qqq.e[i] );
|
||||||
|
for( int j = 0; j < qqq.multi; j++){
|
||||||
|
if ( j == i ) continue;
|
||||||
|
hqqqCoin->Fill( qqq.index[i], qqq.index[j]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for( int j = i + 1; j < qqq.multi; j++){
|
||||||
|
for( int k = 0; k < pc.multi; k++){
|
||||||
|
// if(qqq.e[i>50]){
|
||||||
|
hqqqVpcE->Fill( qqq.e[i], pc.e[k] );
|
||||||
|
hqqqVpcIndex->Fill( qqq.index[i], pc.index[j] );
|
||||||
|
}
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
|
||||||
|
// hanVScatsum->Fill(aE,cE);
|
||||||
|
|
||||||
|
|
||||||
|
if( HitNonZero){
|
||||||
|
pw_contr.CalTrack( hitPos, aID, cID);
|
||||||
|
hZProj->Fill(pw_contr.GetZ0());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//########################################################### Track constrcution
|
||||||
|
|
||||||
|
|
||||||
|
//############################## DO THE KINEMATICS
|
||||||
|
|
||||||
|
|
||||||
|
return kTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PCGainMatch::Terminate(){
|
||||||
|
|
||||||
|
gStyle->SetOptStat("neiou");
|
||||||
|
TCanvas * canvas = new TCanvas("cANASEN", "ANASEN", 2000, 2000);
|
||||||
|
canvas->Divide(3,3);
|
||||||
|
|
||||||
|
//hsx3VpcIndex->Draw("colz");
|
||||||
|
|
||||||
|
//=============================================== pad-1
|
||||||
|
padID ++; canvas->cd(padID); canvas->cd(padID)->SetGrid(1);
|
||||||
|
|
||||||
|
hsx3IndexVE->Draw("colz");
|
||||||
|
|
||||||
|
//=============================================== pad-2
|
||||||
|
padID ++; canvas->cd(padID); canvas->cd(padID)->SetGrid(1);
|
||||||
|
|
||||||
|
hqqqIndexVE->Draw("colz");
|
||||||
|
|
||||||
|
//=============================================== pad-3
|
||||||
|
padID ++; canvas->cd(padID); canvas->cd(padID)->SetGrid(1);
|
||||||
|
|
||||||
|
hpcIndexVE->Draw("colz");
|
||||||
|
|
||||||
|
//=============================================== pad-4
|
||||||
|
padID ++; canvas->cd(padID); canvas->cd(padID)->SetGrid(1);
|
||||||
|
|
||||||
|
hsx3Coin->Draw("colz");
|
||||||
|
|
||||||
|
//=============================================== pad-5
|
||||||
|
padID ++; canvas->cd(padID); canvas->cd(padID)->SetGrid(1);
|
||||||
|
|
||||||
|
canvas->cd(padID)->SetLogz(true);
|
||||||
|
|
||||||
|
hqqqCoin->Draw("colz");
|
||||||
|
|
||||||
|
//=============================================== pad-6
|
||||||
|
padID ++; canvas->cd(padID); canvas->cd(padID)->SetGrid(1);
|
||||||
|
|
||||||
|
hpcCoin->Draw("colz");
|
||||||
|
|
||||||
|
//=============================================== pad-7
|
||||||
|
padID ++; canvas->cd(padID); canvas->cd(padID)->SetGrid(1);
|
||||||
|
|
||||||
|
// hsx3VpcIndex ->Draw("colz");
|
||||||
|
hsx3VpcE->Draw("colz") ;
|
||||||
|
|
||||||
|
//=============================================== pad-8
|
||||||
|
padID ++; canvas->cd(padID); canvas->cd(padID)->SetGrid(1);
|
||||||
|
|
||||||
|
// hqqqVpcIndex ->Draw("colz");
|
||||||
|
|
||||||
|
hqqqVpcE ->Draw("colz");
|
||||||
|
//=============================================== pad-9
|
||||||
|
padID ++;
|
||||||
|
|
||||||
|
// canvas->cd(padID)->DrawFrame(-50, -50, 50, 50);
|
||||||
|
// hqqqPolar->Draw("same colz pol");
|
||||||
|
|
||||||
|
canvas->cd(padID); canvas->cd(padID)->SetGrid(1);
|
||||||
|
hanVScatsum->Draw("colz");
|
||||||
|
// hAnodeHits->Draw("colz");
|
||||||
|
// hAnodeMultiplicity->Draw();
|
||||||
|
}
|
||||||
114
PCGainMatch.h
Normal file
114
PCGainMatch.h
Normal file
|
|
@ -0,0 +1,114 @@
|
||||||
|
#ifndef PCGainMatch_h
|
||||||
|
#define PCGainMatch_h
|
||||||
|
|
||||||
|
#include <TROOT.h>
|
||||||
|
#include <TChain.h>
|
||||||
|
#include <TFile.h>
|
||||||
|
#include <TSelector.h>
|
||||||
|
|
||||||
|
#include "Armory/ClassDet.h"
|
||||||
|
|
||||||
|
class PCGainMatch : public TSelector {
|
||||||
|
public :
|
||||||
|
TTree *fChain; //!pointer to the analyzed TTree or TChain
|
||||||
|
|
||||||
|
// Fixed size dimensions of array or collections stored in the TTree if any.
|
||||||
|
|
||||||
|
// Declaration of leaf types
|
||||||
|
Det sx3;
|
||||||
|
Det qqq;
|
||||||
|
Det pc ;
|
||||||
|
|
||||||
|
ULong64_t evID;
|
||||||
|
UInt_t run;
|
||||||
|
|
||||||
|
// List of branches
|
||||||
|
TBranch *b_eventID; //!
|
||||||
|
TBranch *b_run; //!
|
||||||
|
TBranch *b_sx3Multi; //!
|
||||||
|
TBranch *b_sx3ID; //!
|
||||||
|
TBranch *b_sx3Ch; //!
|
||||||
|
TBranch *b_sx3E; //!
|
||||||
|
TBranch *b_sx3T; //!
|
||||||
|
TBranch *b_qqqMulti; //!
|
||||||
|
TBranch *b_qqqID; //!
|
||||||
|
TBranch *b_qqqCh; //!
|
||||||
|
TBranch *b_qqqE; //!
|
||||||
|
TBranch *b_qqqT; //!
|
||||||
|
TBranch *b_pcMulti; //!
|
||||||
|
TBranch *b_pcID; //!
|
||||||
|
TBranch *b_pcCh; //!
|
||||||
|
TBranch *b_pcE; //!
|
||||||
|
TBranch *b_pcT; //!
|
||||||
|
|
||||||
|
PCGainMatch(TTree * /*tree*/ =0) : fChain(0) { }
|
||||||
|
virtual ~PCGainMatch() { }
|
||||||
|
virtual Int_t Version() const { return 2; }
|
||||||
|
virtual void Begin(TTree *tree);
|
||||||
|
virtual void SlaveBegin(TTree *tree);
|
||||||
|
virtual void Init(TTree *tree);
|
||||||
|
virtual Bool_t Notify();
|
||||||
|
virtual Bool_t Process(Long64_t entry);
|
||||||
|
virtual Int_t GetEntry(Long64_t entry, Int_t getall = 0) { return fChain ? fChain->GetTree()->GetEntry(entry, getall) : 0; }
|
||||||
|
virtual void SetOption(const char *option) { fOption = option; }
|
||||||
|
virtual void SetObject(TObject *obj) { fObject = obj; }
|
||||||
|
virtual void SetInputList(TList *input) { fInput = input; }
|
||||||
|
virtual TList *GetOutputList() const { return fOutput; }
|
||||||
|
virtual void SlaveTerminate();
|
||||||
|
virtual void Terminate();
|
||||||
|
|
||||||
|
ClassDef(PCGainMatch,0);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef PCGainMatch_cxx
|
||||||
|
void PCGainMatch::Init(TTree *tree){
|
||||||
|
|
||||||
|
// Set branch addresses and branch pointers
|
||||||
|
if (!tree) return;
|
||||||
|
fChain = tree;
|
||||||
|
fChain->SetMakeClass(1);
|
||||||
|
|
||||||
|
fChain->SetBranchAddress("evID", &evID, &b_eventID);
|
||||||
|
fChain->SetBranchAddress("run", &run, &b_run);
|
||||||
|
|
||||||
|
sx3.SetDetDimension(24,12);
|
||||||
|
qqq.SetDetDimension(4,32);
|
||||||
|
pc.SetDetDimension(2,24);
|
||||||
|
|
||||||
|
fChain->SetBranchAddress("sx3Multi", &sx3.multi, &b_sx3Multi);
|
||||||
|
fChain->SetBranchAddress("sx3ID", &sx3.id, &b_sx3ID);
|
||||||
|
fChain->SetBranchAddress("sx3Ch", &sx3.ch, &b_sx3Ch);
|
||||||
|
fChain->SetBranchAddress("sx3E", &sx3.e, &b_sx3E);
|
||||||
|
fChain->SetBranchAddress("sx3T", &sx3.t, &b_sx3T);
|
||||||
|
fChain->SetBranchAddress("qqqMulti", &qqq.multi, &b_qqqMulti);
|
||||||
|
fChain->SetBranchAddress("qqqID", &qqq.id, &b_qqqID);
|
||||||
|
fChain->SetBranchAddress("qqqCh", &qqq.ch, &b_qqqCh);
|
||||||
|
fChain->SetBranchAddress("qqqE", &qqq.e, &b_qqqE);
|
||||||
|
fChain->SetBranchAddress("qqqT", &qqq.t, &b_qqqT);
|
||||||
|
fChain->SetBranchAddress("pcMulti", &pc.multi, &b_pcMulti);
|
||||||
|
fChain->SetBranchAddress("pcID", &pc.id, &b_pcID);
|
||||||
|
fChain->SetBranchAddress("pcCh", &pc.ch, &b_pcCh);
|
||||||
|
fChain->SetBranchAddress("pcE", &pc.e, &b_pcE);
|
||||||
|
fChain->SetBranchAddress("pcT", &pc.t, &b_pcT);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Bool_t PCGainMatch::Notify(){
|
||||||
|
|
||||||
|
return kTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void PCGainMatch::SlaveBegin(TTree * /*tree*/){
|
||||||
|
|
||||||
|
TString option = GetOption();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void PCGainMatch::SlaveTerminate(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif // #ifdef Analyzer_cxx
|
||||||
|
|
@ -1,7 +1,8 @@
|
||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
|
|
||||||
if [ "$#" -ne 2 ]; then
|
if [ "$#" -ne 3 ]; then
|
||||||
echo "Usage: $0 runID timeWindow_ns"
|
echo "Usage: $0 runID timeWindow_ns option"
|
||||||
|
echo "option: 0 - process raw data, 1 - process mapped data"
|
||||||
echo "Exiting..."
|
echo "Exiting..."
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
@ -9,19 +10,25 @@ fi
|
||||||
runID=$1
|
runID=$1
|
||||||
timeWindow=$2
|
timeWindow=$2
|
||||||
|
|
||||||
rawFolder=/home/tandem/Desktop/analysis/data
|
option=$3
|
||||||
rootFolder=/home/tandem/Desktop/analysis/data/root_data
|
|
||||||
|
|
||||||
rsync -a splitpole@128.186.111.223:/media/nvmeData/ANASEN27Alap/*.fsu /home/tandem/Desktop/analysis/data
|
# rawFolder=/home/tandem/data1/2024_09_17Fap/data
|
||||||
|
rawFolder=../Raw_data
|
||||||
|
rootFolder=../root_data
|
||||||
|
|
||||||
fileList=`\ls -1 ${rawFolder}/Run_${runID}_*.fsu`
|
if [ $option -eq 0 ]; then
|
||||||
|
|
||||||
./EventBuilder ${timeWindow} 0 0 10000000 ${fileList}
|
# rsync -auh --info=progress2 splitpole@128.186.111.223:/media/nvmeData/2024_09_17Fap/*.fsu /home/tandem/data1/2024_09_17Fap/data
|
||||||
|
|
||||||
outFile=${rawFolder}/*${runID}*${timeWindow}.root
|
fileList=`\ls -1 ${rawFolder}/*Run_${runID}_*.fsu`
|
||||||
|
|
||||||
mv -vf ${outFile} ${rootFolder}/.
|
# ./EventBuilder ${timeWindow} 0 0 100000000 ${fileList}
|
||||||
|
|
||||||
./Mapper ${rootFolder}/*${runID}*${timeWindow}.root
|
outFile=${rawFolder}/*${runID}*${timeWindow}.root
|
||||||
|
|
||||||
|
mv -vf ${outFile} ${rootFolder}/.
|
||||||
|
|
||||||
|
./Mapper ${rootFolder}/*${runID}*${timeWindow}.root
|
||||||
|
fi
|
||||||
|
|
||||||
root "processRun.C(\"${rootFolder}/Run_${runID}_mapped.root\")"
|
root "processRun.C(\"${rootFolder}/Run_${runID}_mapped.root\")"
|
||||||
|
|
|
||||||
167
QQQ_Calcheck.C
Normal file
167
QQQ_Calcheck.C
Normal file
|
|
@ -0,0 +1,167 @@
|
||||||
|
|
||||||
|
#define QQQ_Calcheck_cxx
|
||||||
|
|
||||||
|
#include <TH2.h>
|
||||||
|
#include <TF1.h>
|
||||||
|
#include <TStyle.h>
|
||||||
|
#include <TCanvas.h>
|
||||||
|
#include <TMath.h>
|
||||||
|
#include <TCutG.h>
|
||||||
|
#include <fstream>
|
||||||
|
#include <utility>
|
||||||
|
#include <algorithm>
|
||||||
|
#include "Armory/HistPlotter.h"
|
||||||
|
#include "TVector3.h"
|
||||||
|
#include "QQQ_Calcheck.h"
|
||||||
|
|
||||||
|
TH2F *hQQQFVB;
|
||||||
|
HistPlotter *plotter;
|
||||||
|
int padID = 0;
|
||||||
|
|
||||||
|
TCutG *cut;
|
||||||
|
std::map<std::tuple<int, int, int>, std::vector<std::pair<double, double>>> dataPoints;
|
||||||
|
|
||||||
|
bool qqqEcut = false;
|
||||||
|
|
||||||
|
// Gain Arrays
|
||||||
|
const int MAX_QQQ = 4;
|
||||||
|
const int MAX_RING = 16;
|
||||||
|
const int MAX_WEDGE = 16;
|
||||||
|
double qqqwGain[MAX_QQQ][MAX_RING][MAX_WEDGE] = {{{0}}};
|
||||||
|
double qqqrGain[MAX_QQQ][MAX_RING][MAX_WEDGE] = {{{0}}};
|
||||||
|
bool qqqwGainValid[MAX_QQQ][MAX_RING][MAX_WEDGE] = {{{false}}};
|
||||||
|
bool qqqrGainValid[MAX_QQQ][MAX_RING][MAX_WEDGE] = {{{false}}};
|
||||||
|
double qqqCalib[MAX_QQQ][MAX_RING][MAX_WEDGE] = {{{0}}};
|
||||||
|
bool qqqCalibValid[MAX_QQQ][MAX_RING][MAX_WEDGE] = {{{false}}};
|
||||||
|
|
||||||
|
void QQQ_Calcheck::Begin(TTree * /*tree*/)
|
||||||
|
{
|
||||||
|
plotter = new HistPlotter("Cal_checkQQQ.root", "TFILE");
|
||||||
|
// ----------------------- Load QQQ Gains
|
||||||
|
{
|
||||||
|
std::string filename = "qqq_GainMatch.dat";
|
||||||
|
std::ifstream infile(filename);
|
||||||
|
if (!infile.is_open())
|
||||||
|
{
|
||||||
|
std::cerr << "Error opening " << filename << "!" << std::endl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int det, ring, wedge;
|
||||||
|
double gainw,gainr;
|
||||||
|
while (infile >> det >> ring >> wedge >> gainw>> gainr)
|
||||||
|
{
|
||||||
|
qqqwGain[det][ring][wedge] = gainw;
|
||||||
|
// qqqrGain[det][ring][wedge] = gainr;
|
||||||
|
qqqwGainValid[det][ring][wedge] = (gainw > 0);
|
||||||
|
// qqqrGainValid[det][ring][wedge] = (gainr > 0);
|
||||||
|
}
|
||||||
|
infile.close();
|
||||||
|
std::cout << "Loaded QQQ gains from " << filename << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----------------------- Load QQQ Calibrations
|
||||||
|
{
|
||||||
|
std::string filename = "qqq_Calib.dat";
|
||||||
|
std::ifstream infile(filename);
|
||||||
|
if (!infile.is_open())
|
||||||
|
{
|
||||||
|
std::cerr << "Error opening " << filename << "!" << std::endl;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
int det, ring, wedge;
|
||||||
|
double slope;
|
||||||
|
while (infile >> det >> ring >> wedge >> slope)
|
||||||
|
{
|
||||||
|
qqqCalib[det][ring][wedge] = slope;
|
||||||
|
qqqCalibValid[det][ring][wedge] = (slope > 0);
|
||||||
|
}
|
||||||
|
infile.close();
|
||||||
|
std::cout << "Loaded QQQ calibrations from " << filename << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Bool_t QQQ_Calcheck::Process(Long64_t entry)
|
||||||
|
{
|
||||||
|
b_qqqMulti->GetEntry(entry);
|
||||||
|
b_qqqID->GetEntry(entry);
|
||||||
|
b_qqqCh->GetEntry(entry);
|
||||||
|
b_qqqE->GetEntry(entry);
|
||||||
|
b_qqqT->GetEntry(entry);
|
||||||
|
|
||||||
|
qqq.CalIndex();
|
||||||
|
|
||||||
|
for (int i = 0; i < qqq.multi; i++)
|
||||||
|
{
|
||||||
|
for (int j = i + 1; j < qqq.multi; j++)
|
||||||
|
{
|
||||||
|
if (qqq.e[i] > 100)
|
||||||
|
qqqEcut = true;
|
||||||
|
if (qqq.id[i] == qqq.id[j])
|
||||||
|
{
|
||||||
|
int chWedge = -1;
|
||||||
|
int chRing = -1;
|
||||||
|
float eWedgeRaw = 0.0;
|
||||||
|
float eWedge = 0.0;
|
||||||
|
float eWedgeMeV = 0.0;
|
||||||
|
float eRingRaw = 0.0;
|
||||||
|
float eRing = 0.0;
|
||||||
|
float eRingMeV = 0.0;
|
||||||
|
// plug in gains
|
||||||
|
if (qqq.ch[i] < 16 && qqq.ch[j] >= 16 && /*qqqrGainValid[qqq.id[i]][qqq.ch[i]][qqq.ch[j] - 16] &&*/ qqqwGainValid[qqq.id[i]][qqq.ch[i]][qqq.ch[j] - 16])
|
||||||
|
{
|
||||||
|
chWedge = qqq.ch[i];
|
||||||
|
eWedgeRaw = qqq.e[i];
|
||||||
|
eWedge = qqq.e[i] * qqqwGain[qqq.id[i]][qqq.ch[i]][qqq.ch[j] - 16];
|
||||||
|
// printf("Wedge E: %.2f Gain: %.4f \n", eWedge, qqqGain[qqq.id[i]][qqq.ch[i]][qqq.ch[j] - 16]);
|
||||||
|
chRing = qqq.ch[j] - 16;
|
||||||
|
eRingRaw = qqq.e[j];
|
||||||
|
eRing = qqq.e[j];//* qqqrGain[qqq.id[j]][qqq.ch[j]][qqq.ch[i]-16];
|
||||||
|
}
|
||||||
|
else if (qqq.ch[j] < 16 && qqq.ch[i] >= 16/* && qqqrGainValid[qqq.id[j]][qqq.ch[j]][qqq.ch[i] - 16] */&& qqqwGainValid[qqq.id[j]][qqq.ch[j]][qqq.ch[i] - 16])
|
||||||
|
{
|
||||||
|
chWedge = qqq.ch[j];
|
||||||
|
eWedge = qqq.e[j] * qqqwGain[qqq.id[j]][qqq.ch[j]][qqq.ch[i] - 16];
|
||||||
|
eWedgeRaw = qqq.e[j];
|
||||||
|
|
||||||
|
chRing = qqq.ch[i] - 16;
|
||||||
|
eRing = qqq.e[i];// * qqqrGain[qqq.id[i]][qqq.ch[i]][qqq.ch[j] - 16];
|
||||||
|
eRingRaw = qqq.e[i];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
continue;
|
||||||
|
// plug in calibrations
|
||||||
|
if (qqqCalibValid[qqq.id[i]][chWedge][chRing])
|
||||||
|
{
|
||||||
|
eWedgeMeV = eWedge * qqqCalib[qqq.id[i]][chWedge][chRing] / 1000;
|
||||||
|
eRingMeV = eRing * qqqCalib[qqq.id[i]][chWedge][chRing] / 1000;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// hQQQFVB->Fill(eWedge, eRing);
|
||||||
|
plotter->Fill2D(Form("hRaw_qqq%d_ring%d_wedge%d", qqq.id[i], chRing, chWedge), 400, 0, 8000, 400, 0, 8000, eWedgeRaw, eRingRaw, "ERaw");
|
||||||
|
plotter->Fill2D(Form("hGM_qqq%d_ring%d_wedge%d", qqq.id[i], chRing, chWedge), 400, 0, 16000, 400, 0, 16000, eWedge, eRing, "EGM");
|
||||||
|
plotter->Fill2D(Form("hCal_qqq%d_ring%d_wedge%d", qqq.id[i], chRing, chWedge), 400, 0, 10, 400, 0, 10, eWedgeMeV, eRingMeV, "ECal");
|
||||||
|
if(eWedgeRaw >1500 && eRingRaw>1500 )
|
||||||
|
plotter->Fill2D(Form("hCal_cut_qqq%d_ring%d_wedge%d", qqq.id[i], chRing, chWedge), 400, 0, 10, 400, 0, 10, eWedgeMeV, eRingMeV, "ECal_cut");
|
||||||
|
|
||||||
|
plotter->Fill2D(Form("hRCal_qqq%d", qqq.id[i]), 16, 0, 15, 1000, 0, 30, chRing, eRingMeV, "RingCal");
|
||||||
|
plotter->Fill2D(Form("hWCal_qqq%d", qqq.id[i]), 16, 0, 15, 1000, 0, 30, chWedge, eWedgeMeV, "WedgeCal");
|
||||||
|
plotter->Fill2D("hRawQQQ", 4000, 0, 8000, 4000, 0, 8000, eWedgeRaw, eRingRaw);
|
||||||
|
plotter->Fill2D("hGMQQQ", 4000, 0, 8000, 4000, 0, 8000, eWedge, eRing);
|
||||||
|
plotter->Fill2D("hCalQQQ", 4000, 0, 10, 4000, 0, 10, eWedgeMeV, eRingMeV);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return kTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QQQ_Calcheck::Terminate()
|
||||||
|
{
|
||||||
|
plotter->FlushToDisk();
|
||||||
|
std::cout << "Calibration check file for 2D QQQ histogram saved.\n";
|
||||||
|
}
|
||||||
114
QQQ_Calcheck.h
Normal file
114
QQQ_Calcheck.h
Normal file
|
|
@ -0,0 +1,114 @@
|
||||||
|
#ifndef QQQ_Calcheck_h
|
||||||
|
#define QQQ_Calcheck_h
|
||||||
|
|
||||||
|
#include <TROOT.h>
|
||||||
|
#include <TChain.h>
|
||||||
|
#include <TFile.h>
|
||||||
|
#include <TSelector.h>
|
||||||
|
|
||||||
|
#include "Armory/ClassDet.h"
|
||||||
|
|
||||||
|
class QQQ_Calcheck : public TSelector {
|
||||||
|
public :
|
||||||
|
TTree *fChain; //!pointer to the analyzed TTree or TChain
|
||||||
|
|
||||||
|
// Fixed size dimensions of array or collections stored in the TTree if any.
|
||||||
|
|
||||||
|
// Declaration of leaf types
|
||||||
|
Det sx3;
|
||||||
|
Det qqq;
|
||||||
|
Det pc ;
|
||||||
|
|
||||||
|
ULong64_t evID;
|
||||||
|
UInt_t run;
|
||||||
|
|
||||||
|
// List of branches
|
||||||
|
TBranch *b_eventID; //!
|
||||||
|
TBranch *b_run; //!
|
||||||
|
TBranch *b_sx3Multi; //!
|
||||||
|
TBranch *b_sx3ID; //!
|
||||||
|
TBranch *b_sx3Ch; //!
|
||||||
|
TBranch *b_sx3E; //!
|
||||||
|
TBranch *b_sx3T; //!
|
||||||
|
TBranch *b_qqqMulti; //!
|
||||||
|
TBranch *b_qqqID; //!
|
||||||
|
TBranch *b_qqqCh; //!
|
||||||
|
TBranch *b_qqqE; //!
|
||||||
|
TBranch *b_qqqT; //!
|
||||||
|
TBranch *b_pcMulti; //!
|
||||||
|
TBranch *b_pcID; //!
|
||||||
|
TBranch *b_pcCh; //!
|
||||||
|
TBranch *b_pcE; //!
|
||||||
|
TBranch *b_pcT; //!
|
||||||
|
|
||||||
|
QQQ_Calcheck(TTree * /*tree*/ =0) : fChain(0) { }
|
||||||
|
virtual ~QQQ_Calcheck() { }
|
||||||
|
virtual Int_t Version() const { return 2; }
|
||||||
|
virtual void Begin(TTree *tree);
|
||||||
|
virtual void SlaveBegin(TTree *tree);
|
||||||
|
virtual void Init(TTree *tree);
|
||||||
|
virtual Bool_t Notify();
|
||||||
|
virtual Bool_t Process(Long64_t entry);
|
||||||
|
virtual Int_t GetEntry(Long64_t entry, Int_t getall = 0) { return fChain ? fChain->GetTree()->GetEntry(entry, getall) : 0; }
|
||||||
|
virtual void SetOption(const char *option) { fOption = option; }
|
||||||
|
virtual void SetObject(TObject *obj) { fObject = obj; }
|
||||||
|
virtual void SetInputList(TList *input) { fInput = input; }
|
||||||
|
virtual TList *GetOutputList() const { return fOutput; }
|
||||||
|
virtual void SlaveTerminate();
|
||||||
|
virtual void Terminate();
|
||||||
|
|
||||||
|
ClassDef(QQQ_Calcheck,0);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef QQQ_Calcheck_cxx
|
||||||
|
void QQQ_Calcheck::Init(TTree *tree){
|
||||||
|
|
||||||
|
// Set branch addresses and branch pointers
|
||||||
|
if (!tree) return;
|
||||||
|
fChain = tree;
|
||||||
|
fChain->SetMakeClass(1);
|
||||||
|
|
||||||
|
fChain->SetBranchAddress("evID", &evID, &b_eventID);
|
||||||
|
fChain->SetBranchAddress("run", &run, &b_run);
|
||||||
|
|
||||||
|
sx3.SetDetDimension(24,12);
|
||||||
|
qqq.SetDetDimension(4,32);
|
||||||
|
pc.SetDetDimension(2,24);
|
||||||
|
|
||||||
|
fChain->SetBranchAddress("sx3Multi", &sx3.multi, &b_sx3Multi);
|
||||||
|
fChain->SetBranchAddress("sx3ID", &sx3.id, &b_sx3ID);
|
||||||
|
fChain->SetBranchAddress("sx3Ch", &sx3.ch, &b_sx3Ch);
|
||||||
|
fChain->SetBranchAddress("sx3E", &sx3.e, &b_sx3E);
|
||||||
|
fChain->SetBranchAddress("sx3T", &sx3.t, &b_sx3T);
|
||||||
|
fChain->SetBranchAddress("qqqMulti", &qqq.multi, &b_qqqMulti);
|
||||||
|
fChain->SetBranchAddress("qqqID", &qqq.id, &b_qqqID);
|
||||||
|
fChain->SetBranchAddress("qqqCh", &qqq.ch, &b_qqqCh);
|
||||||
|
fChain->SetBranchAddress("qqqE", &qqq.e, &b_qqqE);
|
||||||
|
fChain->SetBranchAddress("qqqT", &qqq.t, &b_qqqT);
|
||||||
|
fChain->SetBranchAddress("pcMulti", &pc.multi, &b_pcMulti);
|
||||||
|
fChain->SetBranchAddress("pcID", &pc.id, &b_pcID);
|
||||||
|
fChain->SetBranchAddress("pcCh", &pc.ch, &b_pcCh);
|
||||||
|
fChain->SetBranchAddress("pcE", &pc.e, &b_pcE);
|
||||||
|
fChain->SetBranchAddress("pcT", &pc.t, &b_pcT);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Bool_t QQQ_Calcheck::Notify(){
|
||||||
|
|
||||||
|
return kTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QQQ_Calcheck::SlaveBegin(TTree * /*tree*/){
|
||||||
|
|
||||||
|
TString option = GetOption();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void QQQ_Calcheck::SlaveTerminate(){
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif // #ifdef QQQ_Calcheck_cxx
|
||||||
140
RunTimeSummary.C
Normal file
140
RunTimeSummary.C
Normal file
|
|
@ -0,0 +1,140 @@
|
||||||
|
#include <TFile.h>
|
||||||
|
#include <TH1.h>
|
||||||
|
#include <TH2.h>
|
||||||
|
#include <TString.h>
|
||||||
|
#include <TSystem.h>
|
||||||
|
#include <TCanvas.h>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
void RunTimeSummary(int startRun, int endRun)
|
||||||
|
{
|
||||||
|
TString fileDir = "/mnt/d/Remapped_files/17F_data/root_data/";
|
||||||
|
TString histName = "AnodeQQQ_Time";
|
||||||
|
TString filePattern = "Run_%03d_mapped_histograms.root";
|
||||||
|
TString filePatternAlt = "ProtonRun_%d_mapped_histograms.root";
|
||||||
|
TString filePatternAlt2 = "Source_%d_mapped_histograms.root";
|
||||||
|
|
||||||
|
int nBinsTime = 0;
|
||||||
|
double timeMin = 0, timeMax = 0;
|
||||||
|
bool foundRef = false;
|
||||||
|
|
||||||
|
for (int r = startRun; r <= endRun; r++)
|
||||||
|
{
|
||||||
|
TString tempName;
|
||||||
|
|
||||||
|
// 1. Try Pattern 1: Run_XXX...
|
||||||
|
tempName = fileDir + Form(filePattern, r);
|
||||||
|
if (gSystem->AccessPathName(tempName))
|
||||||
|
{ // Returns true if MISSING
|
||||||
|
|
||||||
|
// 2. Try Pattern 2: ProtonRun_X...
|
||||||
|
tempName = fileDir + Form(filePatternAlt, r);
|
||||||
|
if (gSystem->AccessPathName(tempName))
|
||||||
|
{
|
||||||
|
|
||||||
|
// 3. Try Pattern 3: Source_X...
|
||||||
|
tempName = fileDir + Form(filePatternAlt2, r);
|
||||||
|
if (gSystem->AccessPathName(tempName))
|
||||||
|
{
|
||||||
|
// All 3 patterns failed. Skip this run.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we get here, 'tempName' holds the valid filename that was found
|
||||||
|
TFile *fTemp = TFile::Open(tempName);
|
||||||
|
if (!fTemp || fTemp->IsZombie())
|
||||||
|
{
|
||||||
|
if (fTemp)
|
||||||
|
delete fTemp;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
TH1F *hRef = (TH1F *)fTemp->Get(histName);
|
||||||
|
if (hRef)
|
||||||
|
{
|
||||||
|
|
||||||
|
nBinsTime = hRef->GetNbinsX();
|
||||||
|
timeMin = hRef->GetXaxis()->GetXmin();
|
||||||
|
timeMax = hRef->GetXaxis()->GetXmax();
|
||||||
|
foundRef = true;
|
||||||
|
|
||||||
|
delete hRef;
|
||||||
|
fTemp->Close();
|
||||||
|
delete fTemp;
|
||||||
|
printf("Reference found in Run %d: %d bins, Range [%.1f, %.1f]\n", r, nBinsTime, timeMin, timeMax);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
fTemp->Close();
|
||||||
|
delete fTemp;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!foundRef)
|
||||||
|
{
|
||||||
|
printf("Error: No valid histograms found in the entire range. Exiting.\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int nRuns = endRun - startRun + 1;
|
||||||
|
TH2F *hSummary = new TH2F("hSummary",
|
||||||
|
Form("Timing Summary (Runs %d-%d);Timing;Run Number", startRun, endRun),
|
||||||
|
nBinsTime, timeMin, timeMax,
|
||||||
|
nRuns, startRun, endRun + 1);
|
||||||
|
|
||||||
|
for (int run = startRun; run <= endRun; run++)
|
||||||
|
{
|
||||||
|
|
||||||
|
TString filename = fileDir + Form(filePattern, run);
|
||||||
|
|
||||||
|
if (gSystem->AccessPathName(filename))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
TFile *fin = TFile::Open(filename);
|
||||||
|
if (!fin || fin->IsZombie())
|
||||||
|
{
|
||||||
|
if (fin)
|
||||||
|
delete fin;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
TH1F *hin = (TH1F *)fin->Get(histName);
|
||||||
|
|
||||||
|
if (hin)
|
||||||
|
{
|
||||||
|
// Determine which ROW (Y-bin) corresponds to this Run
|
||||||
|
// Note: ROOT bins start at 1.
|
||||||
|
// If startRun=10 and run=10 -> binY=1.
|
||||||
|
int binY_Run = run - startRun + 1;
|
||||||
|
|
||||||
|
// Loop through the Time bins (X-bins in the 1D hist)
|
||||||
|
for (int binX_Time = 1; binX_Time <= hin->GetNbinsX(); binX_Time++)
|
||||||
|
{
|
||||||
|
|
||||||
|
double content = hin->GetBinContent(binX_Time);
|
||||||
|
|
||||||
|
// Copy content to: (Time, Run)
|
||||||
|
if (content > 0)
|
||||||
|
{
|
||||||
|
hSummary->SetBinContent(binX_Time, binY_Run, content);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
delete hin;
|
||||||
|
}
|
||||||
|
|
||||||
|
fin->Close();
|
||||||
|
delete fin;
|
||||||
|
|
||||||
|
if ((run - startRun) % 10 == 0)
|
||||||
|
printf("Stitched Run %d...\n", run);
|
||||||
|
}
|
||||||
|
|
||||||
|
TFile *fOut = new TFile("SummaryPlot.root", "RECREATE");
|
||||||
|
hSummary->Write();
|
||||||
|
|
||||||
|
TCanvas *c1 = new TCanvas("c1", "Time Summary Plot", 1000, 800);
|
||||||
|
hSummary->SetStats(0);
|
||||||
|
hSummary->Draw("COLZ");
|
||||||
|
|
||||||
|
printf("Done! Saved to SummaryPlot.root\n");
|
||||||
|
}
|
||||||
BIN
Timing_Summary_Matplotlib.png
Normal file
BIN
Timing_Summary_Matplotlib.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 70 KiB |
923
TrackRecon.C
923
TrackRecon.C
|
|
@ -1,65 +1,188 @@
|
||||||
#define Analyzer_cxx
|
#define TrackRecon_cxx
|
||||||
|
|
||||||
|
#include "TrackRecon.h"
|
||||||
|
#include "Armory/ClassPW.h"
|
||||||
|
#include "Armory/HistPlotter.h"
|
||||||
|
|
||||||
#include "Analyzer.h"
|
|
||||||
#include <TH2.h>
|
#include <TH2.h>
|
||||||
#include <TStyle.h>
|
#include <TStyle.h>
|
||||||
#include <TCanvas.h>
|
#include <TCanvas.h>
|
||||||
#include <TMath.h>
|
#include <TMath.h>
|
||||||
|
#include "TVector3.h"
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <map>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
#include "Armory/ClassSX3.h"
|
// Global instances
|
||||||
#include "Armory/ClassPC1An.h"
|
PW pw_contr;
|
||||||
|
PW pwinstance;
|
||||||
#include "TVector3.h"
|
|
||||||
|
|
||||||
TH2F * hsx3IndexVE;
|
|
||||||
TH2F * hqqqIndexVE;
|
|
||||||
TH2F * hpcIndexVE;
|
|
||||||
|
|
||||||
TH2F * hsx3Coin;
|
|
||||||
TH2F * hqqqCoin;
|
|
||||||
TH2F * hpcCoin;
|
|
||||||
|
|
||||||
TH2F * hqqqPolar;
|
|
||||||
TH2F * hsx3VpcIndex;
|
|
||||||
TH2F * hqqqVpcIndex;
|
|
||||||
TH2F * hqqqVpcE;
|
|
||||||
TH2F * hsx3VpcE;
|
|
||||||
TH2F * hanVScatsum;
|
|
||||||
int padID = 0;
|
|
||||||
|
|
||||||
SX3 sx3_contr;
|
|
||||||
PC pw_contr;
|
|
||||||
TVector3 hitPos;
|
TVector3 hitPos;
|
||||||
|
double qqqenergy,qqqtime;
|
||||||
|
|
||||||
|
// Calibration globals
|
||||||
|
const int MAX_QQQ = 4;
|
||||||
|
const int MAX_RING = 16;
|
||||||
|
const int MAX_WEDGE = 16;
|
||||||
|
double qqqGain[MAX_QQQ][MAX_RING][MAX_WEDGE] = {{{0}}};
|
||||||
|
bool qqqGainValid[MAX_QQQ][MAX_RING][MAX_WEDGE] = {{{false}}};
|
||||||
|
double qqqCalib[MAX_QQQ][MAX_RING][MAX_WEDGE] = {{{0}}};
|
||||||
|
bool qqqCalibValid[MAX_QQQ][MAX_RING][MAX_WEDGE] = {{{false}}};
|
||||||
|
// TCutg *cutQQQ;
|
||||||
|
|
||||||
|
// PC Arrays
|
||||||
|
double pcSlope[48];
|
||||||
|
double pcIntercept[48];
|
||||||
|
|
||||||
|
HistPlotter *plotter;
|
||||||
|
|
||||||
bool HitNonZero;
|
bool HitNonZero;
|
||||||
|
bool sx3ecut;
|
||||||
|
bool qqqEcut;
|
||||||
|
|
||||||
TH1F * hZProj;
|
void TrackRecon::Begin(TTree *tree)
|
||||||
|
{ // get file name
|
||||||
|
std::cout << tree->GetCurrentFile()->GetName() << std::endl;
|
||||||
|
// get substring from file name to identify run number
|
||||||
|
|
||||||
void Analyzer::Begin(TTree * /*tree*/){
|
|
||||||
TString option = GetOption();
|
TString option = GetOption();
|
||||||
|
std::string treefilename(tree->GetCurrentFile()->GetName());
|
||||||
|
|
||||||
hZProj = new TH1F("hZProj", "Z Projection", 200, -600, 600);
|
plotter = new HistPlotter(treefilename.substr(0, treefilename.length() - std::string(".root").length()) + "_histograms.root", "TFILE");
|
||||||
|
// plotter = new HistPlotter("Analyzer.root", "TFILE");
|
||||||
|
|
||||||
sx3_contr.ConstructGeo();
|
|
||||||
pw_contr.ConstructGeo();
|
pw_contr.ConstructGeo();
|
||||||
|
pwinstance.ConstructGeo();
|
||||||
|
|
||||||
|
// ---------------------------------------------------------
|
||||||
|
// 1. CRITICAL FIX: Initialize PC Arrays to Default (Raw)
|
||||||
|
// ---------------------------------------------------------
|
||||||
|
for (int i = 0; i < 48; i++)
|
||||||
|
{
|
||||||
|
pcSlope[i] = 1.0; // Default slope = 1 (preserves Raw energy)
|
||||||
|
pcIntercept[i] = 0.0; // Default intercept = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate Crossover Geometry ONCE
|
||||||
|
TVector3 a, c, diff;
|
||||||
|
double a2, ac, c2, adiff, cdiff, denom, alpha;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < pwinstance.An.size(); i++)
|
||||||
|
{
|
||||||
|
a = pwinstance.An[i].first - pwinstance.An[i].second;
|
||||||
|
|
||||||
|
for (size_t j = 0; j < pwinstance.Ca.size(); j++)
|
||||||
|
{
|
||||||
|
c = pwinstance.Ca[j].first - pwinstance.Ca[j].second;
|
||||||
|
diff = pwinstance.An[i].first - pwinstance.Ca[j].first;
|
||||||
|
a2 = a.Dot(a);
|
||||||
|
c2 = c.Dot(c);
|
||||||
|
ac = a.Dot(c);
|
||||||
|
adiff = a.Dot(diff);
|
||||||
|
cdiff = c.Dot(diff);
|
||||||
|
denom = a2 * c2 - ac * ac;
|
||||||
|
alpha = (ac * cdiff - c2 * adiff) / denom;
|
||||||
|
|
||||||
|
Crossover[i][j][0].x = pwinstance.An[i].first.X() + alpha * a.X();
|
||||||
|
Crossover[i][j][0].y = pwinstance.An[i].first.Y() + alpha * a.Y();
|
||||||
|
Crossover[i][j][0].z = pwinstance.An[i].first.Z() + alpha * a.Z();
|
||||||
|
|
||||||
|
if (Crossover[i][j][0].z < -190 || Crossover[i][j][0].z > 190 || (i + j) % 24 == 12)
|
||||||
|
{
|
||||||
|
Crossover[i][j][0].z = 9999999;
|
||||||
|
}
|
||||||
|
|
||||||
|
Crossover[i][j][1].x = alpha;
|
||||||
|
Crossover[i][j][1].y = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load PC Calibrations
|
||||||
|
std::ifstream inputFile("slope_intercept_results.dat");
|
||||||
|
if (inputFile.is_open())
|
||||||
|
{
|
||||||
|
std::string line;
|
||||||
|
int index;
|
||||||
|
double slope, intercept;
|
||||||
|
while (std::getline(inputFile, line))
|
||||||
|
{
|
||||||
|
std::stringstream ss(line);
|
||||||
|
ss >> index >> slope >> intercept;
|
||||||
|
if (index >= 0 && index <= 47)
|
||||||
|
{
|
||||||
|
pcSlope[index] = slope;
|
||||||
|
pcIntercept[index] = intercept;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inputFile.close();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cerr << "Error opening slope_intercept.txt" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load QQQ Cuts from file
|
||||||
|
// {
|
||||||
|
// std::string filename = "QQQ_PCCut.root";
|
||||||
|
// TFile *cutFile = TFile::Open(filename.c_str(), "READ");
|
||||||
|
// if (cutFile && !cutFile->IsZombie())
|
||||||
|
// {
|
||||||
|
// cutQQQ = (TCutg *)cutFile->Get("cutQQQPC");
|
||||||
|
// if (cutQQQ)
|
||||||
|
// {
|
||||||
|
// std::cout << "Loaded QQQ PC cut from " << filename << std::endl;
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// std::cerr << "Error: cutQQQPC not found in " << filename << std::endl;
|
||||||
|
// }
|
||||||
|
// cutFile->Close();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// ... (Load QQQ Gains and Calibs - same as before) ...
|
||||||
|
{
|
||||||
|
std::string filename = "qqq_GainMatch.dat";
|
||||||
|
std::ifstream infile(filename);
|
||||||
|
if (infile.is_open())
|
||||||
|
{
|
||||||
|
int det, ring, wedge;
|
||||||
|
double gainw, gainr;
|
||||||
|
while (infile >> det >> wedge >> ring >> gainw >> gainr)
|
||||||
|
{
|
||||||
|
qqqGain[det][wedge][ring] = gainw;
|
||||||
|
qqqGainValid[det][wedge][ring] = (gainw > 0);
|
||||||
|
// std::cout << "QQQ Gain Loaded: Det " << det << " Ring " << ring << " Wedge " << wedge << " GainW " << gainw << " GainR " << gainr << std::endl;
|
||||||
|
}
|
||||||
|
infile.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
std::string filename = "qqq_Calib.dat";
|
||||||
|
std::ifstream infile(filename);
|
||||||
|
if (infile.is_open())
|
||||||
|
{
|
||||||
|
int det, ring, wedge;
|
||||||
|
double slope;
|
||||||
|
while (infile >> det >> wedge >> ring >> slope)
|
||||||
|
{
|
||||||
|
qqqCalib[det][wedge][ring] = slope;
|
||||||
|
qqqCalibValid[det][wedge][ring] = (slope > 0);
|
||||||
|
// std::cout << "QQQ Calib Loaded: Det " << det << " Ring " << ring << " Wedge " << wedge << " Slope " << slope << std::endl;
|
||||||
|
}
|
||||||
|
infile.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Bool_t TrackRecon::Process(Long64_t entry)
|
||||||
|
{
|
||||||
|
|
||||||
Bool_t Analyzer::Process(Long64_t entry){
|
|
||||||
|
|
||||||
// if ( entry > 100 ) return kTRUE;
|
|
||||||
|
|
||||||
hitPos.Clear();
|
hitPos.Clear();
|
||||||
HitNonZero = false;
|
HitNonZero = false;
|
||||||
|
bool qqq1000cut = false;
|
||||||
// if( entry > 1) return kTRUE;
|
|
||||||
// printf("################### ev : %llu \n", entry);
|
|
||||||
|
|
||||||
b_sx3Multi->GetEntry(entry);
|
b_sx3Multi->GetEntry(entry);
|
||||||
b_sx3ID->GetEntry(entry);
|
b_sx3ID->GetEntry(entry);
|
||||||
b_sx3Ch->GetEntry(entry);
|
b_sx3Ch->GetEntry(entry);
|
||||||
|
|
@ -80,224 +203,558 @@ Bool_t Analyzer::Process(Long64_t entry){
|
||||||
qqq.CalIndex();
|
qqq.CalIndex();
|
||||||
pc.CalIndex();
|
pc.CalIndex();
|
||||||
|
|
||||||
// sx3.Print();
|
// QQQ Processing
|
||||||
|
|
||||||
//########################################################### Raw data
|
int qqqCount = 0;
|
||||||
// //======================= SX3
|
int qqqAdjCh = 0;
|
||||||
|
qqqenergy=-1;
|
||||||
|
qqqtime=-1;
|
||||||
|
|
||||||
std::vector<std::pair<int, int>> ID; // first = id, 2nd = index
|
// REMOVE WHEN RERUNNING USING THE NEW CALIBRATION FILE
|
||||||
|
// for (int i = 0; i < qqq.multi; i++)
|
||||||
|
// {
|
||||||
|
// if ((qqq.id[i] == 3 || qqq.id[i] == 1) && qqq.ch[i] < 16)
|
||||||
|
// {
|
||||||
|
// qqq.ch[i] = 16 - qqq.ch[i];
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// for (int i = 0; i < qqq.multi; i++)
|
||||||
|
// {
|
||||||
|
// if (qqq.id[i] == 0 && qqq.ch[i] >= 16)
|
||||||
|
// {
|
||||||
|
// qqq.ch[i] = 31 - qqq.ch[i] + 16;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
if( ID.size() > 0 ){
|
bool PCQQQTimeCut = false;
|
||||||
std::sort(ID.begin(), ID.end(), [](const std::pair<int, int> & a, const std::pair<int, int> & b) {
|
for (int i = 0; i < qqq.multi; i++)
|
||||||
return a.first < b.first;
|
{
|
||||||
} );
|
|
||||||
// printf("##############################\n");
|
|
||||||
// for( size_t i = 0; i < ID.size(); i++) printf("%zu | %d %d \n", i, ID[i].first, ID[i].second );
|
|
||||||
|
|
||||||
std::vector<std::pair<int, int>> sx3ID;
|
plotter->Fill2D("QQQ_Index_Vs_Energy", 16 * 8, 0, 16 * 8, 2000, 0, 16000, qqq.index[i], qqq.e[i], "hRawQQQ");
|
||||||
sx3ID.push_back(ID[0]);
|
|
||||||
bool found = false;
|
for (int j = 0; j < qqq.multi; j++)
|
||||||
for( size_t i = 1; i < ID.size(); i++){
|
{
|
||||||
if( ID[i].first == sx3ID.back().first) {
|
if (j == i)
|
||||||
sx3ID.push_back(ID[i]);
|
continue;
|
||||||
if( sx3ID.size() >= 3) {
|
plotter->Fill2D("QQQ_Coincidence_Matrix", 16 * 8, 0, 16 * 8, 16 * 8, 0, 16 * 8, qqq.index[i], qqq.index[j], "hRawQQQ");
|
||||||
found = true;
|
}
|
||||||
}
|
|
||||||
}else{
|
for (int k = 0; k < pc.multi; k++)
|
||||||
if( !found ){
|
{
|
||||||
sx3ID.clear();
|
if (pc.index[k] < 24 && pc.e[k] > 50)
|
||||||
sx3ID.push_back(ID[i]);
|
{
|
||||||
}
|
plotter->Fill2D("QQQ_Vs_Anode_Energy", 400, 0, 4000, 1000, 0, 16000, qqq.e[i], pc.e[k], "hRawQQQ");
|
||||||
|
plotter->Fill2D("QQQ_Vs_PC_Index", 16 * 8, 0, 16 * 8, 24, 0, 24, qqq.index[i], pc.index[k], "hRawQQQ");
|
||||||
|
}
|
||||||
|
else if (pc.index[k] >= 24 && pc.e[k] > 50)
|
||||||
|
{
|
||||||
|
plotter->Fill2D("QQQ_Vs_Cathode_Energy", 400, 0, 4000, 1000, 0, 16000, qqq.e[i], pc.e[k], "hRawQQQ");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// printf("---------- sx3ID Multi : %zu \n", sx3ID.size());
|
for (int j = i + 1; j < qqq.multi; j++)
|
||||||
|
{
|
||||||
|
if (qqq.id[i] == qqq.id[j])
|
||||||
|
{
|
||||||
|
qqqCount++;
|
||||||
|
|
||||||
if( found ){
|
int chWedge = -1;
|
||||||
int sx3ChUp, sx3ChDn, sx3ChBk;
|
int chRing = -1;
|
||||||
float sx3EUp, sx3EDn;
|
double eWedge = 0.0;
|
||||||
// printf("------ sx3 ID : %d, multi: %zu\n", sx3ID[0].first, sx3ID.size());
|
double eWedgeMeV = 0.0;
|
||||||
for( size_t i = 0; i < sx3ID.size(); i++ ){
|
double eRing = 0.0;
|
||||||
int index = sx3ID[i].second;
|
double eRingMeV = 0.0;
|
||||||
// printf(" %zu | index %d | ch : %d, energy : %d \n", i, index, sx3.ch[index], sx3.e[index]);
|
double tRing = 0.0;
|
||||||
|
double tWedge = 0.0;
|
||||||
|
|
||||||
|
if (qqq.ch[i] < 16 && qqq.ch[j] >= 16 && qqqGainValid[qqq.id[i]][qqq.ch[i]][qqq.ch[j] - 16])
|
||||||
if( sx3.ch[index] < 8 ){
|
{
|
||||||
if( sx3.ch[index] % 2 == 0) {
|
chWedge = qqq.ch[i];
|
||||||
sx3ChDn = sx3.ch[index];
|
eWedge = qqq.e[i] * qqqGain[qqq.id[i]][qqq.ch[i]][qqq.ch[j] - 16];
|
||||||
sx3EDn = sx3.e[index];
|
chRing = qqq.ch[j] - 16;
|
||||||
}else{
|
eRing = qqq.e[j];
|
||||||
sx3ChUp = sx3.ch[index];
|
tRing = static_cast<double>(qqq.t[j]);
|
||||||
sx3EUp = sx3.e[index];
|
tWedge = static_cast<double>(qqq.t[i]);
|
||||||
}
|
|
||||||
}else{
|
|
||||||
sx3ChBk = sx3.ch[index];
|
|
||||||
}
|
}
|
||||||
for( int j = 0; j < pc.multi; j++){
|
else if (qqq.ch[j] < 16 && qqq.ch[i] >= 16 && qqqGainValid[qqq.id[j]][qqq.ch[j]][qqq.ch[i] - 16])
|
||||||
// hsx3VpcIndex->Fill( sx3.index[i], pc.index[j] );
|
{
|
||||||
if( sx3.ch[index] > 8 ){
|
chWedge = qqq.ch[j];
|
||||||
hsx3VpcE->Fill( sx3.e[i], pc.e[j] );
|
eWedge = qqq.e[j] * qqqGain[qqq.id[j]][qqq.ch[j]][qqq.ch[i] - 16];
|
||||||
// hpcIndexVE->Fill( pc.index[i], pc.e[i] );
|
chRing = qqq.ch[i] - 16;
|
||||||
|
eRing = qqq.e[i];
|
||||||
|
tRing = static_cast<double>(qqq.t[i]);
|
||||||
|
tWedge = static_cast<double>(qqq.t[j]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
continue;
|
||||||
|
|
||||||
|
plotter->Fill1D("Wedgetime_Vs_Ringtime", 100, -1000, 1000, tWedge - tRing, "hTiming");
|
||||||
|
plotter->Fill2D("RingE_vs_Index", 16 * 4, 0, 16 * 4, 1000, 0, 16000, chRing + qqq.id[i] * 16, eRing, "hRawQQQ");
|
||||||
|
plotter->Fill2D("WedgeE_vs_Index", 16 * 4, 0, 16 * 4, 1000, 0, 16000, chWedge + qqq.id[i] * 16, eWedge, "hRawQQQ");
|
||||||
|
|
||||||
|
if (qqqCalibValid[qqq.id[i]][chWedge][chRing])
|
||||||
|
{
|
||||||
|
eWedgeMeV = eWedge * qqqCalib[qqq.id[i]][chWedge][chRing] / 1000;
|
||||||
|
eRingMeV = eRing * qqqCalib[qqq.id[i]][chWedge][chRing] / 1000;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
continue;
|
||||||
|
|
||||||
|
plotter->Fill2D("WedgeE_Vs_RingECal", 1000, 0, 10, 1000, 0, 10, eWedgeMeV, eRingMeV, "hCalQQQ");
|
||||||
|
if(qqq.multi>2 ) plotter->Fill2D("WedgeE_Vs_RingECal_mulit>2", 1000, 0, 10, 1000, 0, 10, eWedgeMeV, eRingMeV, "hCalQQQ");
|
||||||
|
if(qqq.multi==2 ) plotter->Fill2D("WedgeE_Vs_RingECal_mulit=2", 1000, 0, 10, 1000, 0, 10, eWedgeMeV, eRingMeV, "hCalQQQ");
|
||||||
|
|
||||||
|
for (int k = 0; k < pc.multi; k++)
|
||||||
|
{
|
||||||
|
plotter->Fill2D("RingCh_vs_Anode_Index", 16 * 4, 0, 16 * 4, 24, 0, 24, chRing + qqq.id[i] * 16, pc.index[k], "hRawQQQ");
|
||||||
|
plotter->Fill2D("WedgeCh_vs_Anode_Index", 16 * 4, 0, 16 * 4, 24, 0, 24, chWedge + qqq.id[i] * 16, pc.index[k], "hRawQQQ");
|
||||||
|
plotter->Fill2D("WedgeCh_vs_Anode_Index" + std::to_string(qqq.id[i]), 16 * 4, 0, 16 * 4, 24, 0, 24, chWedge + qqq.id[i] * 16, pc.index[k]);
|
||||||
|
plotter->Fill2D("RingCh_vs_Cathode_Index", 16 * 4, 0, 16 * 4, 24, 24, 48, chRing + qqq.id[i] * 16, pc.index[k], "hRawQQQ");
|
||||||
|
plotter->Fill2D("WedgeCh_vs_Cathode_Index", 16 * 4, 0, 16 * 4, 24, 24, 48, chWedge + qqq.id[i] * 16, pc.index[k], "hRawQQQ");
|
||||||
|
|
||||||
|
if (pc.index[k] < 24 && pc.e[k] > 50)
|
||||||
|
{
|
||||||
|
// plotter->Fill2D("QQQ_CalibW_Vs_PC_Energy", 1000, 0, 16, 2000, 0, 30000, eWedgeMeV, pc.e[k], "hCalQQQ");
|
||||||
|
// plotter->Fill2D("QQQ_CalibR_Vs_PC_Energy", 1000, 0, 16, 2000, 0, 30000, eRingMeV, pc.e[k], "hCalQQQ");
|
||||||
|
|
||||||
|
// if (tRing - static_cast<double>(pc.t[k]) < 0 && tRing - static_cast<double>(pc.t[k]) > -600)
|
||||||
|
// // {
|
||||||
|
// // plotter->Fill2D("QQQ_CalibW_Vs_PC_Energy_Tight", 1000, 0, 16, 2000, 0, 30000, eWedgeMeV, pc.e[k], "hCalQQQ");
|
||||||
|
// // plotter->Fill2D("QQQ_CalibR_Vs_PC_Energy_Tight", 1000, 0, 16, 2000, 0, 30000, eRingMeV, pc.e[k], "hCalQQQ");
|
||||||
|
// // }
|
||||||
|
// // else
|
||||||
|
// // {
|
||||||
|
// // plotter->Fill2D("QQQ_CalibW_Vs_PC_Energy_OffTime", 1000, 0, 16, 2000, 0, 30000, eWedgeMeV, pc.e[k], "hCalQQQ");
|
||||||
|
// // plotter->Fill2D("QQQ_CalibR_Vs_PC_Energy_OffTime", 1000, 0, 16, 2000, 0, 30000, eRingMeV, pc.e[k], "hCalQQQ");
|
||||||
|
// // }
|
||||||
|
plotter->Fill2D("Timing_Difference_QQQR_Anode_vRing", 1250, -2500, 2500, 16, 0, 16, tRing - static_cast<double>(pc.t[k]), chRing, "hTiming");
|
||||||
|
plotter->Fill2D("DelT_Vs_QQQRingECal", 500, -2500, 2500, 1000, 0, 10, tRing - static_cast<double>(pc.t[k]), eRingMeV, "hTiming");
|
||||||
|
plotter->Fill2D("CalibratedQQQEvsAnodeE_R", 1000, 0, 10, 2000, 0, 30000, eRingMeV, pc.e[k], "hPCQQQ");
|
||||||
|
plotter->Fill2D("CalibratedQQQEvsAnodeE_W", 1000, 0, 10, 2000, 0, 30000, eWedgeMeV, pc.e[k], "hPCQQQ");
|
||||||
|
if (tRing - static_cast<double>(pc.t[k]) < -150) // 27Al
|
||||||
|
// if (tRing - static_cast<double>(pc.t[k]) < -75 && tRing - static_cast<double>(pc.t[k]) > -145) // 17F
|
||||||
|
{
|
||||||
|
PCQQQTimeCut = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
sx3_contr.CalSX3Pos(sx3ID[0].first, sx3ChUp, sx3ChDn, sx3ChBk, sx3EUp, sx3EDn);
|
if (pc.index[k] >= 24 && pc.e[k] > 50)
|
||||||
hitPos = sx3_contr.GetHitPos();
|
{
|
||||||
HitNonZero = true;
|
plotter->Fill2D("Timing_Difference_QQQR_Cathode_vRing", 1250, -2500, 2500, 16, 0, 16, tRing - static_cast<double>(pc.t[k]), chRing, "hTiming");
|
||||||
// hitPos.Print();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// //======================= QQQ
|
|
||||||
for( int i = 0; i < qqq.multi; i ++){
|
|
||||||
for( int j = i + 1; j < qqq.multi; j++){
|
|
||||||
if( qqq.id[i] == qqq.id[j] ){ // must be same detector
|
|
||||||
int chWedge = -1;
|
|
||||||
int chRing = -1;
|
|
||||||
if( qqq.ch[i] < qqq.ch[j]){
|
|
||||||
chRing = qqq.ch[j] - 16;
|
|
||||||
chWedge = qqq.ch[i];
|
|
||||||
}else{
|
|
||||||
chRing = qqq.ch[i];
|
|
||||||
chWedge = qqq.ch[j] - 16;
|
|
||||||
}
|
|
||||||
|
|
||||||
// printf(" ID : %d , chWedge : %d, chRing : %d \n", qqq.id[i], chWedge, chRing);
|
|
||||||
|
|
||||||
double theta = -TMath::Pi()/2 + 2*TMath::Pi()/16/4.*(qqq.id[i]*16 + chWedge +0.5);
|
|
||||||
double rho = 10.+40./16.*(chRing+0.5);
|
|
||||||
// if(qqq.e[i]>50){
|
|
||||||
hqqqPolar->Fill( theta, rho);
|
|
||||||
// }
|
|
||||||
// qqq.used[i] = true;
|
|
||||||
// qqq.used[j] = true;
|
|
||||||
|
|
||||||
if( !HitNonZero ){
|
|
||||||
double x = rho * TMath::Cos(theta);
|
|
||||||
double y = rho * TMath::Sin(theta);
|
|
||||||
hitPos.SetXYZ(x, y, 23 + 75 + 30);
|
|
||||||
HitNonZero = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
// //======================= PC
|
|
||||||
PCHit_1An hitInfo;
|
|
||||||
|
|
||||||
ID.clear();
|
|
||||||
int counter=0;
|
|
||||||
std::vector<std::pair<int, double>> E;
|
|
||||||
E.clear();
|
|
||||||
|
|
||||||
if( E.size()==3 ){
|
|
||||||
float aE = 0;
|
|
||||||
float cE = 0;
|
|
||||||
bool multi_an =false;
|
|
||||||
for(int l=0;l<E.size();l++){
|
|
||||||
if(E[l].first<24 && E[l].first!=20 && E[l].first!=12){
|
|
||||||
if(!multi_an){
|
|
||||||
aE = E[l].second;
|
|
||||||
}
|
}
|
||||||
multi_an=true;
|
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
cE = E[l].second + cE;
|
double theta = -TMath::Pi() / 2 + 2 * TMath::Pi() / 16 / 4. * (qqq.id[i] * 16 + chWedge + 0.5);
|
||||||
|
double rho = 50. + 50. / 16. * (chRing + 0.5);
|
||||||
|
|
||||||
|
plotter->Fill2D("QQQPolarPlot", 16 * 4, -TMath::Pi(), TMath::Pi(), 32, 40, 100, theta, rho, "hCalQQQ");
|
||||||
|
plotter->Fill2D("QQQCartesianPlot", 200, -100, 100, 200, -100, 100, rho * TMath::Cos(theta), rho * TMath::Sin(theta), "hCalQQQ");
|
||||||
|
plotter->Fill2D("QQQCartesianPlot" + std::to_string(qqq.id[i]), 200, -100, 100, 200, -100, 100, rho * TMath::Cos(theta), rho * TMath::Sin(theta), "hCalQQQ");
|
||||||
|
if (PCQQQTimeCut)
|
||||||
|
{
|
||||||
|
plotter->Fill2D("PC_XY_Projection_QQQ_TimeCut" + std::to_string(qqq.id[i]), 400, -100, 100, 400, -100, 100, rho * TMath::Cos(theta), rho * TMath::Sin(theta), "hPCQQQ");
|
||||||
|
}
|
||||||
|
plotter->Fill2D("PC_XY_Projection_QQQ" + std::to_string(qqq.id[i]), 400, -100, 100, 400, -100, 100, rho * TMath::Cos(theta), rho * TMath::Sin(theta), "hPCQQQ");
|
||||||
|
|
||||||
|
if (!HitNonZero)
|
||||||
|
{
|
||||||
|
double x = rho * TMath::Cos(theta);
|
||||||
|
double y = rho * TMath::Sin(theta);
|
||||||
|
hitPos.SetXYZ(x, y, 23 + 75 + 30);
|
||||||
|
qqqenergy = eRingMeV;
|
||||||
|
qqqtime = tRing;
|
||||||
|
HitNonZero = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// printf("anode= %d, cathode = %d\n", aID, cID);
|
|
||||||
// }
|
|
||||||
if( ID[0].first < 1 ) {
|
|
||||||
aID = pc.ch[ID[0].second];
|
|
||||||
cID = pc.ch[ID[1].second];
|
|
||||||
}else{
|
|
||||||
cID = pc.ch[ID[0].second];
|
|
||||||
aID = pc.ch[ID[1].second];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hanVScatsum->Fill(aE,cE);
|
|
||||||
|
|
||||||
if( HitNonZero){
|
|
||||||
pw_contr.CalTrack3( hitPos, hitinfo, cID);
|
|
||||||
hZProj->Fill(pw_contr.GetZ0());
|
|
||||||
}
|
|
||||||
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
plotter->Fill1D("QQQ_Multiplicity", 10, 0, 10, qqqCount, "hRawQQQ");
|
||||||
|
|
||||||
//########################################################### Track constrcution
|
// PC Gain Matching and Filling
|
||||||
|
double anodeT = -99999;
|
||||||
|
double cathodeT = 99999;
|
||||||
|
int anodeIndex = -1;
|
||||||
|
int cathodeIndex = -1;
|
||||||
|
for (int i = 0; i < pc.multi; i++)
|
||||||
|
{
|
||||||
|
if (pc.e[i] > 10)
|
||||||
|
{
|
||||||
|
plotter->Fill2D("PC_Index_Vs_Energy", 48, 0, 48, 2000, 0, 30000, pc.index[i], static_cast<double>(pc.e[i]), "hRawPC");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pc.index[i] < 48)
|
||||||
|
{
|
||||||
|
pc.e[i] = pcSlope[pc.index[i]] * pc.e[i] + pcIntercept[pc.index[i]];
|
||||||
|
plotter->Fill2D("PC_Index_VS_GainMatched_Energy", 48, 0, 48, 2000, 0, 30000, pc.index[i], pc.e[i], "hGMPC");
|
||||||
|
}
|
||||||
|
|
||||||
//############################## DO THE KINEMATICS
|
if (pc.index[i] < 24)
|
||||||
|
{
|
||||||
|
anodeT = static_cast<double>(pc.t[i]);
|
||||||
|
anodeIndex = pc.index[i];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cathodeT = static_cast<double>(pc.t[i]);
|
||||||
|
cathodeIndex = pc.index[i] - 24;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (anodeT != -99999 && cathodeT != 99999)
|
||||||
|
{
|
||||||
|
for (int j = 0; j < qqq.multi; j++)
|
||||||
|
{
|
||||||
|
plotter->Fill1D("AC_Time_qqq_coin", 500, -2500, 2500, anodeT - cathodeT, "hTiming");
|
||||||
|
// plotter->Fill2D("AC_Time_Vs_QQQ_ch", 500, -2500, 2500, 16 * 8, 0, 16 * 8, anodeT - cathodeT, qqq.ch[j], "hTiming");
|
||||||
|
plotter->Fill2D("AC_Time_vs_AIndex", 500, -2500, 2500, 24, 0, 24, anodeT - cathodeT, anodeIndex, "hTiming");
|
||||||
|
plotter->Fill2D("AC_Time_vs_CIndex", 500, -2500, 2500, 24, 0, 24, anodeT - cathodeT, cathodeIndex, "hTiming");
|
||||||
|
// plotter->Fill1D("AC_Time_A" + std::to_string(anodeIndex) + "_C" + std::to_string(cathodeIndex), 200, -1000, 1000, anodeT - cathodeT, "TimingPC");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int j = 0; j < sx3.multi; j++)
|
||||||
|
{
|
||||||
|
plotter->Fill1D("AC_Time_sx3_coinc", 500, -2500, 2500, anodeT - cathodeT, "hTiming");
|
||||||
|
}
|
||||||
|
|
||||||
|
plotter->Fill1D("AC_Time", 500, -2500, 2500, anodeT - cathodeT, "hTiming");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int j = i + 1; j < pc.multi; j++)
|
||||||
|
{
|
||||||
|
// plotter->Fill2D("PC_Coincidence_Matrix_anodeMinusCathode_lt_-200_" + std::to_string(anodeT - cathodeT < -200), 48, 0, 48, 48, 0, 48, pc.index[i], pc.index[j], "hRawPC");
|
||||||
|
if(pc.e[i]>50 && pc.e[j]>50)
|
||||||
|
plotter->Fill2D("Anode_V_Anode", 24, 0, 24, 24, 0, 24, pc.index[i], pc.index[j], "hRawPC");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
anodeHits.clear();
|
||||||
|
cathodeHits.clear();
|
||||||
|
corrcatMax.clear();
|
||||||
|
|
||||||
|
int aID = 0;
|
||||||
|
int cID = 0;
|
||||||
|
double aE = 0;
|
||||||
|
double cE = 0;
|
||||||
|
double aESum = 0;
|
||||||
|
double cESum = 0;
|
||||||
|
double aEMax = 0;
|
||||||
|
int aIDMax = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < pc.multi; i++)
|
||||||
|
{
|
||||||
|
// if (pc.e[i] > 100)
|
||||||
|
{
|
||||||
|
if (pc.index[i] < 24)
|
||||||
|
anodeHits.push_back(std::pair<int, double>(pc.index[i], pc.e[i]));
|
||||||
|
else if (pc.index[i] >= 24)
|
||||||
|
cathodeHits.push_back(std::pair<int, double>(pc.index[i] - 24, pc.e[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// std::sort(anodeHits.begin(), anodeHits.end(), [](const std::pair<int, double> &a, const std::pair<int, double> &b)
|
||||||
|
// { return a.second > b.second; });
|
||||||
|
// std::sort(cathodeHits.begin(), cathodeHits.end(), [](const std::pair<int, double> &a, const std::pair<int, double> &b)
|
||||||
|
// { return a.second > b.second; });
|
||||||
|
|
||||||
|
if (anodeHits.size() >= 1 && cathodeHits.size() >= 1)
|
||||||
|
{
|
||||||
|
// 2. CRITICAL FIX: Define reference vector 'a'
|
||||||
|
// In Analyzer.cxx, 'a' was left over from the loop. We use the first anode wire as reference here.
|
||||||
|
// (Assuming pwinstance.An is populated and wires are generally parallel).
|
||||||
|
TVector3 refAnode = pwinstance.An[0].first - pwinstance.An[0].second;
|
||||||
|
|
||||||
|
{
|
||||||
|
for (const auto &anode : anodeHits)
|
||||||
|
{
|
||||||
|
aID = anode.first;
|
||||||
|
aE = anode.second;
|
||||||
|
aESum += aE;
|
||||||
|
if (aE > aEMax)
|
||||||
|
{
|
||||||
|
aEMax = aE;
|
||||||
|
aIDMax = aID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto &cathode : cathodeHits)
|
||||||
|
{
|
||||||
|
cID = cathode.first;
|
||||||
|
cE = cathode.second;
|
||||||
|
plotter->Fill2D("AnodeMax_Vs_Cathode_Coincidence_Matrix", 24, 0, 24, 24, 0, 24, aIDMax, cID, "hRawPC");
|
||||||
|
plotter->Fill2D("Anode_Vs_Cathode_Coincidence_Matrix", 24, 0, 24, 24, 0, 24, aID, cID, "hRawPC");
|
||||||
|
plotter->Fill2D("Anode_vs_CathodeE", 2000, 0, 30000, 2000, 0, 30000, aE, cE, "hGMPC");
|
||||||
|
// plotter->Fill2D("CathodeMult_V_CathodeE", 6, 0, 6, 2000, 0, 30000, cathodeHits.size(), cE, "hGMPC");
|
||||||
|
for (int j = -4; j < 3; j++)
|
||||||
|
{
|
||||||
|
if ((aIDMax + 24 + j) % 24 == 23 - cID)
|
||||||
|
{
|
||||||
|
corrcatMax.push_back(std::pair<int, double>(cID, cE));
|
||||||
|
cESum += cE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TVector3 anodeIntersection;
|
||||||
|
anodeIntersection.Clear();
|
||||||
|
if (corrcatMax.size() > 0)
|
||||||
|
{
|
||||||
|
double x = 0, y = 0, z = 0;
|
||||||
|
for (const auto &corr : corrcatMax)
|
||||||
|
{
|
||||||
|
if (Crossover[aIDMax][corr.first][0].z > 9000000)
|
||||||
|
continue;
|
||||||
|
if (cESum > 0)
|
||||||
|
{
|
||||||
|
x += (corr.second) / cESum * Crossover[aIDMax][corr.first][0].x;
|
||||||
|
y += (corr.second) / cESum * Crossover[aIDMax][corr.first][0].y;
|
||||||
|
z += (corr.second) / cESum * Crossover[aIDMax][corr.first][0].z;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (x == 0 && y == 0 && z == 0)
|
||||||
|
;
|
||||||
|
// to ignore events with no valid crossover points
|
||||||
|
else
|
||||||
|
anodeIntersection = TVector3(x, y, z);
|
||||||
|
// std::cout << "Anode Intersection: " << anodeIntersection.X() << ", " << anodeIntersection.Y() << ", " << anodeIntersection.Z() << std::endl;
|
||||||
|
}
|
||||||
|
bool PCQQQPhiCut = false;
|
||||||
|
// flip the algorithm for cathode 1 multi anode events
|
||||||
|
if ((hitPos.Phi() > (anodeIntersection.Phi() - TMath::PiOver4())) && (hitPos.Phi() < (anodeIntersection.Phi() + TMath::PiOver4())))
|
||||||
|
{
|
||||||
|
PCQQQPhiCut = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (double AIz = 20; AIz <= 100; AIz += 5.0)
|
||||||
|
{
|
||||||
|
TVector3 TargetPos(0, 0, AIz);
|
||||||
|
if (PCQQQPhiCut && anodeIntersection.Perp() != 0 && cathodeHits.size() >= 2)
|
||||||
|
// TVector3 anodePosAtZ(anodeIntersection.X() * (AIz / anodeIntersection.Z()), anodeIntersection.Y() * (AIz / anodeIntersection.Z()), AIz);
|
||||||
|
// TVector3 anodePosAtZ(anodeIntersection.X(), anodeIntersection.Y(),anodeIntersection.Z() + AIz);
|
||||||
|
plotter->Fill2D("Inttheta_vs_QQQtheta_TC" + std::to_string(PCQQQTimeCut) + "_TZ" + std::to_string(AIz), 180, 0, 180, 90, 0, 90, (anodeIntersection - TargetPos).Theta() * 180. / TMath::Pi(),
|
||||||
|
(hitPos - TargetPos).Theta() * 180. / TMath::Pi(), "TPosVariation");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (anodeIntersection.Perp() != 0)
|
||||||
|
{
|
||||||
|
plotter->Fill1D("PC_Z_Projection", 600, -300, 300, anodeIntersection.Z(), "hPCzQQQ");
|
||||||
|
plotter->Fill2D("Z_Proj_VsDelTime", 600, -300, 300, 200, -2000, 2000, anodeIntersection.Z(), anodeT - cathodeT, "hPCzQQQ");
|
||||||
|
plotter->Fill2D("IntPhi_vs_QQQphi", 100, -200, 200, 80, -200, 200, anodeIntersection.Phi() * 180. / TMath::Pi(), hitPos.Phi() * 180. / TMath::Pi(), "hPCQQQ");
|
||||||
|
plotter->Fill1D("IntRho", 200, 0, 100, anodeIntersection.Perp(), "hRawPC");
|
||||||
|
plotter->Fill2D("Inttheta_vs_QQQtheta", 90, 0, 180, 20, 0, 45, anodeIntersection.Theta() * 180. / TMath::Pi(), hitPos.Theta() * 180. / TMath::Pi(), "hPCQQQ");
|
||||||
|
plotter->Fill2D("Inttheta_vs_QQQtheta_TC" + std::to_string(PCQQQTimeCut), 90, 0, 180, 20, 0, 45, anodeIntersection.Theta() * 180. / TMath::Pi(), hitPos.Theta() * 180. / TMath::Pi(), "hPCQQQ");
|
||||||
|
plotter->Fill2D("IntPhi_vs_QQQphi_TC" + std::to_string(PCQQQTimeCut) + "PhiC" + std::to_string(PCQQQPhiCut), 100, -200, 200, 80, -200, 200, anodeIntersection.Phi() * 180. / TMath::Pi(), hitPos.Phi() * 180. / TMath::Pi(), "hPCQQQ");
|
||||||
|
}
|
||||||
|
if (anodeIntersection.Perp() != 0 && cathodeHits.size() >= 2)
|
||||||
|
plotter->Fill1D("PC_Z_Projection_TC" + std::to_string(PCQQQTimeCut) + "PhiC" + std::to_string(PCQQQPhiCut), 600, -300, 300, anodeIntersection.Z(), "hPCzQQQ");
|
||||||
|
|
||||||
|
if (anodeIntersection.Perp() != 0 && cathodeHits.size() == 1)
|
||||||
|
{
|
||||||
|
plotter->Fill1D("PC_Z_proj_1C", 600, -300, 300, anodeIntersection.Z(), "hPCzQQQ");
|
||||||
|
plotter->Fill2D("IntersectionPhi_vs_AnodeZ_1C", 400, -200, 200, 600, -300, 300, anodeIntersection.Phi() * 180. / TMath::Pi(), anodeIntersection.Z(), "hPCzQQQ");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (anodeIntersection.Perp() != 0 && cathodeHits.size() == 2)
|
||||||
|
{
|
||||||
|
plotter->Fill1D("PC_Z_proj_2C", 600, -300, 300, anodeIntersection.Z(), "hPCzQQQ");
|
||||||
|
plotter->Fill2D("IntersectionPhi_vs_AnodeZ_2C", 400, -200, 200, 600, -300, 300, anodeIntersection.Phi() * 180. / TMath::Pi(), anodeIntersection.Z(), "hPCzQQQ");
|
||||||
|
}
|
||||||
|
if (anodeIntersection.Perp() != 0 && cathodeHits.size() > 2)
|
||||||
|
{
|
||||||
|
plotter->Fill1D("PC_Z_proj_nC", 600, -300, 300, anodeIntersection.Z(), "hPCzQQQ");
|
||||||
|
plotter->Fill2D("IntersectionPhi_vs_AnodeZ_nC", 400, -200, 200, 600, -300, 300, anodeIntersection.Phi() * 180. / TMath::Pi(), anodeIntersection.Z(), "hPCzQQQ");
|
||||||
|
}
|
||||||
|
if (anodeHits.size() > 0 && cathodeHits.size() > 0)
|
||||||
|
plotter->Fill2D("AHits_vs_CHits", 12, 0, 11, 6, 0, 5, anodeHits.size(), cathodeHits.size(), "hRawPC");
|
||||||
|
|
||||||
|
// make another plot with nearest neighbour constraint
|
||||||
|
bool hasNeighbourAnodes = false;
|
||||||
|
bool hasNeighbourCathodes = false;
|
||||||
|
|
||||||
|
// 1. Check Anodes for neighbours (including wrap-around 0-23)
|
||||||
|
for (size_t i = 0; i < anodeHits.size(); i++)
|
||||||
|
{
|
||||||
|
for (size_t j = i + 1; j < anodeHits.size(); j++)
|
||||||
|
{
|
||||||
|
int diff = std::abs(anodeHits[i].first - anodeHits[j].first);
|
||||||
|
if (diff == 1 || diff == 23)
|
||||||
|
{ // 23 handles the cylindrical wrap
|
||||||
|
hasNeighbourAnodes = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (hasNeighbourAnodes)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Check Cathodes for neighbours (including wrap-around 0-23)
|
||||||
|
for (size_t i = 0; i < cathodeHits.size(); i++)
|
||||||
|
{
|
||||||
|
for (size_t j = i + 1; j < cathodeHits.size(); j++)
|
||||||
|
{
|
||||||
|
int diff = std::abs(cathodeHits[i].first - cathodeHits[j].first);
|
||||||
|
if (diff == 1 || diff == 23)
|
||||||
|
{
|
||||||
|
hasNeighbourCathodes = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (hasNeighbourCathodes)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------
|
||||||
|
// FILL PLOTS
|
||||||
|
// ---------------------------------------------------------
|
||||||
|
if (anodeHits.size() > 0 && cathodeHits.size() > 0)
|
||||||
|
{
|
||||||
|
// plotter->Fill2D("AHits_vs_CHits_NA" + std::to_string(hasNeighbourAnodes), 12, 0, 11, 6, 0, 5, anodeHits.size(), cathodeHits.size(), "hRawPC");
|
||||||
|
// plotter->Fill2D("AHits_vs_CHits_NC" + std::to_string(hasNeighbourCathodes), 12, 0, 11, 6, 0, 5, anodeHits.size(), cathodeHits.size(), "hRawPC");
|
||||||
|
|
||||||
|
// Constraint Plot: Only fill if BOTH planes have adjacent hits
|
||||||
|
// This effectively removes events with only isolated single-wire hits (noise)
|
||||||
|
if (hasNeighbourAnodes && hasNeighbourCathodes)
|
||||||
|
{
|
||||||
|
plotter->Fill2D("AHits_vs_CHits_NN", 12, 0, 11, 6, 0, 5, anodeHits.size(), cathodeHits.size(), "hRawPC");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (HitNonZero && anodeIntersection.Z() != 0)
|
||||||
|
{
|
||||||
|
pw_contr.CalTrack2(hitPos, anodeIntersection);
|
||||||
|
plotter->Fill1D("VertexRecon", 600, -300, 300, pw_contr.GetZ0());
|
||||||
|
|
||||||
|
if (PCQQQPhiCut && PCQQQTimeCut)
|
||||||
|
{
|
||||||
|
if (cathodeHits.size() == 2)
|
||||||
|
plotter->Fill1D("VertexRecon_TC_PhiC_2C", 600, -300, 300, pw_contr.GetZ0());
|
||||||
|
}
|
||||||
|
plotter->Fill1D("VertexRecon_TC" + std::to_string(PCQQQTimeCut) + "_PhiC" + std::to_string(PCQQQPhiCut), 600, -300, 300, pw_contr.GetZ0());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < qqq.multi; i++)
|
||||||
|
{
|
||||||
|
if (PCQQQTimeCut)
|
||||||
|
{
|
||||||
|
plotter->Fill2D("PC_XY_Projection_QQQ_TimeCut" + std::to_string(qqq.id[i]), 400, -100, 100, 400, -100, 100, anodeIntersection.X(), anodeIntersection.Y(), "hPCQQQ");
|
||||||
|
}
|
||||||
|
plotter->Fill2D("PC_XY_Projection_QQQ" + std::to_string(qqq.id[i]), 400, -100, 100, 400, -100, 100, anodeIntersection.X(), anodeIntersection.Y(), "hPCQQQ");
|
||||||
|
|
||||||
|
for (int j = i + 1; j < qqq.multi; j++)
|
||||||
|
{
|
||||||
|
if (qqq.id[i] == qqq.id[j])
|
||||||
|
{
|
||||||
|
int chWedge = -1;
|
||||||
|
int chRing = -1;
|
||||||
|
double eWedge = 0.0;
|
||||||
|
double eWedgeMeV = 0.0;
|
||||||
|
double eRing = 0.0;
|
||||||
|
double eRingMeV = 0.0;
|
||||||
|
double tRing = 0.0;
|
||||||
|
int qqqID = -1;
|
||||||
|
if (qqq.ch[i] < 16 && qqq.ch[j] >= 16 && qqqGainValid[qqq.id[i]][qqq.ch[i]][qqq.ch[j] - 16])
|
||||||
|
{
|
||||||
|
chWedge = qqq.ch[i];
|
||||||
|
eWedge = qqq.e[i] * qqqGain[qqq.id[i]][qqq.ch[i]][qqq.ch[j] - 16];
|
||||||
|
chRing = qqq.ch[j] - 16;
|
||||||
|
eRing = qqq.e[j];
|
||||||
|
tRing = static_cast<double>(qqq.t[j]);
|
||||||
|
qqqID = qqq.id[i];
|
||||||
|
}
|
||||||
|
else if (qqq.ch[j] < 16 && qqq.ch[i] >= 16 && qqqGainValid[qqq.id[j]][qqq.ch[j]][qqq.ch[i] - 16])
|
||||||
|
{
|
||||||
|
chWedge = qqq.ch[j];
|
||||||
|
eWedge = qqq.e[j] * qqqGain[qqq.id[j]][qqq.ch[j]][qqq.ch[i] - 16];
|
||||||
|
chRing = qqq.ch[i] - 16;
|
||||||
|
tRing = static_cast<double>(qqq.t[i]);
|
||||||
|
eRing = qqq.e[i];
|
||||||
|
qqqID = qqq.id[i];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (qqqCalibValid[qqq.id[i]][chRing][chWedge])
|
||||||
|
{
|
||||||
|
eWedgeMeV = eWedge * qqqCalib[qqq.id[i]][chRing][chWedge] / 1000;
|
||||||
|
eRingMeV = eRing * qqqCalib[qqq.id[i]][chRing][chWedge] / 1000;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// if (anodeIntersection.Z() != 0)
|
||||||
|
{
|
||||||
|
plotter->Fill2D("PC_Z_vs_QQQRing", 600, -300, 300, 16, 0, 16, anodeIntersection.Z(), chRing, "hPCzQQQ");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (anodeIntersection.Z() != 0 && cathodeHits.size() == 2)
|
||||||
|
{
|
||||||
|
plotter->Fill2D("PC_Z_vs_QQQRing_2C", 600, -300, 300, 16, 0, 16, anodeIntersection.Z(), chRing, "hPCzQQQ");
|
||||||
|
plotter->Fill2D("PC_Z_vs_QQQRing_2C" + std::to_string(qqq.id[i]), 600, -300, 300, 16, 0, 16, anodeIntersection.Z(), chRing, "hPCzQQQ");
|
||||||
|
plotter->Fill2D("PC_Z_vs_QQQWedge_2C", 600, -300, 300, 16, 0, 16, anodeIntersection.Z(), chWedge, "hPCzQQQ");
|
||||||
|
}
|
||||||
|
plotter->Fill2D("Vertex_V_QQQRing", 600, -300, 300, 16, 0, 16, pw_contr.GetZ0(), chRing, "hPCQQQ");
|
||||||
|
double phi = TMath::ATan2(anodeIntersection.Y(), anodeIntersection.X()) * 180. / TMath::Pi();
|
||||||
|
// while (phi > 180)
|
||||||
|
// phi -= 180;
|
||||||
|
// while (phi < -180)
|
||||||
|
// phi += 180;
|
||||||
|
plotter->Fill2D("PolarAngle_Vs_QQQWedge" + std::to_string(qqqID), 360, -360, 360, 16, 0, 16, phi, chWedge, "hPCQQQ");
|
||||||
|
// plotter->Fill2D("EdE_PC_vs_QQQ_timegate_ls1000"+std::to_string())
|
||||||
|
|
||||||
|
plotter->Fill2D("PC_Z_vs_QQQRing_Det" + std::to_string(qqqID), 600, -300, 300, 16, 0, 16, anodeIntersection.Z(), chRing, "hPCQQQ");
|
||||||
|
for (int k = 0; k < pc.multi; k++)
|
||||||
|
{
|
||||||
|
if (pc.index[k] >= 24)
|
||||||
|
continue;
|
||||||
|
plotter->Fill2D("CalibratedQQQE_RvsAnodeE_TC" + std::to_string(PCQQQTimeCut) + "PhiC" + std::to_string(PCQQQPhiCut), 1000, 0, 10, 2000, 0, 30000, eRingMeV, pc.e[k], "hPCQQQ");
|
||||||
|
plotter->Fill2D("CalibratedQQQE_WvsAnodeE_TC" + std::to_string(PCQQQTimeCut) + "PhiC" + std::to_string(PCQQQPhiCut), 1000, 0, 10, 2000, 0, 30000, eWedgeMeV, pc.e[k], "hPCQQQ");
|
||||||
|
plotter->Fill2D("AnodeQQQ_dTimevsdPhi", 200, -2000, 2000, 80, -200, 200, tRing - static_cast<double>(pc.t[k]), (hitPos.Phi() - anodeIntersection.Phi()) * 180. / TMath::Pi(), "hTiming");
|
||||||
|
plotter->Fill1D("AnodeQQQ_Time", 200, -2000, 2000, tRing - static_cast<double>(pc.t[k]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TVector3 guessVertex(0, 0, 90.);
|
||||||
|
// rho=40.0 mm is halfway between the cathodes(rho=42) and anodes(rho=37)
|
||||||
|
double pcz_guess = 42.0 / TMath::Tan((hitPos - guessVertex).Theta()) + guessVertex.Z(); // this is ideally kept to be all QQQ+userinput for calibration of pcz
|
||||||
|
if (PCQQQTimeCut && PCQQQPhiCut && hitPos.Perp() > 0 && anodeIntersection.Perp() > 0 && cathodeHits.size() >= 2)
|
||||||
|
{
|
||||||
|
plotter->Fill2D("pczguess_vs_qqqE", 100, 0, 200, 800, 0, 20, pcz_guess, qqqenergy, "pczguess");
|
||||||
|
// plotter->Fill2D("pczguess_vs_pcz_rad="+std::to_string(hitPos.Perp()),100,0,200,150,0,200,pcz_guess,anodeIntersection.Z(),"pczguess"); //entirely qqq-derived position vs entirely PC derived position
|
||||||
|
plotter->Fill2D("pczguess_vs_pcz_phi=" + std::to_string(hitPos.Phi() * 180. / M_PI), 100, 0, 200, 150, 0, 200, pcz_guess, anodeIntersection.Z() / 0.8, "pczguess"); // entirely qqq-derived position vs entirely PC derived position
|
||||||
|
plotter->Fill2D("pczguess_vs_pcz", 100, 0, 200, 150, 0, 200, pcz_guess, anodeIntersection.Z() / 0.8);
|
||||||
|
plotter->Fill2D("pcz_vs_pcPhi_rad=" + std::to_string(hitPos.Perp()), 360, 0, 360, 150, 0, 200, anodeIntersection.Phi() * 180. / M_PI, anodeIntersection.Z() / 0.8, "pczguess");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < sx3.multi; i++)
|
||||||
|
{
|
||||||
|
// plotting sx3 strip hits vs anode phi
|
||||||
|
if (sx3.ch[i] < 8)
|
||||||
|
plotter->Fill2D("AnodePhi_vs_SX3Strip", 100, -200, 200, 8 * 24, 0, 8 * 24, anodeIntersection.Phi() * 180. / TMath::Pi(), sx3.id[i] * 8 + sx3.ch[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (anodeIntersection.Z() != 0 && cathodeHits.size() == 3)
|
||||||
|
{
|
||||||
|
plotter->Fill1D("PC_Z_proj_3C", 600, -300, 300, anodeIntersection.Z(), "hPCzQQQ");
|
||||||
|
}
|
||||||
|
|
||||||
|
plotter->Fill2D("AnodeMaxE_Vs_Cathode_Sum_Energy", 2000, 0, 30000, 2000, 0, 30000, aEMax, cESum, "hGMPC");
|
||||||
|
plotter->Fill1D("Correlated_Cathode_MaxAnode", 6, 0, 5, corrcatMax.size(), "hGMPC");
|
||||||
|
plotter->Fill2D("Correlated_Cathode_VS_MaxAnodeEnergy", 6, 0, 5, 2000, 0, 30000, corrcatMax.size(), aEMax, "hGMPC");
|
||||||
|
plotter->Fill1D("AnodeHits", 12, 0, 11, anodeHits.size(), "hGMPC");
|
||||||
|
plotter->Fill2D("AnodeMaxE_vs_AnodeHits", 12, 0, 11, 2000, 0, 30000, anodeHits.size(), aEMax, "hGMPC");
|
||||||
|
|
||||||
|
if (anodeHits.size() < 1)
|
||||||
|
{
|
||||||
|
plotter->Fill1D("NoAnodeHits_CathodeHits", 6, 0, 5, cathodeHits.size(), "hGMPC");
|
||||||
|
}
|
||||||
|
|
||||||
return kTRUE;
|
return kTRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Analyzer::Terminate(){
|
void TrackRecon::Terminate()
|
||||||
|
{
|
||||||
gStyle->SetOptStat("neiou");
|
plotter->FlushToDisk();
|
||||||
TCanvas * canvas = new TCanvas("cANASEN", "ANASEN", 2000, 2000);
|
}
|
||||||
canvas->Divide(3,3);
|
|
||||||
|
|
||||||
//hsx3VpcIndex->Draw("colz");
|
|
||||||
|
|
||||||
//=============================================== pad-1
|
|
||||||
padID ++; canvas->cd(padID); canvas->cd(padID)->SetGrid(1);
|
|
||||||
|
|
||||||
hsx3IndexVE->Draw("colz");
|
|
||||||
|
|
||||||
//=============================================== pad-2
|
|
||||||
padID ++; canvas->cd(padID); canvas->cd(padID)->SetGrid(1);
|
|
||||||
|
|
||||||
hqqqIndexVE->Draw("colz");
|
|
||||||
|
|
||||||
//=============================================== pad-3
|
|
||||||
padID ++; canvas->cd(padID); canvas->cd(padID)->SetGrid(1);
|
|
||||||
|
|
||||||
hpcIndexVE->Draw("colz");
|
|
||||||
|
|
||||||
//=============================================== pad-4
|
|
||||||
padID ++; canvas->cd(padID); canvas->cd(padID)->SetGrid(1);
|
|
||||||
|
|
||||||
hsx3Coin->Draw("colz");
|
|
||||||
|
|
||||||
//=============================================== pad-5
|
|
||||||
padID ++; canvas->cd(padID); canvas->cd(padID)->SetGrid(1);
|
|
||||||
|
|
||||||
hqqqCoin->Draw("colz");
|
|
||||||
|
|
||||||
//=============================================== pad-6
|
|
||||||
padID ++; canvas->cd(padID); canvas->cd(padID)->SetGrid(1);
|
|
||||||
|
|
||||||
hpcCoin->Draw("colz");
|
|
||||||
|
|
||||||
//=============================================== pad-7
|
|
||||||
padID ++; canvas->cd(padID); canvas->cd(padID)->SetGrid(1);
|
|
||||||
|
|
||||||
hsx3VpcIndex ->Draw("colz");
|
|
||||||
// hsx3VpcE->Draw("colz") ;
|
|
||||||
|
|
||||||
//=============================================== pad-8
|
|
||||||
padID ++; canvas->cd(padID); canvas->cd(padID)->SetGrid(1);
|
|
||||||
|
|
||||||
hqqqVpcIndex ->Draw("colz");
|
|
||||||
|
|
||||||
// hqqqVpcE ->Draw("colz");
|
|
||||||
//=============================================== pad-9
|
|
||||||
padID ++;
|
|
||||||
|
|
||||||
// canvas->cd(padID)->DrawFrame(-50, -50, 50, 50);
|
|
||||||
// hqqqPolar->Draw("same colz pol");
|
|
||||||
|
|
||||||
canvas->cd(padID); canvas->cd(padID)->SetGrid(1);
|
|
||||||
hZProj->Draw();
|
|
||||||
// hanVScatsum->Draw("colz");
|
|
||||||
|
|
||||||
}
|
|
||||||
742
TrackRecon.C.backup
Normal file
742
TrackRecon.C.backup
Normal file
|
|
@ -0,0 +1,742 @@
|
||||||
|
#define TrackRecon_cxx
|
||||||
|
|
||||||
|
#include "TrackRecon.h"
|
||||||
|
#include "Armory/ClassPW.h"
|
||||||
|
#include "Armory/HistPlotter.h"
|
||||||
|
|
||||||
|
#include <TH2.h>
|
||||||
|
#include <TStyle.h>
|
||||||
|
#include <TCanvas.h>
|
||||||
|
#include <TMath.h>
|
||||||
|
#include <TBranch.h>
|
||||||
|
#include "TVector3.h"
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
#include <iostream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <map>
|
||||||
|
#include <utility>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
|
// Global instances
|
||||||
|
PW pw_contr;
|
||||||
|
PW pwinstance;
|
||||||
|
TVector3 hitPos;
|
||||||
|
|
||||||
|
struct Event {
|
||||||
|
TVector3 pos;
|
||||||
|
double Energy1=-1; //Front for QQQ, Anode for PC
|
||||||
|
double Energy2=-1; //Back for QQQ, Cathode for PC
|
||||||
|
double Time1=-1;
|
||||||
|
double Time2=-1;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Calibration globals
|
||||||
|
const int MAX_QQQ = 4;
|
||||||
|
const int MAX_RING = 16;
|
||||||
|
const int MAX_WEDGE = 16;
|
||||||
|
double qqqGain[MAX_QQQ][MAX_RING][MAX_WEDGE] = {{{0}}};
|
||||||
|
bool qqqGainValid[MAX_QQQ][MAX_RING][MAX_WEDGE] = {{{false}}};
|
||||||
|
double qqqCalib[MAX_QQQ][MAX_RING][MAX_WEDGE] = {{{0}}};
|
||||||
|
bool qqqCalibValid[MAX_QQQ][MAX_RING][MAX_WEDGE] = {{{false}}};
|
||||||
|
// TCutg *cutQQQ;
|
||||||
|
|
||||||
|
// PC Arrays
|
||||||
|
double pcSlope[48];
|
||||||
|
double pcIntercept[48];
|
||||||
|
|
||||||
|
HistPlotter *plotter;
|
||||||
|
|
||||||
|
bool HitNonZero;
|
||||||
|
bool sx3ecut;
|
||||||
|
bool qqqEcut;
|
||||||
|
|
||||||
|
void TrackRecon::Begin(TTree * /*tree*/)
|
||||||
|
{
|
||||||
|
TString option = GetOption();
|
||||||
|
plotter = new HistPlotter("Analyzer_QQQ.root", "TFILE");
|
||||||
|
|
||||||
|
pw_contr.ConstructGeo();
|
||||||
|
pwinstance.ConstructGeo();
|
||||||
|
|
||||||
|
// ---------------------------------------------------------
|
||||||
|
// 1. CRITICAL FIX: Initialize PC Arrays to Default (Raw)
|
||||||
|
// ---------------------------------------------------------
|
||||||
|
for (int i = 0; i < 48; i++)
|
||||||
|
{
|
||||||
|
pcSlope[i] = 1.0; // Default slope = 1 (preserves Raw energy)
|
||||||
|
pcIntercept[i] = 0.0; // Default intercept = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
// Calculate Crossover Geometry ONCE
|
||||||
|
TVector3 a, c, diff;
|
||||||
|
double a2, ac, c2, adiff, cdiff, denom, alpha;
|
||||||
|
|
||||||
|
for (size_t i = 0; i < pwinstance.An.size(); i++)
|
||||||
|
{
|
||||||
|
a = pwinstance.An[i].first - pwinstance.An[i].second;
|
||||||
|
|
||||||
|
for (size_t j = 0; j < pwinstance.Ca.size(); j++)
|
||||||
|
{
|
||||||
|
c = pwinstance.Ca[j].first - pwinstance.Ca[j].second;
|
||||||
|
diff = pwinstance.An[i].first - pwinstance.Ca[j].first;
|
||||||
|
a2 = a.Dot(a);
|
||||||
|
c2 = c.Dot(c);
|
||||||
|
ac = a.Dot(c);
|
||||||
|
adiff = a.Dot(diff);
|
||||||
|
cdiff = c.Dot(diff);
|
||||||
|
denom = a2 * c2 - ac * ac;
|
||||||
|
alpha = (ac * cdiff - c2 * adiff) / denom;
|
||||||
|
|
||||||
|
Crossover[i][j][0].x = pwinstance.An[i].first.X() + alpha * a.X();
|
||||||
|
Crossover[i][j][0].y = pwinstance.An[i].first.Y() + alpha * a.Y();
|
||||||
|
Crossover[i][j][0].z = pwinstance.An[i].first.Z() + alpha * a.Z();
|
||||||
|
|
||||||
|
if (Crossover[i][j][0].z < -190 || Crossover[i][j][0].z > 190 || (i+j)%24 == 12)
|
||||||
|
{
|
||||||
|
Crossover[i][j][0].z = 9999999;
|
||||||
|
}
|
||||||
|
|
||||||
|
Crossover[i][j][1].x = alpha;
|
||||||
|
Crossover[i][j][1].y = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load PC Calibrations
|
||||||
|
std::ifstream inputFile("slope_intercept_results.txt");
|
||||||
|
if (inputFile.is_open())
|
||||||
|
{
|
||||||
|
std::string line;
|
||||||
|
int index;
|
||||||
|
double slope, intercept;
|
||||||
|
while (std::getline(inputFile, line))
|
||||||
|
{
|
||||||
|
std::stringstream ss(line);
|
||||||
|
ss >> index >> slope >> intercept;
|
||||||
|
if (index >= 0 && index <= 47)
|
||||||
|
{
|
||||||
|
pcSlope[index] = slope;
|
||||||
|
pcIntercept[index] = intercept;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inputFile.close();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
std::cerr << "Error opening slope_intercept.txt" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load QQQ Cuts from file
|
||||||
|
// {
|
||||||
|
// std::string filename = "QQQ_PCCut.root";
|
||||||
|
// TFile *cutFile = TFile::Open(filename.c_str(), "READ");
|
||||||
|
// if (cutFile && !cutFile->IsZombie())
|
||||||
|
// {
|
||||||
|
// cutQQQ = (TCutg *)cutFile->Get("cutQQQPC");
|
||||||
|
// if (cutQQQ)
|
||||||
|
// {
|
||||||
|
// std::cout << "Loaded QQQ PC cut from " << filename << std::endl;
|
||||||
|
// }
|
||||||
|
// else
|
||||||
|
// {
|
||||||
|
// std::cerr << "Error: cutQQQPC not found in " << filename << std::endl;
|
||||||
|
// }
|
||||||
|
// cutFile->Close();
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// ... (Load QQQ Gains and Calibs - same as before) ...
|
||||||
|
{
|
||||||
|
std::string filename = "qqq_GainMatch.dat";
|
||||||
|
std::ifstream infile(filename);
|
||||||
|
if (infile.is_open())
|
||||||
|
{
|
||||||
|
int det, ring, wedge;
|
||||||
|
double gainw, gainr;
|
||||||
|
while (infile >> det >> wedge >> ring >> gainw >> gainr)
|
||||||
|
{
|
||||||
|
qqqGain[det][wedge][ring] = gainw;
|
||||||
|
qqqGainValid[det][wedge][ring] = (gainw > 0);
|
||||||
|
// std::cout << "QQQ Gain Loaded: Det " << det << " Ring " << ring << " Wedge " << wedge << " GainW " << gainw << " GainR " << gainr << std::endl;
|
||||||
|
}
|
||||||
|
infile.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
std::string filename = "qqq_Calib.dat";
|
||||||
|
std::ifstream infile(filename);
|
||||||
|
if (infile.is_open())
|
||||||
|
{
|
||||||
|
int det, ring, wedge;
|
||||||
|
double slope;
|
||||||
|
while (infile >> det >> wedge >> ring >> slope)
|
||||||
|
{
|
||||||
|
qqqCalib[det][wedge][ring] = slope;
|
||||||
|
qqqCalibValid[det][wedge][ring] = (slope > 0);
|
||||||
|
// std::cout << "QQQ Calib Loaded: Det " << det << " Ring " << ring << " Wedge " << wedge << " Slope " << slope << std::endl;
|
||||||
|
}
|
||||||
|
infile.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Bool_t TrackRecon::Process(Long64_t entry)
|
||||||
|
{
|
||||||
|
hitPos.Clear();
|
||||||
|
HitNonZero = false;
|
||||||
|
bool qqq1000cut = false;
|
||||||
|
b_sx3Multi->GetEntry(entry);
|
||||||
|
b_sx3ID->GetEntry(entry);
|
||||||
|
b_sx3Ch->GetEntry(entry);
|
||||||
|
b_sx3E->GetEntry(entry);
|
||||||
|
b_sx3T->GetEntry(entry);
|
||||||
|
b_qqqMulti->GetEntry(entry);
|
||||||
|
b_qqqID->GetEntry(entry);
|
||||||
|
b_qqqCh->GetEntry(entry);
|
||||||
|
b_qqqE->GetEntry(entry);
|
||||||
|
b_qqqT->GetEntry(entry);
|
||||||
|
b_pcMulti->GetEntry(entry);
|
||||||
|
b_pcID->GetEntry(entry);
|
||||||
|
b_pcCh->GetEntry(entry);
|
||||||
|
b_pcE->GetEntry(entry);
|
||||||
|
b_pcT->GetEntry(entry);
|
||||||
|
|
||||||
|
sx3.CalIndex();
|
||||||
|
qqq.CalIndex();
|
||||||
|
pc.CalIndex();
|
||||||
|
|
||||||
|
// QQQ Processing
|
||||||
|
|
||||||
|
int qqqCount = 0;
|
||||||
|
int qqqAdjCh = 0;
|
||||||
|
// REMOVE WHEN RERUNNING USING THE NEW CALIBRATION FILE
|
||||||
|
for (int i = 0; i < qqq.multi; i++)
|
||||||
|
{
|
||||||
|
if ((qqq.id[i] == 3 || qqq.id[i] == 1) && qqq.ch[i] < 16)
|
||||||
|
{
|
||||||
|
qqq.ch[i] = 16 - qqq.ch[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int i = 0; i < qqq.multi; i++)
|
||||||
|
{
|
||||||
|
if (qqq.id[i] == 0 && qqq.ch[i] >= 16)
|
||||||
|
{
|
||||||
|
qqq.ch[i] = 31 - qqq.ch[i] + 16;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
std::vector<Event> QQQ_Events, PC_Events;
|
||||||
|
std::vector<Event> QQQ_Events_Raw, PC_Events_Raw;
|
||||||
|
|
||||||
|
|
||||||
|
bool PCQQQTimeCut = false;
|
||||||
|
for (int i = 0; i < qqq.multi; i++)
|
||||||
|
{
|
||||||
|
|
||||||
|
plotter->Fill2D("QQQ_Index_Vs_Energy", 16 * 8, 0, 16 * 8, 2000, 0, 16000, qqq.index[i], qqq.e[i], "hRawQQQ");
|
||||||
|
|
||||||
|
for (int j = 0; j < qqq.multi; j++)
|
||||||
|
{
|
||||||
|
if (j == i)
|
||||||
|
continue;
|
||||||
|
plotter->Fill2D("QQQ_Coincidence_Matrix", 16 * 8, 0, 16 * 8, 16 * 8, 0, 16 * 8, qqq.index[i], qqq.index[j], "hRawQQQ");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int k = 0; k < pc.multi; k++)
|
||||||
|
{
|
||||||
|
if (pc.index[k] < 24 && pc.e[k] > 50)
|
||||||
|
{
|
||||||
|
plotter->Fill2D("QQQ_Vs_Anode_Energy", 400, 0, 4000, 1000, 0, 16000, qqq.e[i], pc.e[k], "hRawQQQ");
|
||||||
|
plotter->Fill2D("QQQ_Vs_PC_Index", 16 * 8, 0, 16 * 8, 24, 0, 24, qqq.index[i], pc.index[k], "hRawQQQ");
|
||||||
|
}
|
||||||
|
else if (pc.index[k] >= 24 && pc.e[k] > 50)
|
||||||
|
{
|
||||||
|
plotter->Fill2D("QQQ_Vs_Cathode_Energy", 400, 0, 4000, 1000, 0, 16000, qqq.e[i], pc.e[k], "hRawQQQ");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int j = i + 1; j < qqq.multi; j++)
|
||||||
|
{
|
||||||
|
if (qqq.id[i] == qqq.id[j])
|
||||||
|
{
|
||||||
|
qqqCount++;
|
||||||
|
|
||||||
|
int chWedge = -1;
|
||||||
|
int chRing = -1;
|
||||||
|
double eWedge = 0.0;
|
||||||
|
double eWedgeMeV = 0.0;
|
||||||
|
double eRing = 0.0;
|
||||||
|
double eRingMeV = 0.0;
|
||||||
|
double tRing = 0.0;
|
||||||
|
double tWedge = 0.0;
|
||||||
|
|
||||||
|
if (qqq.ch[i] < 16 && qqq.ch[j] >= 16 && qqqGainValid[qqq.id[i]][qqq.ch[i]][qqq.ch[j] - 16])
|
||||||
|
{
|
||||||
|
chWedge = qqq.ch[i];
|
||||||
|
eWedge = qqq.e[i] * qqqGain[qqq.id[i]][qqq.ch[i]][qqq.ch[j] - 16];
|
||||||
|
chRing = qqq.ch[j] - 16;
|
||||||
|
eRing = qqq.e[j];
|
||||||
|
tRing = static_cast<double>(qqq.t[j]);
|
||||||
|
tWedge = static_cast<double>(qqq.t[i]);
|
||||||
|
}
|
||||||
|
else if (qqq.ch[j] < 16 && qqq.ch[i] >= 16 && qqqGainValid[qqq.id[j]][qqq.ch[j]][qqq.ch[i] - 16])
|
||||||
|
{
|
||||||
|
chWedge = qqq.ch[j];
|
||||||
|
eWedge = qqq.e[j] * qqqGain[qqq.id[j]][qqq.ch[j]][qqq.ch[i] - 16];
|
||||||
|
chRing = qqq.ch[i] - 16;
|
||||||
|
eRing = qqq.e[i];
|
||||||
|
tRing = static_cast<double>(qqq.t[i]);
|
||||||
|
tWedge = static_cast<double>(qqq.t[j]);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
continue;
|
||||||
|
|
||||||
|
plotter->Fill1D("Wedgetime_Vs_Ringtime", 100, -1000, 1000, tWedge - tRing, "hTiming");
|
||||||
|
plotter->Fill2D("RingE_vs_Index", 16 * 4, 0, 16 * 4, 1000, 0, 16000, chRing + qqq.id[i] * 16, eRing, "hRawQQQ");
|
||||||
|
plotter->Fill2D("WedgeE_vs_Index", 16 * 4, 0, 16 * 4, 1000, 0, 16000, chWedge + qqq.id[i] * 16, eWedge, "hRawQQQ");
|
||||||
|
|
||||||
|
if (qqqCalibValid[qqq.id[i]][chWedge][chRing])
|
||||||
|
{
|
||||||
|
eWedgeMeV = eWedge * qqqCalib[qqq.id[i]][chWedge][chRing] / 1000;
|
||||||
|
eRingMeV = eRing * qqqCalib[qqq.id[i]][chWedge][chRing] / 1000;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
continue;
|
||||||
|
|
||||||
|
plotter->Fill2D("WedgeE_Vs_RingECal", 1000, 0, 10, 1000, 0, 10, eWedgeMeV, eRingMeV, "hCalQQQ");
|
||||||
|
|
||||||
|
for (int k = 0; k < pc.multi; k++)
|
||||||
|
{
|
||||||
|
plotter->Fill2D("RingCh_vs_Anode_Index", 16 * 4, 0, 16 * 4, 24, 0, 24, chRing + qqq.id[i] * 16, pc.index[k], "hRawQQQ");
|
||||||
|
plotter->Fill2D("WedgeCh_vs_Anode_Index", 16 * 4, 0, 16 * 4, 24, 0, 24, chWedge + qqq.id[i] * 16, pc.index[k], "hRawQQQ");
|
||||||
|
plotter->Fill2D("WedgeCh_vs_Anode_Index" + std::to_string(qqq.id[i]), 16 * 4, 0, 16 * 4, 24, 0, 24, chWedge + qqq.id[i] * 16, pc.index[k]);
|
||||||
|
plotter->Fill2D("RingCh_vs_Cathode_Index", 16 * 4, 0, 16 * 4, 24, 24, 48, chRing + qqq.id[i] * 16, pc.index[k], "hRawQQQ");
|
||||||
|
plotter->Fill2D("WedgeCh_vs_Cathode_Index", 16 * 4, 0, 16 * 4, 24, 24, 48, chWedge + qqq.id[i] * 16, pc.index[k], "hRawQQQ");
|
||||||
|
|
||||||
|
if (pc.index[k] < 24 && pc.e[k] > 50)
|
||||||
|
{
|
||||||
|
// plotter->Fill2D("QQQ_CalibW_Vs_PC_Energy", 1000, 0, 16, 2000, 0, 30000, eWedgeMeV, pc.e[k], "hCalQQQ");
|
||||||
|
// plotter->Fill2D("QQQ_CalibR_Vs_PC_Energy", 1000, 0, 16, 2000, 0, 30000, eRingMeV, pc.e[k], "hCalQQQ");
|
||||||
|
|
||||||
|
// if (tRing - static_cast<double>(pc.t[k]) < 0 && tRing - static_cast<double>(pc.t[k]) > -600)
|
||||||
|
// // {
|
||||||
|
// // plotter->Fill2D("QQQ_CalibW_Vs_PC_Energy_Tight", 1000, 0, 16, 2000, 0, 30000, eWedgeMeV, pc.e[k], "hCalQQQ");
|
||||||
|
// // plotter->Fill2D("QQQ_CalibR_Vs_PC_Energy_Tight", 1000, 0, 16, 2000, 0, 30000, eRingMeV, pc.e[k], "hCalQQQ");
|
||||||
|
// // }
|
||||||
|
// // else
|
||||||
|
// // {
|
||||||
|
// // plotter->Fill2D("QQQ_CalibW_Vs_PC_Energy_OffTime", 1000, 0, 16, 2000, 0, 30000, eWedgeMeV, pc.e[k], "hCalQQQ");
|
||||||
|
// // plotter->Fill2D("QQQ_CalibR_Vs_PC_Energy_OffTime", 1000, 0, 16, 2000, 0, 30000, eRingMeV, pc.e[k], "hCalQQQ");
|
||||||
|
// // }
|
||||||
|
plotter->Fill2D("Timing_Difference_QQQ_PC", 500, -1000, 1000, 16, 0, 16, tRing - static_cast<double>(pc.t[k]), chRing, "hTiming");
|
||||||
|
plotter->Fill2D("DelT_Vs_QQQRingECal", 500, -1000, 1000, 1000, 0, 10, tRing - static_cast<double>(pc.t[k]), eRingMeV, "hTiming");
|
||||||
|
plotter->Fill2D("CalibratedQQQEvsPCE_R", 1000, 0, 10, 2000, 0, 30000, eRingMeV, pc.e[k], "hPCQQQ");
|
||||||
|
plotter->Fill2D("CalibratedQQQEvsPCE_W", 1000, 0, 10, 2000, 0, 30000, eWedgeMeV, pc.e[k], "hPCQQQ");
|
||||||
|
if (tRing - static_cast<double>(pc.t[k]) < -150 && tRing - static_cast<double>(pc.t[k]) > -450) // 27Al
|
||||||
|
//if (tRing - static_cast<double>(pc.t[k]) < -70 && tRing - static_cast<double>(pc.t[k]) > -150) // 17F
|
||||||
|
{
|
||||||
|
PCQQQTimeCut = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pc.index[k] >= 24 && pc.e[k] > 50) {
|
||||||
|
plotter->Fill2D("Timing_Difference_QQQ_PC_Cathode", 500, -1000, 1000, 16, 0, 16, tRing - static_cast<double>(pc.t[k]), chRing, "hTiming");
|
||||||
|
}
|
||||||
|
} //end of pc loop
|
||||||
|
|
||||||
|
double theta = -TMath::Pi() / 2 + 2 * TMath::Pi() / 16 / 4. * (qqq.id[i] * 16 + chWedge + 0.5);
|
||||||
|
double rho = 50. + 40. / 16. * (chRing + 0.5);
|
||||||
|
|
||||||
|
//Event qqqevent(TVector3(rho*TMath::Cos(theta),rho*TMath::Sin(theta),23+75+30), eRingMeV, eWedgeMeV, tRing, tWedge);
|
||||||
|
//Event qqqeventr(TVector3(rho*TMath::Cos(theta),rho*TMath::Sin(theta),23+75+30), eRing, eWedge, tRing, tWedge);
|
||||||
|
//QQQ_Events.push_back(qqqevent);
|
||||||
|
//QQQ_Events_Raw.push_back(qqqeventr);
|
||||||
|
plotter->Fill2D("QQQPolarPlot", 16 * 4, -TMath::Pi(), TMath::Pi(), 32, 40, 100, theta, rho, "hCalQQQ");
|
||||||
|
plotter->Fill2D("QQQCartesianPlot", 200, -100, 100, 200, -100, 100, rho * TMath::Cos(theta), rho * TMath::Sin(theta), "hCalQQQ");
|
||||||
|
plotter->Fill2D("QQQCartesianPlot" + std::to_string(qqq.id[i]), 200, -100, 100, 200, -100, 100, rho * TMath::Cos(theta), rho * TMath::Sin(theta), "hCalQQQ");
|
||||||
|
if (PCQQQTimeCut)
|
||||||
|
{
|
||||||
|
plotter->Fill2D("PC_XY_Projection_QQQ_TimeCut" + std::to_string(qqq.id[i]), 400, -100, 100, 400, -100, 100, rho * TMath::Cos(theta), rho * TMath::Sin(theta), "hPCQQQ");
|
||||||
|
}
|
||||||
|
plotter->Fill2D("PC_XY_Projection_QQQ" + std::to_string(qqq.id[i]), 400, -100, 100, 400, -100, 100, rho * TMath::Cos(theta), rho * TMath::Sin(theta), "hPCQQQ");
|
||||||
|
|
||||||
|
if (!HitNonZero)
|
||||||
|
{
|
||||||
|
double x = rho * TMath::Cos(theta);
|
||||||
|
double y = rho * TMath::Sin(theta);
|
||||||
|
hitPos.SetXYZ(x, y, 23 + 75 + 30);
|
||||||
|
HitNonZero = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
plotter->Fill1D("QQQ_Multiplicity", 10, 0, 10, qqqCount, "hRawQQQ");
|
||||||
|
|
||||||
|
// PC Gain Matching and Filling
|
||||||
|
double anodeT = -99999;
|
||||||
|
double cathodeT = 99999;
|
||||||
|
int anodeIndex = -1;
|
||||||
|
int cathodeIndex = -1;
|
||||||
|
for (int i = 0; i < pc.multi; i++)
|
||||||
|
{
|
||||||
|
if (pc.e[i] > 10)
|
||||||
|
{
|
||||||
|
plotter->Fill2D("PC_Index_Vs_Energy", 48, 0, 48, 2000, 0, 30000, pc.index[i], static_cast<double>(pc.e[i]), "hRawPC");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pc.index[i] < 48)
|
||||||
|
{
|
||||||
|
pc.e[i] = pcSlope[pc.index[i]] * pc.e[i] + pcIntercept[pc.index[i]];
|
||||||
|
plotter->Fill2D("PC_Index_VS_GainMatched_Energy", 48, 0, 48, 2000, 0, 30000, pc.index[i], pc.e[i], "hGMPC");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pc.index[i] < 24)
|
||||||
|
{
|
||||||
|
anodeT = static_cast<double>(pc.t[i]);
|
||||||
|
anodeIndex = pc.index[i];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cathodeT = static_cast<double>(pc.t[i]);
|
||||||
|
cathodeIndex = pc.index[i] - 24;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (anodeT != -99999 && cathodeT != 99999)
|
||||||
|
{
|
||||||
|
for (int j = 0; j < qqq.multi; j++)
|
||||||
|
{
|
||||||
|
plotter->Fill1D("PC_Time_qqq", 200, -2000, 2000, anodeT - cathodeT, "hTiming");
|
||||||
|
plotter->Fill2D("PC_Time_Vs_QQQ_ch", 200, -2000, 2000, 16 * 8, 0, 16 * 8, anodeT - cathodeT, qqq.ch[j], "hTiming");
|
||||||
|
plotter->Fill2D("PC_Time_vs_AIndex", 200, -2000, 2000, 24, 0, 24, anodeT - cathodeT, anodeIndex, "hTiming");
|
||||||
|
plotter->Fill2D("PC_Time_vs_CIndex", 200, -2000, 2000, 24, 0, 24, anodeT - cathodeT, cathodeIndex, "hTiming");
|
||||||
|
// plotter->Fill1D("PC_Time_A" + std::to_string(anodeIndex) + "_C" + std::to_string(cathodeIndex), 200, -1000, 1000, anodeT - cathodeT, "TimingPC");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int j = 0; j < sx3.multi; j++)
|
||||||
|
{
|
||||||
|
plotter->Fill1D("PC_Time_sx3", 200, -2000, 2000, anodeT - cathodeT, "hTiming");
|
||||||
|
}
|
||||||
|
|
||||||
|
plotter->Fill1D("PC_Time", 200, -2000, 2000, anodeT - cathodeT, "hTiming");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int j = i + 1; j < pc.multi; j++)
|
||||||
|
{
|
||||||
|
plotter->Fill2D("PC_Coincidence_Matrix", 48, 0, 48, 48, 0, 48, pc.index[i], pc.index[j], "hRawPC");
|
||||||
|
plotter->Fill2D("PC_Coincidence_Matrix_anodeMinusCathode_lt_-200_" + std::to_string(anodeT - cathodeT < -200), 48, 0, 48, 48, 0, 48, pc.index[i], pc.index[j], "hRawPC");
|
||||||
|
plotter->Fill2D("Anode_V_Anode", 24, 0, 24, 24, 0, 24, pc.index[i], pc.index[j], "hGMPC");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
anodeHits.clear();
|
||||||
|
cathodeHits.clear();
|
||||||
|
corrcatMax.clear();
|
||||||
|
|
||||||
|
int aID = 0;
|
||||||
|
int cID = 0;
|
||||||
|
double aE = 0;
|
||||||
|
double cE = 0;
|
||||||
|
double aESum = 0;
|
||||||
|
double cESum = 0;
|
||||||
|
double aEMax = 0;
|
||||||
|
int aIDMax = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < pc.multi; i++)
|
||||||
|
{
|
||||||
|
// if (pc.e[i] > 100)
|
||||||
|
{
|
||||||
|
if (pc.index[i] < 24)
|
||||||
|
anodeHits.push_back(std::pair<int, double>(pc.index[i], pc.e[i]));
|
||||||
|
else if (pc.index[i] >= 24)
|
||||||
|
cathodeHits.push_back(std::pair<int, double>(pc.index[i] - 24, pc.e[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// std::sort(anodeHits.begin(), anodeHits.end(), [](const std::pair<int, double> &a, const std::pair<int, double> &b)
|
||||||
|
// { return a.second > b.second; });
|
||||||
|
// std::sort(cathodeHits.begin(), cathodeHits.end(), [](const std::pair<int, double> &a, const std::pair<int, double> &b)
|
||||||
|
// { return a.second > b.second; });
|
||||||
|
|
||||||
|
if (anodeHits.size() >= 1 && cathodeHits.size() >= 1)
|
||||||
|
{
|
||||||
|
// 2. CRITICAL FIX: Define reference vector 'a'
|
||||||
|
// In Analyzer.cxx, 'a' was left over from the loop. We use the first anode wire as reference here.
|
||||||
|
// (Assuming pwinstance.An is populated and wires are generally parallel).
|
||||||
|
TVector3 refAnode = pwinstance.An[0].first - pwinstance.An[0].second;
|
||||||
|
|
||||||
|
{
|
||||||
|
for (const auto &anode : anodeHits)
|
||||||
|
{
|
||||||
|
aID = anode.first;
|
||||||
|
aE = anode.second;
|
||||||
|
aESum += aE;
|
||||||
|
if (aE > aEMax)
|
||||||
|
{
|
||||||
|
aEMax = aE;
|
||||||
|
aIDMax = aID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto &cathode : cathodeHits)
|
||||||
|
{
|
||||||
|
cID = cathode.first;
|
||||||
|
cE = cathode.second;
|
||||||
|
plotter->Fill2D("AnodeMax_Vs_Cathode_Coincidence_Matrix", 24, 0, 24, 24, 0, 24, aIDMax, cID, "hRawPC");
|
||||||
|
plotter->Fill2D("Anode_Vs_Cathode_Coincidence_Matrix", 24, 0, 24, 24, 0, 24, aID, cID, "hRawPC");
|
||||||
|
plotter->Fill2D("Anode_vs_CathodeE", 2000, 0, 30000, 2000, 0, 30000, aE, cE, "hGMPC");
|
||||||
|
plotter->Fill2D("CathodeMult_V_CathodeE", 6, 0, 6, 2000, 0, 30000, cathodeHits.size(), cE, "hGMPC");
|
||||||
|
for (int j = -4; j < 3; j++)
|
||||||
|
{
|
||||||
|
if ((aIDMax + 24 + j) % 24 == 23 - cID)
|
||||||
|
{
|
||||||
|
corrcatMax.push_back(std::pair<int, double>(cID, cE));
|
||||||
|
cESum += cE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TVector3 anodeIntersection;
|
||||||
|
anodeIntersection.Clear();
|
||||||
|
if (corrcatMax.size() > 0)
|
||||||
|
{
|
||||||
|
double x = 0, y = 0, z = 0;
|
||||||
|
for (const auto &corr : corrcatMax)
|
||||||
|
{
|
||||||
|
if (Crossover[aIDMax][corr.first][0].z > 9000000)
|
||||||
|
continue;
|
||||||
|
if (cESum > 0)
|
||||||
|
{
|
||||||
|
x += (corr.second) / cESum * Crossover[aIDMax][corr.first][0].x;
|
||||||
|
y += (corr.second) / cESum * Crossover[aIDMax][corr.first][0].y;
|
||||||
|
z += (corr.second) / cESum * Crossover[aIDMax][corr.first][0].z;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (x == 0 && y == 0 && z == 0)
|
||||||
|
;
|
||||||
|
// to ignore events with no valid crossover points
|
||||||
|
else
|
||||||
|
anodeIntersection = TVector3(x, -y, -z);
|
||||||
|
// std::cout << "Anode Intersection: " << anodeIntersection.X() << ", " << anodeIntersection.Y() << ", " << anodeIntersection.Z() << std::endl;
|
||||||
|
}
|
||||||
|
bool PCQQQPhiCut = false;
|
||||||
|
// flip the algorithm for cathode 1 multi anode events
|
||||||
|
if ((hitPos.Phi() > (anodeIntersection.Phi() - TMath::PiOver4())) && (hitPos.Phi() < (anodeIntersection.Phi() + TMath::PiOver4()))) {
|
||||||
|
PCQQQPhiCut = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// for (double Tz = -190; Tz <= 190; Tz += 10.0)
|
||||||
|
// {
|
||||||
|
// TVector3 TargetPos(0, 0, Tz);
|
||||||
|
// plotter->Fill2D("Inttheta_vs_QQQtheta_TC" + std::to_string(PCQQQTimeCut) + "_TZ" + std::to_string(Tz), 90, 0, 180, 120, 0, 180, (anodeIntersection - TargetPos).Theta() * 180. / TMath::Pi(), (hitPos - TargetPos).Theta() * 180. / TMath::Pi(), "TPosVariation");
|
||||||
|
// }
|
||||||
|
|
||||||
|
if (anodeIntersection.Z() != 0)
|
||||||
|
{
|
||||||
|
plotter->Fill1D("PC_Z_Projection", 600, -300, 300, anodeIntersection.Z(), "hPCzQQQ");
|
||||||
|
plotter->Fill2D("Z_Proj_VsDelTime", 600, -300, 300, 200, -2000, 2000, anodeIntersection.Z(), anodeT - cathodeT, "hPCzQQQ");
|
||||||
|
plotter->Fill2D("IntPhi_vs_QQQphi", 100, -200, 200, 80, -200, 200, anodeIntersection.Phi() * 180. / TMath::Pi(), hitPos.Phi() * 180. / TMath::Pi(), "hPCQQQ");
|
||||||
|
plotter->Fill2D("Inttheta_vs_QQQtheta", 90, 0, 180, 20, 0, 45, anodeIntersection.Theta() * 180. / TMath::Pi(), hitPos.Theta() * 180. / TMath::Pi(), "hPCQQQ");
|
||||||
|
plotter->Fill2D("Inttheta_vs_QQQtheta_TC" + std::to_string(PCQQQTimeCut), 90, 0, 180, 20, 0, 45, anodeIntersection.Theta() * 180. / TMath::Pi(), hitPos.Theta() * 180. / TMath::Pi(), "hPCQQQ");
|
||||||
|
plotter->Fill2D("IntPhi_vs_QQQphi_TC" + std::to_string(PCQQQTimeCut) + "PhiC" + std::to_string(PCQQQPhiCut), 100, -200, 200, 80, -200, 200, anodeIntersection.Phi() * 180. / TMath::Pi(), hitPos.Phi() * 180. / TMath::Pi(), "hPCQQQ");
|
||||||
|
}
|
||||||
|
if (anodeIntersection.Z() != 0 && cathodeHits.size() >= 2)
|
||||||
|
plotter->Fill1D("PC_Z_Projection_TC" + std::to_string(PCQQQTimeCut) + "PhiC" + std::to_string(PCQQQPhiCut), 600, -300, 300, anodeIntersection.Z(), "hPCzQQQ");
|
||||||
|
|
||||||
|
if (anodeIntersection.Z() != 0 && cathodeHits.size() == 1)
|
||||||
|
{
|
||||||
|
plotter->Fill1D("PC_Z_proj_1C", 600, -300, 300, anodeIntersection.Z(), "hPCzQQQ");
|
||||||
|
plotter->Fill2D("IntersectionPhi_vs_AnodeZ_1C", 400, -200, 200, 600, -300, 300, anodeIntersection.Phi() * 180. / TMath::Pi(), anodeIntersection.Z(), "hPCzQQQ");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (anodeIntersection.Z() != 0 && cathodeHits.size() == 2)
|
||||||
|
{
|
||||||
|
plotter->Fill1D("PC_Z_proj_2C", 600, -300, 300, anodeIntersection.Z(), "hPCzQQQ");
|
||||||
|
plotter->Fill2D("IntersectionPhi_vs_AnodeZ_2C", 400, -200, 200, 600, -300, 300, anodeIntersection.Phi() * 180. / TMath::Pi(), anodeIntersection.Z(), "hGMPC");
|
||||||
|
}
|
||||||
|
if (anodeIntersection.Z() != 0 && cathodeHits.size() > 2)
|
||||||
|
{
|
||||||
|
plotter->Fill1D("PC_Z_proj_nC", 600, -300, 300, anodeIntersection.Z(), "hPCzQQQ");
|
||||||
|
plotter->Fill2D("IntersectionPhi_vs_AnodeZ_nC", 400, -200, 200, 600, -300, 300, anodeIntersection.Phi() * 180. / TMath::Pi(), anodeIntersection.Z(), "hGMPC");
|
||||||
|
}
|
||||||
|
if (anodeHits.size() > 0 && cathodeHits.size() > 0)
|
||||||
|
plotter->Fill2D("AHits_vs_CHits", 12, 0, 11, 6, 0, 5, anodeHits.size(), cathodeHits.size(), "hRawPC");
|
||||||
|
|
||||||
|
// make another plot with nearest neighbour constraint
|
||||||
|
bool hasNeighbourAnodes = false;
|
||||||
|
bool hasNeighbourCathodes = false;
|
||||||
|
|
||||||
|
// 1. Check Anodes for neighbours (including wrap-around 0-23)
|
||||||
|
for (size_t i = 0; i < anodeHits.size(); i++)
|
||||||
|
{
|
||||||
|
for (size_t j = i + 1; j < anodeHits.size(); j++)
|
||||||
|
{
|
||||||
|
int diff = std::abs(anodeHits[i].first - anodeHits[j].first);
|
||||||
|
if (diff == 1 || diff == 23)
|
||||||
|
{ // 23 handles the cylindrical wrap
|
||||||
|
hasNeighbourAnodes = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (hasNeighbourAnodes)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Check Cathodes for neighbours (including wrap-around 0-23)
|
||||||
|
for (size_t i = 0; i < cathodeHits.size(); i++)
|
||||||
|
{
|
||||||
|
for (size_t j = i + 1; j < cathodeHits.size(); j++)
|
||||||
|
{
|
||||||
|
int diff = std::abs(cathodeHits[i].first - cathodeHits[j].first);
|
||||||
|
if (diff == 1 || diff == 23)
|
||||||
|
{
|
||||||
|
hasNeighbourCathodes = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (hasNeighbourCathodes)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ---------------------------------------------------------
|
||||||
|
// FILL PLOTS
|
||||||
|
// ---------------------------------------------------------
|
||||||
|
if (anodeHits.size() > 0 && cathodeHits.size() > 0)
|
||||||
|
{
|
||||||
|
plotter->Fill2D("AHits_vs_CHits_NA" + std::to_string(hasNeighbourAnodes), 12, 0, 11, 6, 0, 5, anodeHits.size(), cathodeHits.size(), "hRawPC");
|
||||||
|
plotter->Fill2D("AHits_vs_CHits_NC" + std::to_string(hasNeighbourCathodes), 12, 0, 11, 6, 0, 5, anodeHits.size(), cathodeHits.size(), "hRawPC");
|
||||||
|
|
||||||
|
// Constraint Plot: Only fill if BOTH planes have adjacent hits
|
||||||
|
// This effectively removes events with only isolated single-wire hits (noise)
|
||||||
|
if (hasNeighbourAnodes && hasNeighbourCathodes)
|
||||||
|
{
|
||||||
|
plotter->Fill2D("AHits_vs_CHits_NN", 12, 0, 11, 6, 0, 5, anodeHits.size(), cathodeHits.size(), "hRawPC");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (HitNonZero && anodeIntersection.Z() != 0)
|
||||||
|
{
|
||||||
|
pw_contr.CalTrack2(hitPos, anodeIntersection);
|
||||||
|
plotter->Fill1D("VertexRecon", 600, -1300, 1300, pw_contr.GetZ0());
|
||||||
|
plotter->Fill1D("VertexRecon_TC"+std::to_string(PCQQQTimeCut)+"_PhiC"+std::to_string(PCQQQPhiCut), 600, -300, 300, pw_contr.GetZ0());
|
||||||
|
|
||||||
|
if (cathodeHits.size() == 2)
|
||||||
|
plotter->Fill1D("VertexRecon_2c_TC"+std::to_string(PCQQQTimeCut)+"_PhiC"+std::to_string(PCQQQPhiCut), 600, -300, 300, pw_contr.GetZ0());
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < qqq.multi; i++)
|
||||||
|
{
|
||||||
|
if (PCQQQTimeCut) {
|
||||||
|
plotter->Fill2D("PC_XY_Projection_QQQ_TimeCut" + std::to_string(qqq.id[i]), 400, -100, 100, 400, -100, 100, anodeIntersection.X(), anodeIntersection.Y(), "hPCQQQ");
|
||||||
|
}
|
||||||
|
plotter->Fill2D("PC_XY_Projection_QQQ" + std::to_string(qqq.id[i]), 400, -100, 100, 400, -100, 100, anodeIntersection.X(), anodeIntersection.Y(), "hPCQQQ");
|
||||||
|
|
||||||
|
for (int j = i + 1; j < qqq.multi; j++)
|
||||||
|
{
|
||||||
|
if (qqq.id[i] == qqq.id[j])
|
||||||
|
{
|
||||||
|
int chWedge = -1;
|
||||||
|
int chRing = -1;
|
||||||
|
double eWedge = 0.0;
|
||||||
|
double eWedgeMeV = 0.0;
|
||||||
|
double eRing = 0.0;
|
||||||
|
double eRingMeV = 0.0;
|
||||||
|
double tRing = 0.0;
|
||||||
|
int qqqID = -1;
|
||||||
|
if (qqq.ch[i] < 16 && qqq.ch[j] >= 16 && qqqGainValid[qqq.id[i]][qqq.ch[i]][qqq.ch[j] - 16])
|
||||||
|
{
|
||||||
|
chWedge = qqq.ch[i];
|
||||||
|
eWedge = qqq.e[i] * qqqGain[qqq.id[i]][qqq.ch[i]][qqq.ch[j] - 16];
|
||||||
|
chRing = qqq.ch[j] - 16;
|
||||||
|
eRing = qqq.e[j];
|
||||||
|
tRing = static_cast<double>(qqq.t[j]);
|
||||||
|
qqqID = qqq.id[i];
|
||||||
|
}
|
||||||
|
else if (qqq.ch[j] < 16 && qqq.ch[i] >= 16 && qqqGainValid[qqq.id[j]][qqq.ch[j]][qqq.ch[i] - 16])
|
||||||
|
{
|
||||||
|
chWedge = qqq.ch[j];
|
||||||
|
eWedge = qqq.e[j] * qqqGain[qqq.id[j]][qqq.ch[j]][qqq.ch[i] - 16];
|
||||||
|
chRing = qqq.ch[i] - 16;
|
||||||
|
tRing = static_cast<double>(qqq.t[i]);
|
||||||
|
eRing = qqq.e[i];
|
||||||
|
qqqID = qqq.id[i];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (qqqCalibValid[qqq.id[i]][chRing][chWedge])
|
||||||
|
{
|
||||||
|
eWedgeMeV = eWedge * qqqCalib[qqq.id[i]][chRing][chWedge] / 1000;
|
||||||
|
eRingMeV = eRing * qqqCalib[qqq.id[i]][chRing][chWedge] / 1000;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// if (anodeIntersection.Z() != 0)
|
||||||
|
{
|
||||||
|
plotter->Fill2D("PC_Z_vs_QQQRing", 600, -300, 300, 16, 0, 16, anodeIntersection.Z(), chRing, "hPCzQQQ");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (anodeIntersection.Z() != 0 && cathodeHits.size() == 2)
|
||||||
|
{
|
||||||
|
plotter->Fill2D("PC_Z_vs_QQQRing_2C", 600, -300, 300, 16, 0, 16, anodeIntersection.Z(), chRing, "hPCzQQQ");
|
||||||
|
plotter->Fill2D("PC_Z_vs_QQQRing_2C" + std::to_string(qqq.id[i]), 600, -300, 300, 16, 0, 16, anodeIntersection.Z(), chRing, "hPCzQQQ");
|
||||||
|
plotter->Fill2D("PC_Z_vs_QQQWedge_2C", 600, -300, 300, 16, 0, 16, anodeIntersection.Z(), chWedge, "hPCzQQQ");
|
||||||
|
}
|
||||||
|
plotter->Fill2D("Vertex_V_QQQRingTC" + std::to_string(PCQQQTimeCut) + "PhiC" + std::to_string(PCQQQPhiCut), 600, -300, 300, 16, 0, 16, pw_contr.GetZ0(), chRing, "hPCQQQ");
|
||||||
|
double phi = TMath::ATan2(anodeIntersection.Y(), anodeIntersection.X()) * 180. / TMath::Pi();
|
||||||
|
plotter->Fill2D("PolarAngle_Vs_QQQWedge" + std::to_string(qqqID), 360, -360, 360, 16, 0, 16, phi, chWedge, "hPCQQQ");
|
||||||
|
// plotter->Fill2D("EdE_PC_vs_QQQ_timegate_ls1000"+std::to_string())
|
||||||
|
|
||||||
|
plotter->Fill2D("PC_Z_vs_QQQRing_Det" + std::to_string(qqqID), 600, -300, 300, 16, 0, 16, anodeIntersection.Z(), chRing, "hPCQQQ");
|
||||||
|
//double theta = -TMath::Pi() / 2 + 2 * TMath::Pi() / 16 / 4. * (qqq.id[i] * 16 + chWedge + 0.5);
|
||||||
|
//double rho = 50. + 40. / 16. * (chRing + 0.5);
|
||||||
|
|
||||||
|
for (int k = 0; k < pc.multi; k++)
|
||||||
|
{
|
||||||
|
if(pc.index[k] >= 24)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
double sinTheta = TMath::Sin(hitPos.Theta());
|
||||||
|
|
||||||
|
plotter->Fill2D("CalibratedQQQE_RvsPCE_TC" + std::to_string(PCQQQTimeCut) + "PhiC" + std::to_string(PCQQQPhiCut), 1000, 0, 10, 2000, 0, 30000, eRingMeV, pc.e[k]*sinTheta, "hPCQQQ");
|
||||||
|
plotter->Fill2D("CalibratedQQQE_WvsPCE_TC" + std::to_string(PCQQQTimeCut) + "PhiC" + std::to_string(PCQQQPhiCut), 1000, 0, 10, 2000, 0, 30000, eWedgeMeV, pc.e[k]*sinTheta, "hPCQQQ");
|
||||||
|
plotter->Fill2D("PCQQQ_dTimevsdPhi", 200, -2000, 2000, 80, -200, 200, tRing - static_cast<double>(pc.t[k]), (hitPos.Phi()-anodeIntersection.Phi()) * 180. / TMath::Pi(), "hTiming");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (int i = 0; i < sx3.multi; i++)
|
||||||
|
{
|
||||||
|
// plotting sx3 strip hits vs anode phi
|
||||||
|
if (sx3.ch[i] < 8)
|
||||||
|
plotter->Fill2D("AnodePhi_vs_SX3Strip", 100, -200, 200, 8 * 24, 0, 8 * 24, anodeIntersection.Phi() * 180. / TMath::Pi(), sx3.id[i] * 8 + sx3.ch[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (anodeIntersection.Z() != 0 && cathodeHits.size() == 3)
|
||||||
|
{
|
||||||
|
plotter->Fill1D("PC_Z_proj_3C", 600, -300, 300, anodeIntersection.Z(), "hPCzQQQ");
|
||||||
|
}
|
||||||
|
|
||||||
|
plotter->Fill2D("AnodeMaxE_Vs_Cathode_Sum_Energy", 2000, 0, 30000, 2000, 0, 30000, aEMax, cESum, "hGMPC");
|
||||||
|
plotter->Fill1D("Correlated_Cathode_MaxAnode", 6, 0, 5, corrcatMax.size(), "hGMPC");
|
||||||
|
plotter->Fill2D("Correlated_Cathode_VS_MaxAnodeEnergy", 6, 0, 5, 2000, 0, 30000, corrcatMax.size(), aEMax, "hGMPC");
|
||||||
|
plotter->Fill1D("AnodeHits", 12, 0, 11, anodeHits.size(), "hGMPC");
|
||||||
|
plotter->Fill2D("AnodeMaxE_vs_AnodeHits", 12, 0, 11, 2000, 0, 30000, anodeHits.size(), aEMax, "hGMPC");
|
||||||
|
|
||||||
|
if (anodeHits.size() < 1)
|
||||||
|
{
|
||||||
|
plotter->Fill1D("NoAnodeHits_CathodeHits", 6, 0, 5, cathodeHits.size(), "hGMPC");
|
||||||
|
}
|
||||||
|
|
||||||
|
return kTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TrackRecon::Terminate()
|
||||||
|
{
|
||||||
|
plotter->FlushToDisk();
|
||||||
|
}
|
||||||
127
TrackRecon.h
Normal file
127
TrackRecon.h
Normal file
|
|
@ -0,0 +1,127 @@
|
||||||
|
#ifndef TrackRecon_h
|
||||||
|
#define TrackRecon_h
|
||||||
|
|
||||||
|
#include <TROOT.h>
|
||||||
|
#include <TChain.h>
|
||||||
|
#include <TFile.h>
|
||||||
|
#include <TSelector.h>
|
||||||
|
#include <vector> // Required for vectors
|
||||||
|
#include <utility> // Required for std::pair
|
||||||
|
|
||||||
|
#include "Armory/ClassDet.h"
|
||||||
|
#include "Armory/ClassPW.h" // YOU ADDED THIS (Correct! Defines Coord)
|
||||||
|
|
||||||
|
class TrackRecon : public TSelector {
|
||||||
|
public :
|
||||||
|
TTree *fChain; //!pointer to the analyzed TTree or TChain
|
||||||
|
|
||||||
|
// Declaration of leaf types
|
||||||
|
Det sx3;
|
||||||
|
Det qqq;
|
||||||
|
Det pc ;
|
||||||
|
Det misc;
|
||||||
|
|
||||||
|
ULong64_t evID;
|
||||||
|
UInt_t run;
|
||||||
|
|
||||||
|
// List of branches
|
||||||
|
TBranch *b_eventID; //!
|
||||||
|
TBranch *b_run; //!
|
||||||
|
TBranch *b_sx3Multi; //!
|
||||||
|
TBranch *b_sx3ID; //!
|
||||||
|
TBranch *b_sx3Ch; //!
|
||||||
|
TBranch *b_sx3E; //!
|
||||||
|
TBranch *b_sx3T; //!
|
||||||
|
TBranch *b_qqqMulti; //!
|
||||||
|
TBranch *b_qqqID; //!
|
||||||
|
TBranch *b_qqqCh; //!
|
||||||
|
TBranch *b_qqqE; //!
|
||||||
|
TBranch *b_qqqT; //!
|
||||||
|
TBranch *b_pcMulti; //!
|
||||||
|
TBranch *b_pcID; //!
|
||||||
|
TBranch *b_pcCh; //!
|
||||||
|
TBranch *b_pcE; //!
|
||||||
|
TBranch *b_pcT; //!
|
||||||
|
TBranch *b_miscMulti; //!
|
||||||
|
TBranch *b_miscID; //!
|
||||||
|
TBranch *b_miscCh; //!
|
||||||
|
TBranch *b_miscE; //!
|
||||||
|
TBranch *b_miscT; //!
|
||||||
|
TBranch *b_miscTf; //!
|
||||||
|
|
||||||
|
// 1. Geometry Cache
|
||||||
|
Coord Crossover[24][24][2];
|
||||||
|
|
||||||
|
// 2. Persistent Vectors (REQUIRED for the optimized .cxx to work)
|
||||||
|
std::vector<std::pair<int, double>> anodeHits;
|
||||||
|
std::vector<std::pair<int, double>> cathodeHits;
|
||||||
|
std::vector<std::pair<int, double>> corrcatMax;
|
||||||
|
|
||||||
|
TrackRecon(TTree * /*tree*/ =0) : fChain(0) { }
|
||||||
|
virtual ~TrackRecon() { }
|
||||||
|
virtual Int_t Version() const { return 2; }
|
||||||
|
virtual void Begin(TTree *tree);
|
||||||
|
virtual void SlaveBegin(TTree *tree);
|
||||||
|
virtual void Init(TTree *tree);
|
||||||
|
virtual Bool_t Notify();
|
||||||
|
virtual Bool_t Process(Long64_t entry);
|
||||||
|
virtual Int_t GetEntry(Long64_t entry, Int_t getall = 0) { return fChain ? fChain->GetTree()->GetEntry(entry, getall) : 0; }
|
||||||
|
virtual void SetOption(const char *option) { fOption = option; }
|
||||||
|
virtual void SetObject(TObject *obj) { fObject = obj; }
|
||||||
|
virtual void SetInputList(TList *input) { fInput = input; }
|
||||||
|
virtual TList *GetOutputList() const { return fOutput; }
|
||||||
|
virtual void SlaveTerminate();
|
||||||
|
virtual void Terminate();
|
||||||
|
|
||||||
|
ClassDef(TrackRecon,0);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef TrackRecon_cxx
|
||||||
|
void TrackRecon::Init(TTree *tree){
|
||||||
|
|
||||||
|
if (!tree) return;
|
||||||
|
fChain = tree;
|
||||||
|
fChain->SetMakeClass(1);
|
||||||
|
|
||||||
|
fChain->SetBranchAddress("evID", &evID, &b_eventID);
|
||||||
|
fChain->SetBranchAddress("run", &run, &b_run);
|
||||||
|
|
||||||
|
sx3.SetDetDimension(24,12);
|
||||||
|
qqq.SetDetDimension(4,32);
|
||||||
|
pc.SetDetDimension(2,24);
|
||||||
|
|
||||||
|
fChain->SetBranchAddress("sx3Multi", &sx3.multi, &b_sx3Multi);
|
||||||
|
fChain->SetBranchAddress("sx3ID", &sx3.id, &b_sx3ID);
|
||||||
|
fChain->SetBranchAddress("sx3Ch", &sx3.ch, &b_sx3Ch);
|
||||||
|
fChain->SetBranchAddress("sx3E", &sx3.e, &b_sx3E);
|
||||||
|
fChain->SetBranchAddress("sx3T", &sx3.t, &b_sx3T);
|
||||||
|
fChain->SetBranchAddress("qqqMulti", &qqq.multi, &b_qqqMulti);
|
||||||
|
fChain->SetBranchAddress("qqqID", &qqq.id, &b_qqqID);
|
||||||
|
fChain->SetBranchAddress("qqqCh", &qqq.ch, &b_qqqCh);
|
||||||
|
fChain->SetBranchAddress("qqqE", &qqq.e, &b_qqqE);
|
||||||
|
fChain->SetBranchAddress("qqqT", &qqq.t, &b_qqqT);
|
||||||
|
fChain->SetBranchAddress("pcMulti", &pc.multi, &b_pcMulti);
|
||||||
|
fChain->SetBranchAddress("pcID", &pc.id, &b_pcID);
|
||||||
|
fChain->SetBranchAddress("pcCh", &pc.ch, &b_pcCh);
|
||||||
|
fChain->SetBranchAddress("pcE", &pc.e, &b_pcE);
|
||||||
|
fChain->SetBranchAddress("pcT", &pc.t, &b_pcT);
|
||||||
|
fChain->SetBranchAddress("miscMulti", &misc.multi, &b_miscMulti);
|
||||||
|
fChain->SetBranchAddress("miscID", &misc.id, &b_miscID);
|
||||||
|
fChain->SetBranchAddress("miscCh", &misc.ch, &b_miscCh);
|
||||||
|
fChain->SetBranchAddress("miscE", &misc.e, &b_miscE);
|
||||||
|
fChain->SetBranchAddress("miscT", &misc.t, &b_miscT);
|
||||||
|
}
|
||||||
|
|
||||||
|
Bool_t TrackRecon::Notify(){
|
||||||
|
return kTRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TrackRecon::SlaveBegin(TTree * /*tree*/){
|
||||||
|
// TString option = GetOption();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TrackRecon::SlaveTerminate(){
|
||||||
|
}
|
||||||
|
#endif // #ifdef TrackRecon_cxx
|
||||||
BIN
WedgeChVAnode.jpeg
Normal file
BIN
WedgeChVAnode.jpeg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 201 KiB |
27
anasen_fem/README.md
Normal file
27
anasen_fem/README.md
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
### README for ANASEN fem simulations:
|
||||||
|
|
||||||
|
* There are a few iterations of these simulations that already exist. Be sure to also locate and refer to them if necessary.
|
||||||
|
* Install gmsh and its python api by running (Ubuntu 22.04 LTS)
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo apt install gmsh python3-gmsh
|
||||||
|
```
|
||||||
|
|
||||||
|
* Gmsh gives us the tools to create a meshgrid that samples the 2d space appropriately to plot the field/equipotential lines.
|
||||||
|
* The output file typically has the .msh extension. This is read as input to Elmer, which is the FEM differential-equation solver.
|
||||||
|
|
||||||
|
* Install Elmer via the following steps:
|
||||||
|
|
||||||
|
```
|
||||||
|
sudo add-apt-repository ppa:elmer-csc-ubuntu/elmer-csc-ppa
|
||||||
|
sudo apt install elmerfem-csc-eg
|
||||||
|
```
|
||||||
|
|
||||||
|
* Install ParaView for visualizations by downloading from the Linux .tar.gz link at https://www.paraview.org/download/
|
||||||
|
- The current version is tested to work on Paraview 6.1.0. The default version in Ubuntu 22.04 repositories has some trouble with scripting
|
||||||
|
* v0.0.1, March 10 2026
|
||||||
|
- 2d simulations of fields only. gmsh for meshing, elmer for fem, paraview to plot
|
||||||
|
- Before running, open `paraview_plotter.py` to make the bash shebang (#!) point to the location of `pvpython` or `pvbatch`
|
||||||
|
- `python3 run.py` should run everything in order, and is hopefully all the files are self-documenting
|
||||||
|
* v0.0.2, planned TODO
|
||||||
|
- Garfield to take Elmer results and perform charge-transport
|
||||||
2
anasen_fem/clean.sh
Normal file
2
anasen_fem/clean.sh
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
rm wires2d.msh
|
||||||
|
rm wires2d/*
|
||||||
114
anasen_fem/junk/wires.py
Normal file
114
anasen_fem/junk/wires.py
Normal file
|
|
@ -0,0 +1,114 @@
|
||||||
|
import numpy as np
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
from mpl_toolkits.mplot3d import Axes3D
|
||||||
|
|
||||||
|
acolors = plt.get_cmap('tab20',24)
|
||||||
|
ccolors = plt.get_cmap('tab20',24)
|
||||||
|
|
||||||
|
k=-2*np.pi/24.
|
||||||
|
offset = 6*k + 3*k #-pi/2
|
||||||
|
xarra_1 = np.array([37*np.cos(k*i+offset) for i in np.arange(0,24)])
|
||||||
|
yarra_1 = np.array([37*np.sin(k*i+offset) for i in np.arange(0,24)])
|
||||||
|
labelsa_1 = np.array([i for i in np.arange(0,24)])
|
||||||
|
|
||||||
|
fig,ax = plt.subplots(figsize=(10,10))
|
||||||
|
ax.invert_yaxis()
|
||||||
|
ax.plot(xarra_1,yarra_1,"x",label="anode, z=-L/2")
|
||||||
|
|
||||||
|
for x,y,label in zip(xarra_1,yarra_1,labelsa_1):
|
||||||
|
ax.text(x,y,label)
|
||||||
|
|
||||||
|
kc=2*np.pi/24.
|
||||||
|
offsetc = -4*kc + 2*kc - np.pi/24 #-pi/4
|
||||||
|
xarrc_1 = np.array([42*np.cos(kc*i+offsetc) for i in np.arange(0,24)])
|
||||||
|
yarrc_1 = np.array([42*np.sin(kc*i+offsetc) for i in np.arange(0,24)])
|
||||||
|
labelsc_1 = np.array([i for i in np.arange(0,24)])
|
||||||
|
|
||||||
|
ax.plot(xarrc_1,yarrc_1,"o",label="cathode, z=-L/2, where they are picked up")
|
||||||
|
|
||||||
|
for x,y,label in zip(xarrc_1,yarrc_1,labelsc_1):
|
||||||
|
ax.text(x,y,label)
|
||||||
|
plt.title("z=-L/2 plane, beam going into the plane along +z, (+x right, +y down)")
|
||||||
|
plt.grid()
|
||||||
|
plt.legend()
|
||||||
|
plt.savefig("plane1.png")
|
||||||
|
plt.show()
|
||||||
|
|
||||||
|
fig,ax = plt.subplots(figsize=(10,10))
|
||||||
|
ax.invert_yaxis()
|
||||||
|
|
||||||
|
offset = offset-3*k
|
||||||
|
xarra_2 = np.array([37*np.cos(k*i+offset) for i in np.arange(0,24)])
|
||||||
|
yarra_2 = np.array([37*np.sin(k*i+offset) for i in np.arange(0,24)])
|
||||||
|
labelsa_2 = np.array([i for i in np.arange(0,24)])
|
||||||
|
|
||||||
|
ax.plot(xarra_2,yarra_2,"x",label="anode, z=+L/2, where they are picked up")
|
||||||
|
|
||||||
|
for x,y,label in zip(xarra_2,yarra_2,labelsa_2):
|
||||||
|
ax.text(x,y,label)
|
||||||
|
|
||||||
|
offsetc = offsetc-3*kc
|
||||||
|
xarrc_2 = np.array([42*np.cos(kc*i+offsetc) for i in np.arange(0,24)])
|
||||||
|
yarrc_2 = np.array([42*np.sin(kc*i+offsetc) for i in np.arange(0,24)])
|
||||||
|
labelsc_2 = np.array([i for i in np.arange(0,24)])
|
||||||
|
|
||||||
|
ax.plot(xarrc_2,yarrc_2,"o",label="cathode, z=+L/2")
|
||||||
|
|
||||||
|
for x,y,label in zip(xarrc_2,yarrc_2,labelsc_2):
|
||||||
|
ax.text(x,y,label)
|
||||||
|
plt.title("z=+L/2 plane, beam going into the plane along +z, (+x right, +y down)")
|
||||||
|
plt.grid()
|
||||||
|
plt.legend()
|
||||||
|
plt.savefig("plane2.png")
|
||||||
|
plt.show()
|
||||||
|
|
||||||
|
fig = plt.figure(figsize=(10,10))
|
||||||
|
ax = fig.add_subplot(111,projection='3d')
|
||||||
|
ax.set_xlabel("x")
|
||||||
|
ax.set_ylabel("y")
|
||||||
|
ax.set_zlabel("z")
|
||||||
|
|
||||||
|
xx_a = np.array([[x1,x2] for x1,x2 in zip(xarra_1,xarra_2)])
|
||||||
|
yy_a = np.array([[y1,y2] for y1,y2 in zip(yarra_1,yarra_2)])
|
||||||
|
zz_a = np.array([[-173.5,173.5] for x1,x2 in zip(xarra_1,xarra_2)])
|
||||||
|
for i,[xx,yy,zz] in enumerate(zip(xx_a,yy_a,zz_a)):
|
||||||
|
ax.plot(xx,yy,zz,'-',color=acolors(i/24))
|
||||||
|
|
||||||
|
for i,[x,y,label] in enumerate(zip(xarra_1,yarra_1,labelsa_1)):
|
||||||
|
ax.text(x,y,-173,"a"+str(label),color=acolors(i/24))
|
||||||
|
for i,[x,y,label] in enumerate(zip(xarra_2,yarra_2,labelsa_2)):
|
||||||
|
ax.text(x,y,+173,"a"+str(label),color=acolors(i/24))
|
||||||
|
|
||||||
|
xx_c = np.array([[x1,x2] for x1,x2 in zip(xarrc_1,xarrc_2)])
|
||||||
|
yy_c = np.array([[y1,y2] for y1,y2 in zip(yarrc_1,yarrc_2)])
|
||||||
|
zz_c = np.array([[-173.5,173.5] for x1,x2 in zip(xarrc_1,xarrc_2)])
|
||||||
|
for i,[xx,yy,zz] in enumerate(zip(xx_c,yy_c,zz_c)):
|
||||||
|
ax.plot(xx,yy,zz,'--',color=ccolors(((47-i)%24)/24))
|
||||||
|
|
||||||
|
for i,[x,y,label] in enumerate(zip(xarrc_1,yarrc_1,labelsc_1)):
|
||||||
|
ax.text(x,y,-173,"c"+str(label),color=ccolors(((25-i)%24)/24))
|
||||||
|
for i,[x,y,label] in enumerate(zip(xarrc_2,yarrc_2,labelsc_2)):
|
||||||
|
ax.text(x,y,+173,"c"+str(label),color=ccolors(((47-i)%24)/24))
|
||||||
|
ax.view_init(elev=-53, azim=-106, roll=18)
|
||||||
|
plt.tight_layout()
|
||||||
|
plt.show()
|
||||||
|
phi_qqq = np.array([[2*np.pi*(-i*16+j+0.5)/(16*4) for i in range(4)] for j in range(16)])
|
||||||
|
print(phi_qqq)
|
||||||
|
#'''
|
||||||
|
for i,[phi1,phi2,phi3,phi4] in enumerate(phi_qqq):
|
||||||
|
ax.plot([50*np.cos(phi1),100*np.cos(phi1)],[50*np.sin(phi1),100*np.sin(phi1)],[100,100],'-',color='red')
|
||||||
|
ax.text(104*np.cos(phi1),104*np.sin(phi1),100,"0_%d"%(i),color="red")
|
||||||
|
|
||||||
|
ax.plot([50*np.cos(phi2),100*np.cos(phi2)],[50*np.sin(phi2),100*np.sin(phi2)],[100,100],'-',color='green')
|
||||||
|
ax.text(104*np.cos(phi2),104*np.sin(phi2),100,"1_%d"%(i),color="green")
|
||||||
|
|
||||||
|
ax.plot([50*np.cos(phi3),100*np.cos(phi3)],[50*np.sin(phi3),100*np.sin(phi3)],[100,100],'-',color='blue')
|
||||||
|
ax.text(104*np.cos(phi3),104*np.sin(phi3),100,"2_%d"%(i),color="blue")
|
||||||
|
|
||||||
|
ax.plot([50*np.cos(phi4),100*np.cos(phi4)],[50*np.sin(phi4),100*np.sin(phi4)],[100,100],'-',color='brown')
|
||||||
|
ax.text(104*np.cos(phi4),104*np.sin(phi4),100,"3_%d"%(i),color="brown")
|
||||||
|
#'''
|
||||||
|
#coords_qqq = np.array([[50*np.cos(phi),100*np.sin(phi),100] for phi in phi_qqq]).T
|
||||||
|
plt.tight_layout()
|
||||||
|
plt.show()
|
||||||
|
|
||||||
71
anasen_fem/junk/wires2d_test.sif
Normal file
71
anasen_fem/junk/wires2d_test.sif
Normal file
|
|
@ -0,0 +1,71 @@
|
||||||
|
Check Keywords Warn
|
||||||
|
|
||||||
|
Header
|
||||||
|
Mesh DB "." "wires2d"
|
||||||
|
End
|
||||||
|
|
||||||
|
Simulation
|
||||||
|
Coordinate System = Cartesian 2D
|
||||||
|
Simulation Type = Steady State
|
||||||
|
Steady State Max Iterations = 1
|
||||||
|
Output File = "elstatics.result"
|
||||||
|
Post File = "elstatics.ep"
|
||||||
|
End
|
||||||
|
|
||||||
|
Constants
|
||||||
|
Permittivity Of Vacuum = 8.8542e-12
|
||||||
|
End
|
||||||
|
|
||||||
|
|
||||||
|
Body 1
|
||||||
|
Target Bodies(1) = 13
|
||||||
|
Equation = 1
|
||||||
|
Material = 1
|
||||||
|
End
|
||||||
|
|
||||||
|
|
||||||
|
Equation 1
|
||||||
|
Active Solvers(2) = 1 2
|
||||||
|
End
|
||||||
|
|
||||||
|
|
||||||
|
Material 1
|
||||||
|
Relative Permittivity = 1
|
||||||
|
End
|
||||||
|
|
||||||
|
|
||||||
|
Solver 1
|
||||||
|
Equation = Electrostatics
|
||||||
|
Procedure = "StatElecSolve" "StatElecSolver"
|
||||||
|
|
||||||
|
Variable = Potential
|
||||||
|
Variable DOFs = 1
|
||||||
|
|
||||||
|
Calculate Electric Field = True
|
||||||
|
Calculate Electric Flux = False
|
||||||
|
|
||||||
|
Linear System Solver = Iterative
|
||||||
|
Linear System Iterative Method = CG
|
||||||
|
Linear System Max Iterations = 500
|
||||||
|
Linear System Convergence Tolerance = 1.0e-8
|
||||||
|
Linear System Preconditioning = ILU1
|
||||||
|
End
|
||||||
|
|
||||||
|
|
||||||
|
Solver 2
|
||||||
|
Equation = Electric Force
|
||||||
|
Procedure = "ElectricForce" "StatElecForce"
|
||||||
|
End
|
||||||
|
|
||||||
|
|
||||||
|
Boundary Condition 1
|
||||||
|
Target Boundaries = 10
|
||||||
|
Potential = 650
|
||||||
|
Calculate Electric Force = True
|
||||||
|
End
|
||||||
|
|
||||||
|
|
||||||
|
Boundary Condition 2
|
||||||
|
Target Boundaries = 20
|
||||||
|
Potential = 0
|
||||||
|
End
|
||||||
91
anasen_fem/junk/wires_gmsh.py
Normal file
91
anasen_fem/junk/wires_gmsh.py
Normal file
|
|
@ -0,0 +1,91 @@
|
||||||
|
import numpy as np
|
||||||
|
import gmsh
|
||||||
|
|
||||||
|
gmsh.initialize()
|
||||||
|
gmsh.model.add("adaptive_mesh")
|
||||||
|
gmsh.option.setNumber('General.NumThreads', 4)
|
||||||
|
#gmsh.option.setNumber("Mesh.Adapt.MaxNumberOfElements", 200000)
|
||||||
|
#gmsh.option.setNumber("Mesh.Adapt.MaxNumberOfNodes", 200000)
|
||||||
|
#gmsh.option.setNumber("Mesh.Adapt.MaxIter",5)
|
||||||
|
#gmsh.option.setNumber("Mesh.MeshSizeMin", 5e-3)
|
||||||
|
#gmsh.option.setNumber("Mesh.MeshSizeMax", 10.0)
|
||||||
|
#gmsh.option.setNumber("Mesh.CharacteristicLengthFromCurvature", 0)
|
||||||
|
|
||||||
|
lc = 0.01
|
||||||
|
|
||||||
|
#anodes, plane 1 at -zmax/2
|
||||||
|
k=-2*np.pi/24.
|
||||||
|
offset = 6*k + 3*k #-pi/2
|
||||||
|
xarra_1 = np.array([37*np.cos(k*i+offset) for i in np.arange(0,24)])
|
||||||
|
yarra_1 = np.array([37*np.sin(k*i+offset) for i in np.arange(0,24)])
|
||||||
|
|
||||||
|
#cathodes, plane 1 at -zmax/2
|
||||||
|
kc=2*np.pi/24.
|
||||||
|
offsetc = -4*kc + 2*kc - np.pi/24 #-pi/4
|
||||||
|
xarrc_1 = np.array([42*np.cos(kc*i+offsetc) for i in np.arange(0,24)])
|
||||||
|
yarrc_1 = np.array([42*np.sin(kc*i+offsetc) for i in np.arange(0,24)])
|
||||||
|
|
||||||
|
#anodes, plane 2 at +zmax/2
|
||||||
|
offset = offset-3*k
|
||||||
|
xarra_2 = np.array([37*np.cos(k*i+offset) for i in np.arange(0,24)])
|
||||||
|
yarra_2 = np.array([37*np.sin(k*i+offset) for i in np.arange(0,24)])
|
||||||
|
|
||||||
|
#cathodes, plane2 at +zmax/2
|
||||||
|
offsetc = offsetc-3*kc
|
||||||
|
xarrc_2 = np.array([42*np.cos(kc*i+offsetc) for i in np.arange(0,24)])
|
||||||
|
yarrc_2 = np.array([42*np.sin(kc*i+offsetc) for i in np.arange(0,24)])
|
||||||
|
|
||||||
|
pa1 = []
|
||||||
|
pa2 = []
|
||||||
|
pc1 = []
|
||||||
|
pc2 = []
|
||||||
|
|
||||||
|
wire_radius = 0.254 #mm
|
||||||
|
anode_wires = []
|
||||||
|
cathode_wires = []
|
||||||
|
aw_tags = [(3,i) for i in range(24)]
|
||||||
|
cw_tags = [(3,i+24) for i in range(24)]
|
||||||
|
|
||||||
|
for i,[xa,ya,xc,yc,xa2,ya2,xc2,yc2] in enumerate(zip(xarra_1,yarra_1,xarrc_1,yarrc_1,xarra_2,yarra_2,xarrc_2,yarrc_2)):
|
||||||
|
print(i,xa,ya,-178.3,xc,yc,-178.3,xa2,ya2,178.3,xc2,yc2,178.3)
|
||||||
|
anode_wires.append(gmsh.model.occ.addCylinder(xa,ya,-178.3,(xa2-xa),(ya2-ya),178.3*2,wire_radius,i)) #x,y,z of first face center, dx,dy,dz of the axis, then the wire radius
|
||||||
|
cathode_wires.append(gmsh.model.occ.addCylinder(xc,yc,-178.3,(xc2-xc),(yc2-yc),178.3*2,wire_radius,i+24)) #cathode tags 24-47, anode 0-23
|
||||||
|
|
||||||
|
|
||||||
|
anasen_barrel = gmsh.model.occ.addCylinder(0,0,-500,0,0,500+605,300,1234) #tag 1234
|
||||||
|
#anasen_barrel = gmsh.model.occ.addCylinder(0,0,-500,0,0,500+605,300,1234) #tag 1234
|
||||||
|
|
||||||
|
gmsh.model.occ.synchronize()
|
||||||
|
|
||||||
|
all_wires = aw_tags+cw_tags
|
||||||
|
gmsh.model.occ.fragment([(3,1234)],all_wires)
|
||||||
|
gmsh.model.occ.removeAllDuplicates()
|
||||||
|
gmsh.model.occ.synchronize()
|
||||||
|
gmsh.option.setNumber("Geometry.Tolerance", 1e-6)
|
||||||
|
gmsh.option.setNumber("Geometry.OCCFixDegenerated", 1)
|
||||||
|
gmsh.option.setNumber("Geometry.OCCFixSmallEdges", 1)
|
||||||
|
gmsh.option.setNumber("Geometry.OCCFixSmallFaces", 1)
|
||||||
|
|
||||||
|
wire_surfs = []
|
||||||
|
for w in anode_wires + cathode_wires:
|
||||||
|
wire_surfs += [s[1] for s in gmsh.model.getBoundary([(3,w)], oriented=False) if s[0] == 2]
|
||||||
|
#'''
|
||||||
|
f1 = gmsh.model.mesh.field.add("Distance")
|
||||||
|
gmsh.model.mesh.field.setNumbers(f1, "FacesList", wire_surfs) # Example curves
|
||||||
|
f2 = gmsh.model.mesh.field.add("Threshold")
|
||||||
|
gmsh.model.mesh.field.setNumber(f2, "InField", f1)
|
||||||
|
gmsh.model.mesh.field.setNumber(f2, "SizeMin", 0.05)
|
||||||
|
gmsh.model.mesh.field.setNumber(f2, "SizeMax", 5.)
|
||||||
|
gmsh.model.mesh.field.setNumber(f2, "DistMin", 1.)
|
||||||
|
gmsh.model.mesh.field.setNumber(f2, "DistMax", 20.)
|
||||||
|
gmsh.model.mesh.field.setAsBackgroundMesh(f2)
|
||||||
|
#'''
|
||||||
|
gmsh.option.setNumber("Mesh.Algorithm", 2)
|
||||||
|
gmsh.option.setNumber("Mesh.Algorithm3D", 1) # For 3D meshes
|
||||||
|
|
||||||
|
gmsh.model.mesh.generate(dim=3)
|
||||||
|
#gmsh.model.mesh.refine()
|
||||||
|
#gmsh.model.mesh.refine()
|
||||||
|
#gmsh.model.mesh.refine()
|
||||||
|
gmsh.fltk.run()
|
||||||
|
gmsh.finalize()
|
||||||
87
anasen_fem/junk/wires_gmsh_bc.py
Normal file
87
anasen_fem/junk/wires_gmsh_bc.py
Normal file
|
|
@ -0,0 +1,87 @@
|
||||||
|
import numpy as np
|
||||||
|
import gmsh
|
||||||
|
|
||||||
|
gmsh.initialize()
|
||||||
|
#gmsh.model.add("adaptive_mesh")
|
||||||
|
gmsh.option.setNumber('General.NumThreads', 4)
|
||||||
|
#gmsh.option.setNumber("Mesh.Adapt.MaxNumberOfElements", 200000)
|
||||||
|
#gmsh.option.setNumber("Mesh.Adapt.MaxNumberOfNodes", 200000)
|
||||||
|
#gmsh.option.setNumber("Mesh.Adapt.MaxIter",5)
|
||||||
|
#gmsh.option.setNumber("Mesh.MeshSizeMin", 5e-3)
|
||||||
|
#gmsh.option.setNumber("Mesh.MeshSizeMax", 10.0)
|
||||||
|
gmsh.option.setNumber("Geometry.Tolerance", 1e-2)
|
||||||
|
#gmsh.option.setNumber("Mesh.CharacteristicLengthFromCurvature", 0)
|
||||||
|
|
||||||
|
lc = 0.04
|
||||||
|
#anodes, plane 1 at -zmax/2
|
||||||
|
k=-2*np.pi/24.
|
||||||
|
offset = 6*k + 3*k #-pi/2
|
||||||
|
xarra_1 = np.array([37*np.cos(k*i+offset) for i in np.arange(0,24)])
|
||||||
|
yarra_1 = np.array([37*np.sin(k*i+offset) for i in np.arange(0,24)])
|
||||||
|
|
||||||
|
#cathodes, plane 1 at -zmax/2
|
||||||
|
kc=2*np.pi/24.
|
||||||
|
offsetc = -4*kc + 2*kc - np.pi/24 #-pi/4
|
||||||
|
xarrc_1 = np.array([42*np.cos(kc*i+offsetc) for i in np.arange(0,24)])
|
||||||
|
yarrc_1 = np.array([42*np.sin(kc*i+offsetc) for i in np.arange(0,24)])
|
||||||
|
|
||||||
|
#anodes, plane 2 at +zmax/2
|
||||||
|
offset = offset-3*k
|
||||||
|
xarra_2 = np.array([37*np.cos(k*i+offset) for i in np.arange(0,24)])
|
||||||
|
yarra_2 = np.array([37*np.sin(k*i+offset) for i in np.arange(0,24)])
|
||||||
|
|
||||||
|
#cathodes, plane2 at +zmax/2
|
||||||
|
offsetc = offsetc-3*kc
|
||||||
|
xarrc_2 = np.array([42*np.cos(kc*i+offsetc) for i in np.arange(0,24)])
|
||||||
|
yarrc_2 = np.array([42*np.sin(kc*i+offsetc) for i in np.arange(0,24)])
|
||||||
|
|
||||||
|
wire_radius = 0.254 #mm
|
||||||
|
anode_wires = []
|
||||||
|
cathode_wires = []
|
||||||
|
aw_tags = [(3,i) for i in range(24)]
|
||||||
|
cw_tags = [(3,i+24) for i in range(24)]
|
||||||
|
|
||||||
|
for i,[xa,ya,xc,yc,xa2,ya2,xc2,yc2] in enumerate(zip(xarra_1,yarra_1,xarrc_1,yarrc_1,xarra_2,yarra_2,xarrc_2,yarrc_2)):
|
||||||
|
print(i,xa,ya,-178.3,xc,yc,-178.3,xa2,ya2,178.3,xc2,yc2,178.3)
|
||||||
|
pa1 = gmsh.model.occ.addPoint(xa,ya,-178.3,lc)
|
||||||
|
pa2 = gmsh.model.occ.addPoint(xa2,ya2,178.3,lc)
|
||||||
|
pc1 = gmsh.model.occ.addPoint(xc,yc,-178.3,lc)
|
||||||
|
pc2 = gmsh.model.occ.addPoint(xc2,yc2,178.3,lc)
|
||||||
|
linea = gmsh.model.occ.addLine(pa1,pa2)
|
||||||
|
linec = gmsh.model.occ.addLine(pc1,pc2)
|
||||||
|
anode_wires.append(linea)
|
||||||
|
cathode_wires.append(linec)
|
||||||
|
|
||||||
|
#anasen_barrel = gmsh.model.occ.addCylinder(0,0,-500,0,0,500+605,300,1234) #tag 1234
|
||||||
|
anasen_barrel = gmsh.model.occ.addCylinder(0,0,-200, 0,0,400, 300) #tag 1234
|
||||||
|
|
||||||
|
gmsh.model.occ.synchronize()
|
||||||
|
gmsh.model.mesh.embed(1,anode_wires+cathode_wires,3,anasen_barrel)
|
||||||
|
|
||||||
|
f1 = gmsh.model.mesh.field.add("Distance")
|
||||||
|
gmsh.model.mesh.field.setNumbers(f1,"CurvesList",anode_wires+cathode_wires)
|
||||||
|
|
||||||
|
f2 = gmsh.model.mesh.field.add("Threshold")
|
||||||
|
gmsh.model.mesh.field.setNumber(f2,"InField",f1)
|
||||||
|
gmsh.model.mesh.field.setNumber(f2,"SizeMin",0.08)
|
||||||
|
gmsh.model.mesh.field.setNumber(f2,"SizeMax",5)
|
||||||
|
gmsh.model.mesh.field.setNumber(f2,"DistMin",1)
|
||||||
|
gmsh.model.mesh.field.setNumber(f2,"DistMax",20)
|
||||||
|
|
||||||
|
gmsh.model.mesh.field.setAsBackgroundMesh(f2)
|
||||||
|
|
||||||
|
gmsh.model.addPhysicalGroup(1, anode_wires, tag=10)
|
||||||
|
gmsh.model.setPhysicalName(1,10,"anode_wires")
|
||||||
|
|
||||||
|
gmsh.model.addPhysicalGroup(1, cathode_wires, tag=20)
|
||||||
|
gmsh.model.setPhysicalName(1,20,"cathode_wires")
|
||||||
|
|
||||||
|
gmsh.option.setNumber("Mesh.Algorithm",6)
|
||||||
|
gmsh.option.setNumber("Mesh.Algorithm3D", 10) # For 3D meshes
|
||||||
|
|
||||||
|
gmsh.model.mesh.generate(dim=3)
|
||||||
|
gmsh.model.mesh.refine()
|
||||||
|
#gmsh.model.mesh.refine()
|
||||||
|
#gmsh.model.mesh.refine()
|
||||||
|
gmsh.fltk.run()
|
||||||
|
gmsh.finalize()
|
||||||
BIN
anasen_fem/output.gif
Normal file
BIN
anasen_fem/output.gif
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.8 MiB |
62
anasen_fem/paraview_plotter.py
Executable file
62
anasen_fem/paraview_plotter.py
Executable file
|
|
@ -0,0 +1,62 @@
|
||||||
|
#!/home/sud/Downloads/ParaView-6.1.0-RC1-MPI-Linux-Python3.12-x86_64/bin/pvbatch
|
||||||
|
import numpy as np
|
||||||
|
import sys
|
||||||
|
from paraview.simple import *
|
||||||
|
|
||||||
|
reader = XMLUnstructuredGridReader(FileName=["wires2d/elfield_anasen_t0001.vtu"])
|
||||||
|
|
||||||
|
contour_filter = Contour(Input=reader,ContourBy = 'potential')
|
||||||
|
contour_filter.Isosurfaces = [i for i in np.arange(0,660,650/24.)]
|
||||||
|
|
||||||
|
renderView = GetActiveViewOrCreate('RenderView')
|
||||||
|
renderView.ViewSize = [800,800]
|
||||||
|
renderView.OrientationAxesVisibility = 0 # Hide axis
|
||||||
|
renderView.UseColorPaletteForBackground=0
|
||||||
|
renderView.Background = [0.1, 0.1, 0.1] # Set background to dark gray (RGB 0-1)
|
||||||
|
|
||||||
|
renderView.MultiSamples = 8 # 0 disables it, 4-8 is usually sufficient
|
||||||
|
|
||||||
|
ResetCamera()
|
||||||
|
|
||||||
|
contour_display = Show(contour_filter, renderView)
|
||||||
|
|
||||||
|
#colorbar
|
||||||
|
contour_display_potentialLUT = GetColorTransferFunction('potential', contour_display, separate=True)
|
||||||
|
contour_display_potentialLUT.ApplyPreset('Cool to Warm', True)
|
||||||
|
contour_display.SetScalarBarVisibility(renderView, True)
|
||||||
|
|
||||||
|
#axesGrid = renderView.AxesGrid
|
||||||
|
#axesGrid.Visibility = 1
|
||||||
|
#axesGrid.XTitle = "x (mm)"
|
||||||
|
#axesGrid.YTitle = "y (mm)"
|
||||||
|
|
||||||
|
# 1. Get the active view
|
||||||
|
view = GetActiveView()
|
||||||
|
|
||||||
|
# 2. Define your desired coordinate ranges (x_min, x_max, y_min, y_max, z_min, z_max)
|
||||||
|
# Example: Look at a box from -10 to 10 in all dimensions
|
||||||
|
x_min, x_max = -50.0, 50.0
|
||||||
|
y_min, y_max = -50.0, 50.0
|
||||||
|
z_min, z_max = -50.0, 50.0
|
||||||
|
|
||||||
|
# 3. Calculate Center, Position, and Parallel Scale
|
||||||
|
center = [(x_min + x_max) / 2.0, (y_min + y_max) / 2.0, (z_min + z_max) / 2.0]
|
||||||
|
# Position the camera far away along Z to look at the center
|
||||||
|
position = [center[0], center[1], z_min - 30.0]
|
||||||
|
# Parallel scale defines how much of the scene is visible.
|
||||||
|
# It is usually half the height of the viewed area.
|
||||||
|
view.CameraParallelScale = max((x_max - x_min), (y_max - y_min))/1.6
|
||||||
|
|
||||||
|
# 4. Apply settings
|
||||||
|
view.CenterOfRotation = center
|
||||||
|
view.CameraPosition = position
|
||||||
|
view.CameraFocalPoint = center
|
||||||
|
view.CameraViewUp = [0.0, 1.0, 0.0] # Y-axis is up
|
||||||
|
|
||||||
|
# 5. Enable Parallel Projection (optional, often better for exact mapping)
|
||||||
|
view.CameraParallelProjection = 1
|
||||||
|
|
||||||
|
#ResetCamera()
|
||||||
|
Render()
|
||||||
|
|
||||||
|
SaveScreenshot("contour_output.png")
|
||||||
15
anasen_fem/run.py
Normal file
15
anasen_fem/run.py
Normal file
|
|
@ -0,0 +1,15 @@
|
||||||
|
import os
|
||||||
|
|
||||||
|
#val=-178.3
|
||||||
|
val=17.83
|
||||||
|
count=11
|
||||||
|
while val<178.3+0.1:
|
||||||
|
print(val)
|
||||||
|
os.system("python3 wires_gmsh2d_bc.py "+str(val))
|
||||||
|
os.system("ElmerGrid 14 2 wires2d.msh")
|
||||||
|
os.system("ElmerSolver wires2d.sif")
|
||||||
|
os.system("./paraview_plotter.py")
|
||||||
|
os.system("cp contour_output.png contour_output_z_%02d_%1.4f.png"%(count,val))
|
||||||
|
val=val+17.83
|
||||||
|
count = count + 1
|
||||||
|
|
||||||
1
anasen_fem/scalars.dat
Normal file
1
anasen_fem/scalars.dat
Normal file
|
|
@ -0,0 +1 @@
|
||||||
|
6.500000000000E+002
|
||||||
8
anasen_fem/scalars.dat.names
Normal file
8
anasen_fem/scalars.dat.names
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
Metadata for SaveScalars file: ./scalars.dat
|
||||||
|
Elmer version: 26.1
|
||||||
|
Elmer compilation date: 2026-03-05
|
||||||
|
Solver input file: wires2d.sif
|
||||||
|
File started at: 2026/03/11 23:33:58
|
||||||
|
|
||||||
|
Variables in columns of matrix:
|
||||||
|
1: res: potential difference
|
||||||
103
anasen_fem/wires2d.sif
Normal file
103
anasen_fem/wires2d.sif
Normal file
|
|
@ -0,0 +1,103 @@
|
||||||
|
Check Keywords Warn
|
||||||
|
|
||||||
|
Header
|
||||||
|
Mesh DB "." "wires2d"
|
||||||
|
End
|
||||||
|
|
||||||
|
Simulation
|
||||||
|
Coordinate System = Cartesian 2D
|
||||||
|
Simulation Type = Steady State
|
||||||
|
Steady State Max Iterations = 1
|
||||||
|
Output File = "elstatics.result"
|
||||||
|
Post File = "elstatics.ep"
|
||||||
|
End
|
||||||
|
|
||||||
|
Constants
|
||||||
|
Permittivity Of Vacuum = 8.8542e-12
|
||||||
|
End
|
||||||
|
|
||||||
|
|
||||||
|
Body 1
|
||||||
|
Target Bodies(1) = 13
|
||||||
|
Equation = 1
|
||||||
|
Material = 1
|
||||||
|
End
|
||||||
|
|
||||||
|
|
||||||
|
Equation 1
|
||||||
|
Active Solvers(2) = 1 2
|
||||||
|
End
|
||||||
|
|
||||||
|
|
||||||
|
Material 1
|
||||||
|
Relative Permittivity = 1
|
||||||
|
End
|
||||||
|
|
||||||
|
|
||||||
|
Solver 1
|
||||||
|
Equation = Electrostatics
|
||||||
|
Procedure = "StatElecSolve" "StatElecSolver"
|
||||||
|
|
||||||
|
Variable = Potential
|
||||||
|
Variable DOFs = 1
|
||||||
|
|
||||||
|
Calculate Electric Field = True
|
||||||
|
Calculate Electric Flux = False
|
||||||
|
|
||||||
|
Linear System Solver = Iterative
|
||||||
|
Linear System Iterative Method = CG
|
||||||
|
Linear System Max Iterations = 5000
|
||||||
|
Linear System Convergence Tolerance = 1.0e-8
|
||||||
|
Linear System Preconditioning = ILU1
|
||||||
|
Calculate Vectors = Logical True
|
||||||
|
End
|
||||||
|
|
||||||
|
Solver 2
|
||||||
|
Equation = "Electric Field"
|
||||||
|
Procedure = "FluxSolver" "FluxSolver"
|
||||||
|
|
||||||
|
! Calculate from the potential
|
||||||
|
Target Variable = "Potential"
|
||||||
|
! Name of the output vector field in VTU
|
||||||
|
Flux Variable = String "Electric Field"
|
||||||
|
|
||||||
|
! Use 2D components (x, y)
|
||||||
|
Flux Coefficient = String "Permittivity"
|
||||||
|
|
||||||
|
Calculate Vectors = Logical True
|
||||||
|
End
|
||||||
|
|
||||||
|
Solver 3
|
||||||
|
Equation = Result Output
|
||||||
|
Procedure = "ResultOutputSolve" "ResultOutputSolver"
|
||||||
|
Output File Name = elfield_anasen ! Sets prefix for output files
|
||||||
|
Output Format = Vtu
|
||||||
|
! Optional: Select specific variables to save
|
||||||
|
Scalar Field 1 = Potential
|
||||||
|
Vector Field 1 = Electric Field
|
||||||
|
End
|
||||||
|
|
||||||
|
Solver 4
|
||||||
|
Exec Solver = After All
|
||||||
|
Equation = SaveScalars
|
||||||
|
Procedure = "SaveData" "SaveScalars"
|
||||||
|
Filename = "scalars.dat"
|
||||||
|
End
|
||||||
|
|
||||||
|
|
||||||
|
Boundary Condition 1
|
||||||
|
Target Boundaries = 10
|
||||||
|
Potential = 650
|
||||||
|
Calculate Electric Force = True
|
||||||
|
End
|
||||||
|
|
||||||
|
|
||||||
|
Boundary Condition 2
|
||||||
|
Target Boundaries = 20
|
||||||
|
Potential = 0
|
||||||
|
End
|
||||||
|
|
||||||
|
!Boundary Condition 2
|
||||||
|
! Target Boundaries = 30
|
||||||
|
! Potential = 0
|
||||||
|
!End
|
||||||
126
anasen_fem/wires_gmsh2d_bc.py
Normal file
126
anasen_fem/wires_gmsh2d_bc.py
Normal file
|
|
@ -0,0 +1,126 @@
|
||||||
|
import numpy as np
|
||||||
|
import gmsh,sys
|
||||||
|
|
||||||
|
gmsh.initialize()
|
||||||
|
gmsh.model.add("adaptive_mesh")
|
||||||
|
gmsh.option.setNumber('General.NumThreads', 4)
|
||||||
|
#gmsh.option.setNumber("Mesh.Adapt.MaxNumberOfElements", 200000)
|
||||||
|
#gmsh.option.setNumber("Mesh.Adapt.MaxNumberOfNodes", 200000)
|
||||||
|
#gmsh.option.setNumber("Mesh.Adapt.MaxIter",5)
|
||||||
|
#gmsh.option.setNumber("Mesh.MeshSizeMin", 5e-3)
|
||||||
|
#gmsh.option.setNumber("Mesh.MeshSizeMax", 10.0)
|
||||||
|
gmsh.option.setNumber("Geometry.Tolerance", 4e-2)
|
||||||
|
#gmsh.option.setNumber("Mesh.MeshSizeExtendFromBoundary", 0)
|
||||||
|
|
||||||
|
lc = 0.04
|
||||||
|
#z_loc = -178.3
|
||||||
|
|
||||||
|
if len(sys.argv) < 2:
|
||||||
|
print("Usage: python3 wires_gmsh2d_bc.py <z_locus in mm>")
|
||||||
|
quit()
|
||||||
|
|
||||||
|
z_loc = float(sys.argv[1])
|
||||||
|
|
||||||
|
k=(2*np.pi/24.)
|
||||||
|
|
||||||
|
#anodes, plane 1 at -zmax/2
|
||||||
|
k=-2*np.pi/24.
|
||||||
|
offset = 6*k + 3*k #-pi/2
|
||||||
|
xarra_1 = np.array([37*np.cos(k*i+offset) for i in np.arange(0,24)])
|
||||||
|
yarra_1 = np.array([37*np.sin(k*i+offset) for i in np.arange(0,24)])
|
||||||
|
|
||||||
|
#cathodes, plane 1 at -zmax/2
|
||||||
|
kc=2*np.pi/24.
|
||||||
|
offsetc = -4*kc + 2*kc - np.pi/24 #-pi/4
|
||||||
|
xarrc_1 = np.array([42*np.cos(kc*i+offsetc) for i in np.arange(0,24)])
|
||||||
|
yarrc_1 = np.array([42*np.sin(kc*i+offsetc) for i in np.arange(0,24)])
|
||||||
|
|
||||||
|
#anodes, plane 2 at +zmax/2
|
||||||
|
offset = offset-3*k
|
||||||
|
xarra_2 = np.array([37*np.cos(k*i+offset) for i in np.arange(0,24)])
|
||||||
|
yarra_2 = np.array([37*np.sin(k*i+offset) for i in np.arange(0,24)])
|
||||||
|
|
||||||
|
#cathodes, plane2 at +zmax/2
|
||||||
|
offsetc = offsetc-3*kc
|
||||||
|
xarrc_2 = np.array([42*np.cos(kc*i+offsetc) for i in np.arange(0,24)])
|
||||||
|
yarrc_2 = np.array([42*np.sin(kc*i+offsetc) for i in np.arange(0,24)])
|
||||||
|
|
||||||
|
direction_anodes_x = xarra_2 - xarra_1
|
||||||
|
direction_anodes_y = yarra_2 - yarra_1
|
||||||
|
|
||||||
|
direction_cathodes_x = xarrc_2 - xarrc_1
|
||||||
|
direction_cathodes_y = yarrc_2 - yarrc_1
|
||||||
|
|
||||||
|
t = (z_loc+178.3)/(2*178.3) #z=-178.3 is 0, z=+178.3 is 1
|
||||||
|
xloc_a = xarra_1 + t*direction_anodes_x
|
||||||
|
yloc_a = yarra_1 + t*direction_anodes_y
|
||||||
|
xloc_c = xarrc_1 + t*direction_cathodes_x
|
||||||
|
yloc_c = yarrc_1 + t*direction_cathodes_y
|
||||||
|
|
||||||
|
wire_radius = 0.254 #mm
|
||||||
|
anode_wires = []
|
||||||
|
cathode_wires = []
|
||||||
|
aw_tags = [(3,i) for i in range(24)]
|
||||||
|
cw_tags = [(3,i+24) for i in range(24)]
|
||||||
|
|
||||||
|
#for i,[xa,ya,xc,yc] in enumerate(zip(xarra_1,yarra_1,xarrc_1,yarrc_1)):
|
||||||
|
for i,[xa,ya,xc,yc] in enumerate(zip(xloc_a,yloc_a,xloc_c,yloc_c)):
|
||||||
|
print(i,xa,ya,-178.3,xc,yc,-178.3)
|
||||||
|
adisk = gmsh.model.occ.addDisk(xa,ya,0,wire_radius,wire_radius)
|
||||||
|
cdisk = gmsh.model.occ.addDisk(xc,yc,0,wire_radius,wire_radius)
|
||||||
|
anode_wires.append(adisk)
|
||||||
|
cathode_wires.append(cdisk)
|
||||||
|
|
||||||
|
anasen_barrel = gmsh.model.occ.addDisk(0,0,0,500,500)
|
||||||
|
#gmsh.model.occ.synchronize()
|
||||||
|
#gmsh.model.mesh.embed(1,anode_wires+cathode_wires,2,anasen_barrel)
|
||||||
|
|
||||||
|
gmsh.option.setNumber("Geometry.Tolerance", 1e-6)
|
||||||
|
gmsh.option.setNumber("Geometry.OCCFixDegenerated", 1)
|
||||||
|
gmsh.model.occ.synchronize()
|
||||||
|
|
||||||
|
awire_surfs = []
|
||||||
|
for w in anode_wires:
|
||||||
|
awire_surfs += [s[1] for s in gmsh.model.getBoundary([(2,w)], oriented=False) if s[0] == 1]
|
||||||
|
|
||||||
|
cwire_surfs = []
|
||||||
|
for w in cathode_wires:
|
||||||
|
cwire_surfs += [s[1] for s in gmsh.model.getBoundary([(2,w)], oriented=False) if s[0] == 1]
|
||||||
|
gmsh.model.mesh.embed(1,cwire_surfs+awire_surfs,2,anasen_barrel)
|
||||||
|
|
||||||
|
for s in gmsh.model.getBoundary([(2,w)],oriented=False):
|
||||||
|
if s[0] == 1:
|
||||||
|
anasen_bdry=s[1]
|
||||||
|
|
||||||
|
|
||||||
|
f1 = gmsh.model.mesh.field.add("Distance")
|
||||||
|
gmsh.model.mesh.field.setNumbers(f1,"CurvesList",cwire_surfs+awire_surfs)
|
||||||
|
|
||||||
|
f2 = gmsh.model.mesh.field.add("Threshold")
|
||||||
|
gmsh.model.mesh.field.setNumber(f2,"InField",f1)
|
||||||
|
gmsh.model.mesh.field.setNumber(f2,"SizeMin",0.1)
|
||||||
|
gmsh.model.mesh.field.setNumber(f2,"SizeMax",5)
|
||||||
|
gmsh.model.mesh.field.setNumber(f2,"DistMin",1)
|
||||||
|
gmsh.model.mesh.field.setNumber(f2,"DistMax",20)
|
||||||
|
|
||||||
|
gmsh.model.mesh.field.setAsBackgroundMesh(f2)
|
||||||
|
|
||||||
|
gmsh.model.addPhysicalGroup(1, awire_surfs, tag=10)
|
||||||
|
gmsh.model.setPhysicalName(1,10,"anode_wires")
|
||||||
|
|
||||||
|
gmsh.model.addPhysicalGroup(1, cwire_surfs, tag=20)
|
||||||
|
gmsh.model.setPhysicalName(1,20,"cathode_wires")
|
||||||
|
|
||||||
|
#gmsh.model.addPhysicalGroup(1, [anasen_bdry], tag=30)
|
||||||
|
#gmsh.model.setPhysicalName(1,30,"barrel_boundary")
|
||||||
|
|
||||||
|
gmsh.model.addPhysicalGroup(2,[anasen_barrel],tag=13)
|
||||||
|
gmsh.model.setPhysicalName(1,13,"gas")
|
||||||
|
|
||||||
|
gmsh.option.setNumber("Mesh.Algorithm", 6)
|
||||||
|
|
||||||
|
gmsh.model.mesh.generate(dim=2)
|
||||||
|
gmsh.model.mesh.refine()
|
||||||
|
gmsh.write("wires2d.msh")
|
||||||
|
#gmsh.fltk.run()
|
||||||
|
gmsh.finalize()
|
||||||
97
centroids.txt
Normal file
97
centroids.txt
Normal file
|
|
@ -0,0 +1,97 @@
|
||||||
|
HistogramIndex PeakNumber Centroid Amplitude Sigma
|
||||||
|
0 1 991.118
|
||||||
|
0 2 2026.83
|
||||||
|
0 3 3060.26
|
||||||
|
0 4 4092.45
|
||||||
|
1 1 922.213
|
||||||
|
1 2 1885.55
|
||||||
|
1 3 2845.53
|
||||||
|
1 4 3810.32
|
||||||
|
2 1 955.591
|
||||||
|
2 2 1953.17
|
||||||
|
2 3 2949.37
|
||||||
|
2 4 3950.79
|
||||||
|
3 1 995.787
|
||||||
|
3 2 2036.58
|
||||||
|
3 3 3076.91
|
||||||
|
3 4 4112.05
|
||||||
|
4 1 1017.48
|
||||||
|
4 2 2080.19
|
||||||
|
4 3 3142.24
|
||||||
|
4 4 4206.1
|
||||||
|
5 1 1022.78
|
||||||
|
5 2 2091.21
|
||||||
|
5 3 3158.28
|
||||||
|
5 4 4226.97
|
||||||
|
6 1 1076.22
|
||||||
|
6 2 2203.37
|
||||||
|
6 3 3329.53
|
||||||
|
6 4 4457.69
|
||||||
|
7 1 977.46
|
||||||
|
7 2 1998.02
|
||||||
|
7 3 3017.36
|
||||||
|
7 4 4040.47
|
||||||
|
8 1 1049.74
|
||||||
|
8 2 2144.38
|
||||||
|
8 3 3238.2
|
||||||
|
8 4 4335.25
|
||||||
|
9 1 1000.59
|
||||||
|
9 2 2046.42
|
||||||
|
9 3 3090.29
|
||||||
|
9 4 4129.63
|
||||||
|
10 1 1014.92
|
||||||
|
10 2 2076.16
|
||||||
|
10 3 3134.59
|
||||||
|
10 4 4213.42
|
||||||
|
11 1 1004.85
|
||||||
|
11 2 2052.88
|
||||||
|
11 3 3100.3
|
||||||
|
11 4 4164.75
|
||||||
|
12 1 945.861
|
||||||
|
12 2 1932.49
|
||||||
|
12 3 2917.95
|
||||||
|
12 4 3955.15
|
||||||
|
13 1 998.307
|
||||||
|
13 2 2040.38
|
||||||
|
13 3 3078.76
|
||||||
|
13 4 4135.51
|
||||||
|
14 1 966.429
|
||||||
|
14 2 1972.15
|
||||||
|
14 3 2974.84
|
||||||
|
14 4 4056.41
|
||||||
|
15 1 958.352
|
||||||
|
15 2 1958.64
|
||||||
|
15 3 2957.7
|
||||||
|
15 4 3970.41
|
||||||
|
16 1 970.732
|
||||||
|
16 2 1977.63
|
||||||
|
16 3 2984.97
|
||||||
|
16 4 4002.56
|
||||||
|
17 1 1013.65
|
||||||
|
17 2 2064.9
|
||||||
|
17 3 3114.19
|
||||||
|
17 4 4190.98
|
||||||
|
18 1 975.538
|
||||||
|
18 2 1990.64
|
||||||
|
18 3 3005.46
|
||||||
|
18 4 4048.99
|
||||||
|
19 1 1082.91
|
||||||
|
19 2 2194.08
|
||||||
|
19 3 3303.65
|
||||||
|
19 4 4411.32
|
||||||
|
20 1 912.778
|
||||||
|
20 2 1866.83
|
||||||
|
20 3 2819.21
|
||||||
|
20 4 3781.63
|
||||||
|
21 1 1002.36
|
||||||
|
21 2 1989.95
|
||||||
|
21 3 2975.53
|
||||||
|
21 4 3986.71
|
||||||
|
22 1 1075.38
|
||||||
|
22 2 2144.25
|
||||||
|
22 3 3210.17
|
||||||
|
22 4 4312.84
|
||||||
|
23 1 988.828
|
||||||
|
23 2 2016.35
|
||||||
|
23 3 3044.19
|
||||||
|
23 4 4082.41
|
||||||
89
centroids_edited.txt
Normal file
89
centroids_edited.txt
Normal file
|
|
@ -0,0 +1,89 @@
|
||||||
|
HistogramIndex PeakNumber Centroid Amplitude Sigma
|
||||||
|
1 1 922.213
|
||||||
|
1 2 1885.55
|
||||||
|
1 3 2845.53
|
||||||
|
1 4 3810.32
|
||||||
|
2 1 955.591
|
||||||
|
2 2 1953.17
|
||||||
|
2 3 2949.37
|
||||||
|
2 4 3950.79
|
||||||
|
3 1 995.787
|
||||||
|
3 2 2036.58
|
||||||
|
3 3 3076.91
|
||||||
|
3 4 4112.05
|
||||||
|
4 1 1017.48
|
||||||
|
4 2 2080.19
|
||||||
|
4 3 3142.24
|
||||||
|
4 4 4206.1
|
||||||
|
5 1 1022.78
|
||||||
|
5 2 2091.21
|
||||||
|
5 3 3158.28
|
||||||
|
5 4 4226.97
|
||||||
|
6 1 1076.22
|
||||||
|
6 2 2203.37
|
||||||
|
6 3 3329.53
|
||||||
|
6 4 4457.69
|
||||||
|
7 1 977.46
|
||||||
|
7 2 1998.02
|
||||||
|
7 3 3017.36
|
||||||
|
7 4 4040.47
|
||||||
|
8 1 1049.74
|
||||||
|
8 2 2144.38
|
||||||
|
8 3 3238.2
|
||||||
|
8 4 4335.25
|
||||||
|
9 1 1000.59
|
||||||
|
9 2 2046.42
|
||||||
|
9 3 3090.29
|
||||||
|
9 4 4129.63
|
||||||
|
10 1 1014.92
|
||||||
|
10 2 2076.16
|
||||||
|
10 3 3134.59
|
||||||
|
10 4 4213.42
|
||||||
|
11 1 1004.85
|
||||||
|
11 2 2052.88
|
||||||
|
11 3 3100.3
|
||||||
|
11 4 4164.75
|
||||||
|
12 1 945.861
|
||||||
|
12 2 1932.49
|
||||||
|
12 3 2917.95
|
||||||
|
12 4 3955.15
|
||||||
|
13 1 998.307
|
||||||
|
13 2 2040.38
|
||||||
|
13 3 3078.76
|
||||||
|
13 4 4135.51
|
||||||
|
14 1 966.429
|
||||||
|
14 2 1972.15
|
||||||
|
14 3 2974.84
|
||||||
|
14 4 4056.41
|
||||||
|
15 1 958.352
|
||||||
|
15 2 1958.64
|
||||||
|
15 3 2957.7
|
||||||
|
15 4 3970.41
|
||||||
|
16 1 970.732
|
||||||
|
16 2 1977.63
|
||||||
|
16 3 2984.97
|
||||||
|
16 4 4002.56
|
||||||
|
17 1 1013.65
|
||||||
|
17 2 2064.9
|
||||||
|
17 3 3114.19
|
||||||
|
17 4 4190.98
|
||||||
|
18 1 975.538
|
||||||
|
18 2 1990.64
|
||||||
|
18 3 3005.46
|
||||||
|
18 4 4048.99
|
||||||
|
20 1 912.778
|
||||||
|
20 2 1866.83
|
||||||
|
20 3 2819.21
|
||||||
|
20 4 3781.63
|
||||||
|
21 1 1002.36
|
||||||
|
21 2 1989.95
|
||||||
|
21 3 2975.53
|
||||||
|
21 4 3986.71
|
||||||
|
22 1 1075.38
|
||||||
|
22 2 2144.25
|
||||||
|
22 3 3210.17
|
||||||
|
22 4 4312.84
|
||||||
|
23 1 988.828
|
||||||
|
23 2 2016.35
|
||||||
|
23 3 3044.19
|
||||||
|
23 4 4082.41
|
||||||
32
cutlist.txt
Normal file
32
cutlist.txt
Normal file
|
|
@ -0,0 +1,32 @@
|
||||||
|
results/anode_strip_diagonalCut1.root anode_sx3_diag1
|
||||||
|
results/anode_strip_diagonalCut2.root anode_sx3_diag2
|
||||||
|
results/anode_wedge_diagonalCut1.root anode_qqq_diag1
|
||||||
|
results/anode_wedge_diagonalCut2.root anode_qqq_diag2
|
||||||
|
cuts/alphas_anode_qqq.root anode_qqq_alphas_27Al
|
||||||
|
cuts/mystery_gate.root mystery_gate
|
||||||
|
cuts/anodecuts_27Al/anode01_up.root anodeup00
|
||||||
|
cuts/anodecuts_27Al/anode01_up.root anodeup01
|
||||||
|
cuts/anodecuts_27Al/anode02_up.root anodeup02
|
||||||
|
cuts/anodecuts_27Al/anode03_up.root anodeup03
|
||||||
|
cuts/anodecuts_27Al/anode04_up.root anodeup04
|
||||||
|
cuts/anodecuts_27Al/anode05_up.root anodeup05
|
||||||
|
cuts/anodecuts_27Al/anode06_up.root anodeup06
|
||||||
|
cuts/anodecuts_27Al/anode07_up.root anodeup07
|
||||||
|
cuts/anodecuts_27Al/anode08_up.root anodeup08
|
||||||
|
cuts/anodecuts_27Al/anode09_up.root anodeup09
|
||||||
|
cuts/anodecuts_27Al/anode10_up.root anodeup10
|
||||||
|
cuts/anodecuts_27Al/anode11_up.root anodeup11
|
||||||
|
cuts/anodecuts_27Al/anode12_up.root anodeup12
|
||||||
|
cuts/anodecuts_27Al/anode13_up.root anodeup13
|
||||||
|
cuts/anodecuts_27Al/anode14_up.root anodeup14
|
||||||
|
cuts/anodecuts_27Al/anode15_up.root anodeup15
|
||||||
|
cuts/anodecuts_27Al/anode15_up.root anodeup16
|
||||||
|
cuts/anodecuts_27Al/anode17_up.root anodeup17
|
||||||
|
cuts/anodecuts_27Al/anode18_up.root anodeup18
|
||||||
|
cuts/anodecuts_27Al/anode19_up.root anodeup19
|
||||||
|
cuts/anodecuts_27Al/anode20_up.root anodeup20
|
||||||
|
cuts/anodecuts_27Al/anode21_up.root anodeup21
|
||||||
|
cuts/anodecuts_27Al/anode22_up.root anodeup22
|
||||||
|
cuts/anodecuts_27Al/anode23_up.root anodeup23
|
||||||
|
cuts/17F_dt_Cathode_QQQ_cut.root 17Fcathode_dt_QQQ
|
||||||
|
cuts/17F_dt_Anode_QQQ_cut.root 17Fanode_dt_QQQ
|
||||||
1109
elog/elogd.cfg
Normal file
1109
elog/elogd.cfg
Normal file
File diff suppressed because it is too large
Load Diff
96
eloss_calculations/Eloss.py
Normal file
96
eloss_calculations/Eloss.py
Normal file
|
|
@ -0,0 +1,96 @@
|
||||||
|
import pycatima as catima
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
# --- 1. Constants ---
|
||||||
|
P_TORR = 250
|
||||||
|
TEMP_K = 293.15
|
||||||
|
R = 8.3144
|
||||||
|
MEV2U = 1.0 / 931.494
|
||||||
|
P_CO2 = 4
|
||||||
|
|
||||||
|
# Gas Density Calculations
|
||||||
|
p_pa = P_TORR * 133.322
|
||||||
|
molar_density = p_pa / (R * TEMP_K)
|
||||||
|
m_he, m_c, m_o= 4.0026, 12.0000, 15.9949
|
||||||
|
m_mix_avg = ((1 - P_CO2 / 100) * m_he) + (P_CO2 / 100 * (m_c + 2*m_o))
|
||||||
|
rho_g_cm3 = (molar_density * m_mix_avg) / 1e6
|
||||||
|
print(f"Gas density at {P_TORR} Torr: {rho_g_cm3:.6e} g/cm^3")
|
||||||
|
|
||||||
|
# --- 2. Material & Step Setup ---
|
||||||
|
material_def = [(m_he, 2, (1 - P_CO2 / 100)), (m_c, 6, P_CO2 / 100), (m_o, 8, 2*P_CO2 / 100)]
|
||||||
|
gas_mix = catima.Material(material_def)
|
||||||
|
gas_mix.density(rho_g_cm3)
|
||||||
|
|
||||||
|
# Thickness step settings
|
||||||
|
step_mg_cm2 = 0.001 # 1 ug/cm2 steps as per your example -- kept fine for
|
||||||
|
# numerical accuracy of the dedx integration itself.
|
||||||
|
step_g_cm2 = step_mg_cm2 / 1000.0
|
||||||
|
max_steps = 1000000000 # Adjust based on how far you want to track
|
||||||
|
|
||||||
|
coarse_step_cm = 0.2 # row spacing over most of the track
|
||||||
|
fine_step_cm = 0.03 # row spacing near the Bragg peak
|
||||||
|
fine_zone_frac = 0.085 # fraction of the *total* range treated as "near the peak"
|
||||||
|
|
||||||
|
def generate_lookup(z, mass_u, e_start_mev, label):
|
||||||
|
filename = f"{label}_lookup_{e_start_mev}MeV_{P_TORR}torr_{P_CO2}pc.dat"
|
||||||
|
header = f"Energy(MeV) \tmg/cm2 \tcm\nStarting Energy: {e_start_mev} MeV"
|
||||||
|
|
||||||
|
# Pass 1: integrate at full precision just to find the total range (needed
|
||||||
|
# to know where the "last fine_zone_frac" of the track begins).
|
||||||
|
projectile = catima.Projectile(mass_u, z)
|
||||||
|
e_u = e_start_mev / mass_u
|
||||||
|
total_thickness_g_cm2 = 0.0
|
||||||
|
while e_u >= 0.0001:
|
||||||
|
projectile.T(e_u)
|
||||||
|
loss_mev = catima.dedx(projectile, gas_mix) * step_g_cm2
|
||||||
|
e_u = (e_u * mass_u - loss_mev) / mass_u
|
||||||
|
total_thickness_g_cm2 += step_g_cm2
|
||||||
|
total_range_cm = total_thickness_g_cm2 / rho_g_cm3
|
||||||
|
fine_zone_start_cm = total_range_cm * (1.0 - fine_zone_frac)
|
||||||
|
|
||||||
|
projectile = catima.Projectile(mass_u, z)
|
||||||
|
current_e_total = e_start_mev
|
||||||
|
current_thickness_g_cm2 = 0.0
|
||||||
|
next_checkpoint_cm = 0.0
|
||||||
|
|
||||||
|
output = []
|
||||||
|
last_dist_cm = None
|
||||||
|
|
||||||
|
def append_row(e_total, thickness_g_cm2, dist_cm):
|
||||||
|
if last_dist_cm is not None and dist_cm <= last_dist_cm:
|
||||||
|
return False
|
||||||
|
output.append([e_total, thickness_g_cm2 * 1000.0, dist_cm])
|
||||||
|
return True
|
||||||
|
|
||||||
|
for i in range(max_steps):
|
||||||
|
dist_cm = current_thickness_g_cm2 / rho_g_cm3
|
||||||
|
if dist_cm >= next_checkpoint_cm:
|
||||||
|
if append_row(current_e_total, current_thickness_g_cm2, dist_cm):
|
||||||
|
last_dist_cm = dist_cm
|
||||||
|
step_cm = fine_step_cm if dist_cm >= fine_zone_start_cm else coarse_step_cm
|
||||||
|
next_checkpoint_cm = dist_cm + step_cm
|
||||||
|
|
||||||
|
e_u = current_e_total / mass_u
|
||||||
|
if e_u < 0.0001: # Stop at ATIMA limit
|
||||||
|
append_row(current_e_total, current_thickness_g_cm2, dist_cm)
|
||||||
|
break
|
||||||
|
|
||||||
|
projectile.T(e_u)
|
||||||
|
# dedx returns MeV / (g/cm2)
|
||||||
|
loss_mev = catima.dedx(projectile, gas_mix) * step_g_cm2
|
||||||
|
|
||||||
|
current_e_total = max(0.0, current_e_total - loss_mev)
|
||||||
|
current_thickness_g_cm2 += step_g_cm2
|
||||||
|
|
||||||
|
np.savetxt(filename, output, fmt='%.6f', delimiter='\t', header=header)
|
||||||
|
print(f"Lookup table created: {filename} ({len(output)} rows, "
|
||||||
|
f"range {total_range_cm:.2f} cm, fine zone below {fine_zone_start_cm:.2f} cm)")
|
||||||
|
|
||||||
|
# --- 3. Run ---
|
||||||
|
# Format: generate_lookup(Z, mass_u, E_start_MeV, label)
|
||||||
|
generate_lookup(1, 1.0078, 30, "proton")
|
||||||
|
generate_lookup(1, 2.01355, 30, "deuteron")
|
||||||
|
generate_lookup(2, 4.0026, 50, "alpha")
|
||||||
|
generate_lookup(13,26.9815, 80, "aluminum")
|
||||||
|
generate_lookup(9,17.0021, 70, "fluorine")
|
||||||
|
generate_lookup(8,15.9949, 70, "oxygen")
|
||||||
15189
eloss_calculations/alpha_lookup_50MeV_250torr_3pc.dat
Normal file
15189
eloss_calculations/alpha_lookup_50MeV_250torr_3pc.dat
Normal file
File diff suppressed because it is too large
Load Diff
14328
eloss_calculations/alpha_lookup_50MeV_250torr_4pc.dat
Normal file
14328
eloss_calculations/alpha_lookup_50MeV_250torr_4pc.dat
Normal file
File diff suppressed because it is too large
Load Diff
12596
eloss_calculations/alpha_lookup_50MeV_350torr_3pc.dat
Normal file
12596
eloss_calculations/alpha_lookup_50MeV_350torr_3pc.dat
Normal file
File diff suppressed because it is too large
Load Diff
10527
eloss_calculations/alpha_lookup_50MeV_350torr_4pc.dat
Normal file
10527
eloss_calculations/alpha_lookup_50MeV_350torr_4pc.dat
Normal file
File diff suppressed because it is too large
Load Diff
2432
eloss_calculations/alphas_in_250torr_mix.txt
Normal file
2432
eloss_calculations/alphas_in_250torr_mix.txt
Normal file
File diff suppressed because it is too large
Load Diff
2432
eloss_calculations/alphas_in_250torr_mix_filtered.txt
Normal file
2432
eloss_calculations/alphas_in_250torr_mix_filtered.txt
Normal file
File diff suppressed because it is too large
Load Diff
5474
eloss_calculations/alphas_in_250torr_mix_filtered_6MeV.txt
Normal file
5474
eloss_calculations/alphas_in_250torr_mix_filtered_6MeV.txt
Normal file
File diff suppressed because it is too large
Load Diff
5474
eloss_calculations/alphas_in_250torr_mix_filtered_full.txt
Normal file
5474
eloss_calculations/alphas_in_250torr_mix_filtered_full.txt
Normal file
File diff suppressed because it is too large
Load Diff
397
eloss_calculations/aluminum_lookup_80MeV_250torr_3pc.dat
Normal file
397
eloss_calculations/aluminum_lookup_80MeV_250torr_3pc.dat
Normal file
|
|
@ -0,0 +1,397 @@
|
||||||
|
# Energy(MeV) mg/cm2 cm
|
||||||
|
# Starting Energy: 80 MeV
|
||||||
|
80.000000 0.000000 0.000000
|
||||||
|
79.766654 0.015000 0.210854
|
||||||
|
79.532996 0.030000 0.421708
|
||||||
|
79.299025 0.045000 0.632562
|
||||||
|
79.064738 0.060000 0.843416
|
||||||
|
78.830135 0.075000 1.054270
|
||||||
|
78.595215 0.090000 1.265124
|
||||||
|
78.359976 0.105000 1.475978
|
||||||
|
78.124416 0.120000 1.686832
|
||||||
|
77.888535 0.135000 1.897686
|
||||||
|
77.652331 0.150000 2.108540
|
||||||
|
77.415803 0.165000 2.319394
|
||||||
|
77.178950 0.180000 2.530248
|
||||||
|
76.941769 0.195000 2.741102
|
||||||
|
76.704260 0.210000 2.951956
|
||||||
|
76.466421 0.225000 3.162810
|
||||||
|
76.228251 0.240000 3.373664
|
||||||
|
75.989748 0.255000 3.584518
|
||||||
|
75.750912 0.270000 3.795372
|
||||||
|
75.511739 0.285000 4.006226
|
||||||
|
75.272230 0.300000 4.217080
|
||||||
|
75.032383 0.315000 4.427934
|
||||||
|
74.792195 0.330000 4.638788
|
||||||
|
74.551666 0.345000 4.849642
|
||||||
|
74.310794 0.360000 5.060496
|
||||||
|
74.069578 0.375000 5.271350
|
||||||
|
73.828016 0.390000 5.482204
|
||||||
|
73.586107 0.405000 5.693058
|
||||||
|
73.343848 0.420000 5.903912
|
||||||
|
73.101239 0.435000 6.114766
|
||||||
|
72.858278 0.450000 6.325620
|
||||||
|
72.614963 0.465000 6.536474
|
||||||
|
72.371292 0.480000 6.747328
|
||||||
|
72.127265 0.495000 6.958182
|
||||||
|
71.882879 0.510000 7.169036
|
||||||
|
71.638133 0.525000 7.379890
|
||||||
|
71.393026 0.540000 7.590744
|
||||||
|
71.147555 0.555000 7.801598
|
||||||
|
70.901718 0.570000 8.012452
|
||||||
|
70.655515 0.585000 8.223306
|
||||||
|
70.408943 0.600000 8.434160
|
||||||
|
70.162001 0.615000 8.645014
|
||||||
|
69.914687 0.630000 8.855868
|
||||||
|
69.666999 0.645000 9.066722
|
||||||
|
69.418936 0.660000 9.277576
|
||||||
|
69.170496 0.675000 9.488430
|
||||||
|
68.921676 0.690000 9.699284
|
||||||
|
68.672475 0.705000 9.910138
|
||||||
|
68.422892 0.720000 10.120992
|
||||||
|
68.172925 0.735000 10.331846
|
||||||
|
67.922571 0.750000 10.542700
|
||||||
|
67.671828 0.765000 10.753554
|
||||||
|
67.420696 0.780000 10.964408
|
||||||
|
67.169172 0.795000 11.175262
|
||||||
|
66.917254 0.810000 11.386116
|
||||||
|
66.664939 0.825000 11.596970
|
||||||
|
66.412227 0.840000 11.807825
|
||||||
|
66.159116 0.855000 12.018679
|
||||||
|
65.905602 0.870000 12.229533
|
||||||
|
65.651685 0.885000 12.440387
|
||||||
|
65.397362 0.900000 12.651241
|
||||||
|
65.142631 0.915000 12.862095
|
||||||
|
64.887491 0.930000 13.072949
|
||||||
|
64.631938 0.945000 13.283803
|
||||||
|
64.375971 0.960000 13.494657
|
||||||
|
64.119588 0.975000 13.705511
|
||||||
|
63.862787 0.990000 13.916365
|
||||||
|
63.605566 1.005000 14.127219
|
||||||
|
63.347922 1.020000 14.338073
|
||||||
|
63.089853 1.035000 14.548927
|
||||||
|
62.831356 1.050000 14.759781
|
||||||
|
62.572431 1.065000 14.970635
|
||||||
|
62.313074 1.080000 15.181489
|
||||||
|
62.053284 1.095000 15.392343
|
||||||
|
61.793057 1.110000 15.603197
|
||||||
|
61.532392 1.125000 15.814051
|
||||||
|
61.271286 1.140000 16.024905
|
||||||
|
61.009737 1.155000 16.235759
|
||||||
|
60.747742 1.170000 16.446613
|
||||||
|
60.485299 1.185000 16.657467
|
||||||
|
60.222406 1.200000 16.868321
|
||||||
|
59.959060 1.215000 17.079175
|
||||||
|
59.695259 1.230000 17.290029
|
||||||
|
59.431000 1.245000 17.500883
|
||||||
|
59.166280 1.260000 17.711737
|
||||||
|
58.901097 1.275000 17.922591
|
||||||
|
58.635449 1.290000 18.133445
|
||||||
|
58.369332 1.305000 18.344299
|
||||||
|
58.102744 1.320000 18.555153
|
||||||
|
57.835683 1.335000 18.766007
|
||||||
|
57.568146 1.350000 18.976861
|
||||||
|
57.300129 1.365000 19.187715
|
||||||
|
57.031631 1.380000 19.398569
|
||||||
|
56.762648 1.395000 19.609423
|
||||||
|
56.493177 1.410000 19.820277
|
||||||
|
56.223216 1.425000 20.031131
|
||||||
|
55.952762 1.440000 20.241985
|
||||||
|
55.681811 1.455000 20.452839
|
||||||
|
55.410362 1.470000 20.663693
|
||||||
|
55.138410 1.485000 20.874547
|
||||||
|
54.865953 1.500000 21.085401
|
||||||
|
54.592988 1.515000 21.296255
|
||||||
|
54.319511 1.530000 21.507109
|
||||||
|
54.045519 1.545000 21.717963
|
||||||
|
53.771010 1.560000 21.928817
|
||||||
|
53.495980 1.575000 22.139671
|
||||||
|
53.220426 1.590000 22.350525
|
||||||
|
52.944344 1.605000 22.561379
|
||||||
|
52.667731 1.620000 22.772233
|
||||||
|
52.390583 1.635000 22.983087
|
||||||
|
52.112898 1.650000 23.193941
|
||||||
|
51.834672 1.665000 23.404795
|
||||||
|
51.555901 1.680000 23.615649
|
||||||
|
51.276581 1.695000 23.826503
|
||||||
|
50.996710 1.710000 24.037357
|
||||||
|
50.716282 1.725000 24.248211
|
||||||
|
50.435296 1.740000 24.459065
|
||||||
|
50.153746 1.755000 24.669919
|
||||||
|
49.871629 1.770000 24.880773
|
||||||
|
49.588941 1.785000 25.091627
|
||||||
|
49.305678 1.800000 25.302481
|
||||||
|
49.021837 1.815000 25.513335
|
||||||
|
48.737412 1.830000 25.724189
|
||||||
|
48.452400 1.845000 25.935043
|
||||||
|
48.166797 1.860000 26.145897
|
||||||
|
47.880599 1.875000 26.356751
|
||||||
|
47.593801 1.890000 26.567605
|
||||||
|
47.306399 1.905000 26.778459
|
||||||
|
47.018388 1.920000 26.989313
|
||||||
|
46.729764 1.935000 27.200167
|
||||||
|
46.440522 1.950000 27.411021
|
||||||
|
46.150658 1.965000 27.621875
|
||||||
|
45.860166 1.980000 27.832729
|
||||||
|
45.569043 1.995000 28.043583
|
||||||
|
45.277283 2.010000 28.254437
|
||||||
|
44.984881 2.025000 28.465291
|
||||||
|
44.691832 2.040000 28.676145
|
||||||
|
44.398131 2.055000 28.886999
|
||||||
|
44.103773 2.070000 29.097853
|
||||||
|
43.808752 2.085000 29.308707
|
||||||
|
43.513062 2.100000 29.519561
|
||||||
|
43.216700 2.115000 29.730415
|
||||||
|
42.919657 2.130000 29.941269
|
||||||
|
42.621930 2.145000 30.152123
|
||||||
|
42.323512 2.160000 30.362977
|
||||||
|
42.024397 2.175000 30.573831
|
||||||
|
41.724578 2.190000 30.784685
|
||||||
|
41.424051 2.205000 30.995539
|
||||||
|
41.122807 2.220000 31.206393
|
||||||
|
40.820842 2.235000 31.417247
|
||||||
|
40.518147 2.250000 31.628101
|
||||||
|
40.214717 2.265000 31.838955
|
||||||
|
39.910545 2.280000 32.049809
|
||||||
|
39.605623 2.295000 32.260663
|
||||||
|
39.299944 2.310000 32.471517
|
||||||
|
38.993500 2.325000 32.682371
|
||||||
|
38.686285 2.340000 32.893225
|
||||||
|
38.378291 2.355000 33.104079
|
||||||
|
38.069508 2.370000 33.314933
|
||||||
|
37.759930 2.385000 33.525787
|
||||||
|
37.449548 2.400000 33.736641
|
||||||
|
37.138353 2.415000 33.947495
|
||||||
|
36.826337 2.430000 34.158349
|
||||||
|
36.513491 2.445000 34.369203
|
||||||
|
36.199805 2.460000 34.580057
|
||||||
|
35.885269 2.475000 34.790911
|
||||||
|
35.569875 2.490000 35.001765
|
||||||
|
35.253612 2.505000 35.212619
|
||||||
|
34.936469 2.520000 35.423474
|
||||||
|
34.618436 2.535000 35.634328
|
||||||
|
34.299503 2.550000 35.845182
|
||||||
|
33.979657 2.565000 36.056036
|
||||||
|
33.658887 2.580000 36.266890
|
||||||
|
33.337182 2.595000 36.477744
|
||||||
|
33.014528 2.610000 36.688598
|
||||||
|
32.690914 2.625000 36.899452
|
||||||
|
32.366325 2.640000 37.110306
|
||||||
|
32.040748 2.655000 37.321160
|
||||||
|
31.714169 2.670000 37.532014
|
||||||
|
31.386576 2.685000 37.742868
|
||||||
|
31.058108 2.700000 37.953722
|
||||||
|
30.728863 2.715000 38.164576
|
||||||
|
30.398840 2.730000 38.375430
|
||||||
|
30.068036 2.745000 38.586284
|
||||||
|
29.736448 2.760000 38.797138
|
||||||
|
29.404071 2.775000 39.007992
|
||||||
|
29.070902 2.790000 39.218846
|
||||||
|
28.736938 2.805000 39.429700
|
||||||
|
28.402175 2.820000 39.640554
|
||||||
|
28.066610 2.835000 39.851408
|
||||||
|
27.730240 2.850000 40.062262
|
||||||
|
27.393061 2.865000 40.273116
|
||||||
|
27.055071 2.880000 40.483970
|
||||||
|
26.716265 2.895000 40.694824
|
||||||
|
26.376641 2.910000 40.905678
|
||||||
|
26.036197 2.925000 41.116532
|
||||||
|
25.694928 2.940000 41.327386
|
||||||
|
25.352833 2.955000 41.538240
|
||||||
|
25.009908 2.970000 41.749094
|
||||||
|
24.666151 2.985000 41.959948
|
||||||
|
24.321560 3.000000 42.170802
|
||||||
|
23.976132 3.015000 42.381656
|
||||||
|
23.629866 3.030000 42.592510
|
||||||
|
23.282758 3.045000 42.803364
|
||||||
|
22.934808 3.060000 43.014218
|
||||||
|
22.586015 3.075000 43.225072
|
||||||
|
22.236376 3.090000 43.435926
|
||||||
|
21.885892 3.105000 43.646780
|
||||||
|
21.534561 3.120000 43.857634
|
||||||
|
21.182384 3.135000 44.068488
|
||||||
|
20.829361 3.150000 44.279342
|
||||||
|
20.475493 3.165000 44.490196
|
||||||
|
20.120781 3.180000 44.701050
|
||||||
|
19.765227 3.195000 44.911904
|
||||||
|
19.408835 3.210000 45.122758
|
||||||
|
19.051609 3.225000 45.333612
|
||||||
|
18.693552 3.240000 45.544466
|
||||||
|
18.334793 3.255000 45.755320
|
||||||
|
17.975875 3.270000 45.966174
|
||||||
|
17.616919 3.285000 46.177028
|
||||||
|
17.257970 3.300000 46.387882
|
||||||
|
16.899079 3.315000 46.598736
|
||||||
|
16.540297 3.330000 46.809590
|
||||||
|
16.181683 3.345000 47.020444
|
||||||
|
15.823299 3.360000 47.231298
|
||||||
|
15.465212 3.375000 47.442152
|
||||||
|
15.107493 3.390000 47.653006
|
||||||
|
14.750223 3.405000 47.863860
|
||||||
|
14.393487 3.420000 48.074714
|
||||||
|
14.037378 3.435000 48.285568
|
||||||
|
13.681997 3.450000 48.496422
|
||||||
|
13.327455 3.465000 48.707276
|
||||||
|
12.973871 3.480000 48.918130
|
||||||
|
12.621377 3.495000 49.128984
|
||||||
|
12.270117 3.510000 49.339838
|
||||||
|
11.920246 3.525000 49.550692
|
||||||
|
11.571935 3.540000 49.761546
|
||||||
|
11.225370 3.555000 49.972400
|
||||||
|
10.880755 3.570000 50.183254
|
||||||
|
10.538310 3.585000 50.394108
|
||||||
|
10.198276 3.600000 50.604962
|
||||||
|
9.860913 3.615000 50.815816
|
||||||
|
9.526502 3.630000 51.026670
|
||||||
|
9.194786 3.645000 51.237524
|
||||||
|
8.864425 3.660000 51.448378
|
||||||
|
8.535501 3.675000 51.659232
|
||||||
|
8.208281 3.690000 51.870086
|
||||||
|
7.883066 3.705000 52.080940
|
||||||
|
7.560188 3.720000 52.291794
|
||||||
|
7.240018 3.735000 52.502648
|
||||||
|
6.922960 3.750000 52.713502
|
||||||
|
6.609459 3.765000 52.924356
|
||||||
|
6.299994 3.780000 53.135210
|
||||||
|
5.995077 3.795000 53.346064
|
||||||
|
5.695251 3.810000 53.556918
|
||||||
|
5.401081 3.825000 53.767772
|
||||||
|
5.113148 3.840000 53.978626
|
||||||
|
4.832038 3.855000 54.189480
|
||||||
|
4.558329 3.870000 54.400334
|
||||||
|
4.292583 3.885000 54.611188
|
||||||
|
4.035323 3.900000 54.822042
|
||||||
|
3.787028 3.915000 55.032896
|
||||||
|
3.548111 3.930000 55.243750
|
||||||
|
3.318917 3.945000 55.454604
|
||||||
|
3.099704 3.960000 55.665458
|
||||||
|
2.890645 3.975000 55.876312
|
||||||
|
2.691822 3.990000 56.087166
|
||||||
|
2.503225 4.005000 56.298020
|
||||||
|
2.324760 4.020000 56.508874
|
||||||
|
2.156254 4.035000 56.719728
|
||||||
|
1.997466 4.050000 56.930582
|
||||||
|
1.966849 4.053000 56.972753
|
||||||
|
1.936606 4.056000 57.014924
|
||||||
|
1.906734 4.059000 57.057095
|
||||||
|
1.877231 4.062000 57.099266
|
||||||
|
1.848094 4.065000 57.141436
|
||||||
|
1.819319 4.068000 57.183607
|
||||||
|
1.790904 4.071000 57.225778
|
||||||
|
1.762846 4.074000 57.267949
|
||||||
|
1.735142 4.077000 57.310120
|
||||||
|
1.707788 4.080000 57.352290
|
||||||
|
1.680781 4.083000 57.394461
|
||||||
|
1.654118 4.086000 57.436632
|
||||||
|
1.627796 4.089000 57.478803
|
||||||
|
1.601811 4.092000 57.520974
|
||||||
|
1.576161 4.095000 57.563144
|
||||||
|
1.550841 4.098000 57.605315
|
||||||
|
1.525848 4.101000 57.647486
|
||||||
|
1.501179 4.104000 57.689657
|
||||||
|
1.476831 4.107000 57.731828
|
||||||
|
1.452799 4.110000 57.773998
|
||||||
|
1.429081 4.113000 57.816169
|
||||||
|
1.405673 4.116000 57.858340
|
||||||
|
1.382572 4.119000 57.900511
|
||||||
|
1.359773 4.122000 57.942682
|
||||||
|
1.337274 4.125000 57.984852
|
||||||
|
1.315070 4.128000 58.027023
|
||||||
|
1.293159 4.131000 58.069194
|
||||||
|
1.271536 4.134000 58.111365
|
||||||
|
1.250199 4.137000 58.153536
|
||||||
|
1.229144 4.140000 58.195706
|
||||||
|
1.208367 4.143000 58.237877
|
||||||
|
1.187864 4.146000 58.280048
|
||||||
|
1.167633 4.149000 58.322219
|
||||||
|
1.147669 4.152000 58.364390
|
||||||
|
1.127970 4.155000 58.406560
|
||||||
|
1.108531 4.158000 58.448731
|
||||||
|
1.089349 4.161000 58.490902
|
||||||
|
1.070422 4.164000 58.533073
|
||||||
|
1.051744 4.167000 58.575244
|
||||||
|
1.033314 4.170000 58.617414
|
||||||
|
1.015128 4.173000 58.659585
|
||||||
|
0.997181 4.176000 58.701756
|
||||||
|
0.979472 4.179000 58.743927
|
||||||
|
0.961996 4.182000 58.786098
|
||||||
|
0.944750 4.185000 58.828269
|
||||||
|
0.927731 4.188000 58.870439
|
||||||
|
0.910936 4.191000 58.912610
|
||||||
|
0.894362 4.194000 58.954781
|
||||||
|
0.878005 4.197000 58.996952
|
||||||
|
0.861861 4.200000 59.039123
|
||||||
|
0.845928 4.203000 59.081293
|
||||||
|
0.830203 4.206000 59.123464
|
||||||
|
0.814682 4.209000 59.165635
|
||||||
|
0.799363 4.212000 59.207806
|
||||||
|
0.784243 4.215000 59.249977
|
||||||
|
0.769318 4.218000 59.292147
|
||||||
|
0.754585 4.221000 59.334318
|
||||||
|
0.740042 4.224000 59.376489
|
||||||
|
0.725685 4.227000 59.418660
|
||||||
|
0.711512 4.230000 59.460831
|
||||||
|
0.697520 4.233000 59.503001
|
||||||
|
0.683705 4.236000 59.545172
|
||||||
|
0.670065 4.239000 59.587343
|
||||||
|
0.656575 4.242000 59.629514
|
||||||
|
0.643192 4.245000 59.671685
|
||||||
|
0.629914 4.248000 59.713855
|
||||||
|
0.616739 4.251000 59.756026
|
||||||
|
0.603668 4.254000 59.798197
|
||||||
|
0.590700 4.257000 59.840368
|
||||||
|
0.577834 4.260000 59.882539
|
||||||
|
0.565071 4.263000 59.924709
|
||||||
|
0.552409 4.266000 59.966880
|
||||||
|
0.539832 4.269000 60.009051
|
||||||
|
0.527356 4.272000 60.051222
|
||||||
|
0.514979 4.275000 60.093393
|
||||||
|
0.502701 4.278000 60.135563
|
||||||
|
0.490522 4.281000 60.177734
|
||||||
|
0.478441 4.284000 60.219905
|
||||||
|
0.466456 4.287000 60.262076
|
||||||
|
0.454569 4.290000 60.304247
|
||||||
|
0.442777 4.293000 60.346417
|
||||||
|
0.431080 4.296000 60.388588
|
||||||
|
0.419478 4.299000 60.430759
|
||||||
|
0.407969 4.302000 60.472930
|
||||||
|
0.396553 4.305000 60.515101
|
||||||
|
0.385226 4.308000 60.557271
|
||||||
|
0.373989 4.311000 60.599442
|
||||||
|
0.362838 4.314000 60.641613
|
||||||
|
0.351775 4.317000 60.683784
|
||||||
|
0.340796 4.320000 60.725955
|
||||||
|
0.329900 4.323000 60.768125
|
||||||
|
0.319087 4.326000 60.810296
|
||||||
|
0.308354 4.329000 60.852467
|
||||||
|
0.297702 4.332000 60.894638
|
||||||
|
0.287129 4.335000 60.936809
|
||||||
|
0.276633 4.338000 60.978979
|
||||||
|
0.266213 4.341000 61.021150
|
||||||
|
0.255866 4.344000 61.063321
|
||||||
|
0.245592 4.347000 61.105492
|
||||||
|
0.235388 4.350000 61.147663
|
||||||
|
0.225252 4.353000 61.189833
|
||||||
|
0.215182 4.356000 61.232004
|
||||||
|
0.205174 4.359000 61.274175
|
||||||
|
0.195225 4.362000 61.316346
|
||||||
|
0.185333 4.365000 61.358517
|
||||||
|
0.175492 4.368000 61.400687
|
||||||
|
0.165698 4.371000 61.442858
|
||||||
|
0.155946 4.374000 61.485029
|
||||||
|
0.146231 4.377000 61.527200
|
||||||
|
0.136544 4.380000 61.569371
|
||||||
|
0.126878 4.383000 61.611541
|
||||||
|
0.117222 4.386000 61.653712
|
||||||
|
0.107566 4.389000 61.695883
|
||||||
|
0.097894 4.392000 61.738054
|
||||||
|
0.088190 4.395000 61.780225
|
||||||
|
0.078430 4.398000 61.822395
|
||||||
|
0.068587 4.401000 61.864566
|
||||||
|
0.058623 4.404000 61.906737
|
||||||
|
0.048489 4.407000 61.948908
|
||||||
|
0.038115 4.410000 61.991079
|
||||||
|
0.027405 4.413000 62.033249
|
||||||
|
0.016227 4.416000 62.075420
|
||||||
|
0.004537 4.419000 62.117591
|
||||||
|
0.000722 4.420000 62.131648
|
||||||
374
eloss_calculations/aluminum_lookup_80MeV_250torr_4pc.dat
Normal file
374
eloss_calculations/aluminum_lookup_80MeV_250torr_4pc.dat
Normal file
|
|
@ -0,0 +1,374 @@
|
||||||
|
# Energy(MeV) mg/cm2 cm
|
||||||
|
# Starting Energy: 80 MeV
|
||||||
|
80.000000 0.000000 0.000000
|
||||||
|
79.747605 0.016000 0.208857
|
||||||
|
79.494846 0.032000 0.417714
|
||||||
|
79.241720 0.048000 0.626571
|
||||||
|
78.988227 0.064000 0.835428
|
||||||
|
78.734364 0.080000 1.044285
|
||||||
|
78.480130 0.096000 1.253142
|
||||||
|
78.225524 0.112000 1.461999
|
||||||
|
77.970543 0.128000 1.670856
|
||||||
|
77.715186 0.144000 1.879713
|
||||||
|
77.459452 0.160000 2.088570
|
||||||
|
77.203338 0.176000 2.297427
|
||||||
|
76.946842 0.192000 2.506284
|
||||||
|
76.689964 0.208000 2.715141
|
||||||
|
76.432701 0.224000 2.923998
|
||||||
|
76.175051 0.240000 3.132855
|
||||||
|
75.917013 0.256000 3.341712
|
||||||
|
75.658585 0.272000 3.550569
|
||||||
|
75.399765 0.288000 3.759426
|
||||||
|
75.140552 0.304000 3.968283
|
||||||
|
74.880942 0.320000 4.177140
|
||||||
|
74.620935 0.336000 4.385997
|
||||||
|
74.360529 0.352000 4.594854
|
||||||
|
74.099722 0.368000 4.803711
|
||||||
|
73.838511 0.384000 5.012568
|
||||||
|
73.576895 0.400000 5.221425
|
||||||
|
73.314872 0.416000 5.430282
|
||||||
|
73.052440 0.432000 5.639139
|
||||||
|
72.789598 0.448000 5.847996
|
||||||
|
72.526342 0.464000 6.056853
|
||||||
|
72.262671 0.480000 6.265710
|
||||||
|
71.998583 0.496000 6.474567
|
||||||
|
71.734076 0.512000 6.683424
|
||||||
|
71.469148 0.528000 6.892281
|
||||||
|
71.203797 0.544000 7.101138
|
||||||
|
70.938020 0.560000 7.309995
|
||||||
|
70.671816 0.576000 7.518852
|
||||||
|
70.405183 0.592000 7.727709
|
||||||
|
70.138117 0.608000 7.936566
|
||||||
|
69.870618 0.624000 8.145423
|
||||||
|
69.602683 0.640000 8.354280
|
||||||
|
69.334309 0.656000 8.563137
|
||||||
|
69.065495 0.672000 8.771994
|
||||||
|
68.796238 0.688000 8.980851
|
||||||
|
68.526536 0.704000 9.189708
|
||||||
|
68.256387 0.720000 9.398565
|
||||||
|
67.985788 0.736000 9.607422
|
||||||
|
67.714737 0.752000 9.816279
|
||||||
|
67.443232 0.768000 10.025136
|
||||||
|
67.171269 0.784000 10.233993
|
||||||
|
66.898848 0.800000 10.442850
|
||||||
|
66.625965 0.816000 10.651707
|
||||||
|
66.352618 0.832000 10.860564
|
||||||
|
66.078805 0.848000 11.069421
|
||||||
|
65.804523 0.864000 11.278278
|
||||||
|
65.529769 0.880000 11.487135
|
||||||
|
65.254541 0.896000 11.695992
|
||||||
|
64.978836 0.912000 11.904849
|
||||||
|
64.702652 0.928000 12.113706
|
||||||
|
64.425986 0.944000 12.322563
|
||||||
|
64.148836 0.960000 12.531420
|
||||||
|
63.871198 0.976000 12.740277
|
||||||
|
63.593071 0.992000 12.949134
|
||||||
|
63.314451 1.008000 13.157991
|
||||||
|
63.035336 1.024000 13.366848
|
||||||
|
62.755722 1.040000 13.575705
|
||||||
|
62.475608 1.056000 13.784562
|
||||||
|
62.194989 1.072000 13.993419
|
||||||
|
61.913864 1.088000 14.202276
|
||||||
|
61.632230 1.104000 14.411133
|
||||||
|
61.350083 1.120000 14.619990
|
||||||
|
61.067420 1.136000 14.828847
|
||||||
|
60.784239 1.152000 15.037704
|
||||||
|
60.500536 1.168000 15.246561
|
||||||
|
60.216309 1.184000 15.455418
|
||||||
|
59.931554 1.200000 15.664275
|
||||||
|
59.646268 1.216000 15.873132
|
||||||
|
59.360448 1.232000 16.081989
|
||||||
|
59.074091 1.248000 16.290846
|
||||||
|
58.787194 1.264000 16.499703
|
||||||
|
58.499752 1.280000 16.708560
|
||||||
|
58.211764 1.296000 16.917417
|
||||||
|
57.923226 1.312000 17.126274
|
||||||
|
57.634133 1.328000 17.335131
|
||||||
|
57.344484 1.344000 17.543988
|
||||||
|
57.054273 1.360000 17.752845
|
||||||
|
56.763499 1.376000 17.961702
|
||||||
|
56.472156 1.392000 18.170559
|
||||||
|
56.180243 1.408000 18.379416
|
||||||
|
55.887754 1.424000 18.588273
|
||||||
|
55.594687 1.440000 18.797130
|
||||||
|
55.301037 1.456000 19.005987
|
||||||
|
55.006801 1.472000 19.214844
|
||||||
|
54.711975 1.488000 19.423701
|
||||||
|
54.416555 1.504000 19.632558
|
||||||
|
54.120537 1.520000 19.841415
|
||||||
|
53.823917 1.536000 20.050272
|
||||||
|
53.526691 1.552000 20.259129
|
||||||
|
53.228855 1.568000 20.467986
|
||||||
|
52.930406 1.584000 20.676843
|
||||||
|
52.631337 1.600000 20.885700
|
||||||
|
52.331646 1.616000 21.094557
|
||||||
|
52.031329 1.632000 21.303414
|
||||||
|
51.730380 1.648000 21.512271
|
||||||
|
51.428795 1.664000 21.721128
|
||||||
|
51.126569 1.680000 21.929985
|
||||||
|
50.823699 1.696000 22.138842
|
||||||
|
50.520180 1.712000 22.347699
|
||||||
|
50.216006 1.728000 22.556556
|
||||||
|
49.911173 1.744000 22.765413
|
||||||
|
49.605677 1.760000 22.974270
|
||||||
|
49.299511 1.776000 23.183127
|
||||||
|
48.992672 1.792000 23.391984
|
||||||
|
48.685154 1.808000 23.600841
|
||||||
|
48.376952 1.824000 23.809698
|
||||||
|
48.068060 1.840000 24.018555
|
||||||
|
47.758474 1.856000 24.227412
|
||||||
|
47.448188 1.872000 24.436269
|
||||||
|
47.137196 1.888000 24.645126
|
||||||
|
46.825493 1.904000 24.853983
|
||||||
|
46.513073 1.920000 25.062840
|
||||||
|
46.199931 1.936000 25.271697
|
||||||
|
45.886059 1.952000 25.480554
|
||||||
|
45.571453 1.968000 25.689411
|
||||||
|
45.256106 1.984000 25.898268
|
||||||
|
44.940012 2.000000 26.107125
|
||||||
|
44.623165 2.016000 26.315982
|
||||||
|
44.305558 2.032000 26.524839
|
||||||
|
43.987184 2.048000 26.733696
|
||||||
|
43.668037 2.064000 26.942553
|
||||||
|
43.348110 2.080000 27.151410
|
||||||
|
43.027396 2.096000 27.360267
|
||||||
|
42.705888 2.112000 27.569124
|
||||||
|
42.383578 2.128000 27.777981
|
||||||
|
42.060459 2.144000 27.986838
|
||||||
|
41.736523 2.160000 28.195695
|
||||||
|
41.411763 2.176000 28.404552
|
||||||
|
41.086171 2.192000 28.613409
|
||||||
|
40.759738 2.208000 28.822266
|
||||||
|
40.432456 2.224000 29.031123
|
||||||
|
40.104317 2.240000 29.239980
|
||||||
|
39.775311 2.256000 29.448837
|
||||||
|
39.445431 2.272000 29.657694
|
||||||
|
39.114666 2.288000 29.866551
|
||||||
|
38.783008 2.304000 30.075408
|
||||||
|
38.450447 2.320000 30.284265
|
||||||
|
38.116972 2.336000 30.493122
|
||||||
|
37.782575 2.352000 30.701979
|
||||||
|
37.447244 2.368000 30.910836
|
||||||
|
37.110968 2.384000 31.119693
|
||||||
|
36.773737 2.400000 31.328550
|
||||||
|
36.435540 2.416000 31.537407
|
||||||
|
36.096364 2.432000 31.746264
|
||||||
|
35.756199 2.448000 31.955121
|
||||||
|
35.415030 2.464000 32.163978
|
||||||
|
35.072847 2.480000 32.372835
|
||||||
|
34.729635 2.496000 32.581692
|
||||||
|
34.385382 2.512000 32.790549
|
||||||
|
34.040072 2.528000 32.999406
|
||||||
|
33.693693 2.544000 33.208263
|
||||||
|
33.346228 2.560000 33.417120
|
||||||
|
32.997663 2.576000 33.625977
|
||||||
|
32.647981 2.592000 33.834834
|
||||||
|
32.297166 2.608000 34.043691
|
||||||
|
31.945201 2.624000 34.252548
|
||||||
|
31.592067 2.640000 34.461405
|
||||||
|
31.237790 2.656000 34.670262
|
||||||
|
30.882573 2.672000 34.879119
|
||||||
|
30.526456 2.688000 35.087976
|
||||||
|
30.169434 2.704000 35.296833
|
||||||
|
29.811505 2.720000 35.505690
|
||||||
|
29.452662 2.736000 35.714547
|
||||||
|
29.092902 2.752000 35.923404
|
||||||
|
28.732221 2.768000 36.132261
|
||||||
|
28.370614 2.784000 36.341118
|
||||||
|
28.008078 2.800000 36.549975
|
||||||
|
27.644608 2.816000 36.758832
|
||||||
|
27.280200 2.832000 36.967689
|
||||||
|
26.914851 2.848000 37.176546
|
||||||
|
26.548557 2.864000 37.385403
|
||||||
|
26.181314 2.880000 37.594260
|
||||||
|
25.813119 2.896000 37.803117
|
||||||
|
25.443967 2.912000 38.011974
|
||||||
|
25.073857 2.928000 38.220831
|
||||||
|
24.702785 2.944000 38.429688
|
||||||
|
24.330748 2.960000 38.638545
|
||||||
|
23.957743 2.976000 38.847402
|
||||||
|
23.583768 2.992000 39.056259
|
||||||
|
23.208820 3.008000 39.265116
|
||||||
|
22.832899 3.024000 39.473973
|
||||||
|
22.456002 3.040000 39.682830
|
||||||
|
22.078128 3.056000 39.891687
|
||||||
|
21.699277 3.072000 40.100544
|
||||||
|
21.319449 3.088000 40.309401
|
||||||
|
20.938644 3.104000 40.518258
|
||||||
|
20.556862 3.120000 40.727115
|
||||||
|
20.174107 3.136000 40.935972
|
||||||
|
19.790381 3.152000 41.144829
|
||||||
|
19.405688 3.168000 41.353686
|
||||||
|
19.020033 3.184000 41.562543
|
||||||
|
18.633422 3.200000 41.771400
|
||||||
|
18.246103 3.216000 41.980257
|
||||||
|
17.858670 3.232000 42.189114
|
||||||
|
17.471218 3.248000 42.397971
|
||||||
|
17.083807 3.264000 42.606828
|
||||||
|
16.696502 3.280000 42.815685
|
||||||
|
16.309372 3.296000 43.024542
|
||||||
|
15.922493 3.312000 43.233399
|
||||||
|
15.535948 3.328000 43.442256
|
||||||
|
15.149825 3.344000 43.651113
|
||||||
|
14.764224 3.360000 43.859970
|
||||||
|
14.379251 3.376000 44.068827
|
||||||
|
13.995023 3.392000 44.277684
|
||||||
|
13.611669 3.408000 44.486541
|
||||||
|
13.229329 3.424000 44.695398
|
||||||
|
12.848157 3.440000 44.904255
|
||||||
|
12.468322 3.456000 45.113112
|
||||||
|
12.090012 3.472000 45.321969
|
||||||
|
11.713430 3.488000 45.530826
|
||||||
|
11.338802 3.504000 45.739683
|
||||||
|
10.966373 3.520000 45.948540
|
||||||
|
10.596414 3.536000 46.157397
|
||||||
|
10.229222 3.552000 46.366254
|
||||||
|
9.865119 3.568000 46.575111
|
||||||
|
9.504457 3.584000 46.783968
|
||||||
|
9.146817 3.600000 46.992825
|
||||||
|
8.790754 3.616000 47.201682
|
||||||
|
8.436442 3.632000 47.410540
|
||||||
|
8.084225 3.648000 47.619397
|
||||||
|
7.734494 3.664000 47.828254
|
||||||
|
7.387683 3.680000 48.037111
|
||||||
|
7.044277 3.696000 48.245968
|
||||||
|
6.704811 3.712000 48.454825
|
||||||
|
6.369869 3.728000 48.663682
|
||||||
|
6.040079 3.744000 48.872539
|
||||||
|
5.716114 3.760000 49.081396
|
||||||
|
5.398677 3.776000 49.290253
|
||||||
|
5.088493 3.792000 49.499110
|
||||||
|
4.786294 3.808000 49.707967
|
||||||
|
4.492802 3.824000 49.916824
|
||||||
|
4.208709 3.840000 50.125681
|
||||||
|
3.934655 3.856000 50.334538
|
||||||
|
3.671213 3.872000 50.543395
|
||||||
|
3.418865 3.888000 50.752252
|
||||||
|
3.177987 3.904000 50.961109
|
||||||
|
2.948841 3.920000 51.169966
|
||||||
|
2.731568 3.936000 51.378823
|
||||||
|
2.526187 3.952000 51.587680
|
||||||
|
2.332600 3.968000 51.796537
|
||||||
|
2.150600 3.984000 52.005394
|
||||||
|
1.979888 4.000000 52.214251
|
||||||
|
1.949107 4.003000 52.253411
|
||||||
|
1.918706 4.006000 52.292572
|
||||||
|
1.888684 4.009000 52.331733
|
||||||
|
1.859036 4.012000 52.370893
|
||||||
|
1.829761 4.015000 52.410054
|
||||||
|
1.800854 4.018000 52.449215
|
||||||
|
1.772314 4.021000 52.488375
|
||||||
|
1.744136 4.024000 52.527536
|
||||||
|
1.716318 4.027000 52.566697
|
||||||
|
1.688856 4.030000 52.605857
|
||||||
|
1.661747 4.033000 52.645018
|
||||||
|
1.634987 4.036000 52.684179
|
||||||
|
1.608574 4.039000 52.723339
|
||||||
|
1.582503 4.042000 52.762500
|
||||||
|
1.556772 4.045000 52.801661
|
||||||
|
1.531376 4.048000 52.840822
|
||||||
|
1.506313 4.051000 52.879982
|
||||||
|
1.481578 4.054000 52.919143
|
||||||
|
1.457168 4.057000 52.958304
|
||||||
|
1.433080 4.060000 52.997464
|
||||||
|
1.409310 4.063000 53.036625
|
||||||
|
1.385853 4.066000 53.075786
|
||||||
|
1.362708 4.069000 53.114946
|
||||||
|
1.339869 4.072000 53.154107
|
||||||
|
1.317334 4.075000 53.193268
|
||||||
|
1.295099 4.078000 53.232428
|
||||||
|
1.273159 4.081000 53.271589
|
||||||
|
1.251512 4.084000 53.310750
|
||||||
|
1.230154 4.087000 53.349911
|
||||||
|
1.209081 4.090000 53.389071
|
||||||
|
1.188289 4.093000 53.428232
|
||||||
|
1.167776 4.096000 53.467393
|
||||||
|
1.147536 4.099000 53.506553
|
||||||
|
1.127567 4.102000 53.545714
|
||||||
|
1.107866 4.105000 53.584875
|
||||||
|
1.088427 4.108000 53.624035
|
||||||
|
1.069249 4.111000 53.663196
|
||||||
|
1.050327 4.114000 53.702357
|
||||||
|
1.031658 4.117000 53.741517
|
||||||
|
1.013238 4.120000 53.780678
|
||||||
|
0.995065 4.123000 53.819839
|
||||||
|
0.977133 4.126000 53.858999
|
||||||
|
0.959441 4.129000 53.898160
|
||||||
|
0.941984 4.132000 53.937321
|
||||||
|
0.924760 4.135000 53.976482
|
||||||
|
0.907764 4.138000 54.015642
|
||||||
|
0.890994 4.141000 54.054803
|
||||||
|
0.874445 4.144000 54.093964
|
||||||
|
0.858115 4.147000 54.133124
|
||||||
|
0.842000 4.150000 54.172285
|
||||||
|
0.826098 4.153000 54.211446
|
||||||
|
0.810405 4.156000 54.250606
|
||||||
|
0.794918 4.159000 54.289767
|
||||||
|
0.779633 4.162000 54.328928
|
||||||
|
0.764548 4.165000 54.368088
|
||||||
|
0.749659 4.168000 54.407249
|
||||||
|
0.734964 4.171000 54.446410
|
||||||
|
0.720459 4.174000 54.485570
|
||||||
|
0.706141 4.177000 54.524731
|
||||||
|
0.692007 4.180000 54.563892
|
||||||
|
0.678055 4.183000 54.603053
|
||||||
|
0.664278 4.186000 54.642213
|
||||||
|
0.650633 4.189000 54.681374
|
||||||
|
0.637097 4.192000 54.720535
|
||||||
|
0.623670 4.195000 54.759695
|
||||||
|
0.610352 4.198000 54.798856
|
||||||
|
0.597142 4.201000 54.838017
|
||||||
|
0.584039 4.204000 54.877177
|
||||||
|
0.571042 4.207000 54.916338
|
||||||
|
0.558152 4.210000 54.955499
|
||||||
|
0.545363 4.213000 54.994659
|
||||||
|
0.532668 4.216000 55.033820
|
||||||
|
0.520077 4.219000 55.072981
|
||||||
|
0.507589 4.222000 55.112141
|
||||||
|
0.495205 4.225000 55.151302
|
||||||
|
0.482922 4.228000 55.190463
|
||||||
|
0.470741 4.231000 55.229624
|
||||||
|
0.458660 4.234000 55.268784
|
||||||
|
0.446679 4.237000 55.307945
|
||||||
|
0.434797 4.240000 55.347106
|
||||||
|
0.423013 4.243000 55.386266
|
||||||
|
0.411327 4.246000 55.425427
|
||||||
|
0.399736 4.249000 55.464588
|
||||||
|
0.388240 4.252000 55.503748
|
||||||
|
0.376834 4.255000 55.542909
|
||||||
|
0.365519 4.258000 55.582070
|
||||||
|
0.354293 4.261000 55.621230
|
||||||
|
0.343153 4.264000 55.660391
|
||||||
|
0.332099 4.267000 55.699552
|
||||||
|
0.321129 4.270000 55.738712
|
||||||
|
0.310242 4.273000 55.777873
|
||||||
|
0.299437 4.276000 55.817034
|
||||||
|
0.288713 4.279000 55.856195
|
||||||
|
0.278067 4.282000 55.895355
|
||||||
|
0.267499 4.285000 55.934516
|
||||||
|
0.257007 4.288000 55.973677
|
||||||
|
0.246589 4.291000 56.012837
|
||||||
|
0.236242 4.294000 56.051998
|
||||||
|
0.225965 4.297000 56.091159
|
||||||
|
0.215754 4.300000 56.130319
|
||||||
|
0.205608 4.303000 56.169480
|
||||||
|
0.195522 4.306000 56.208641
|
||||||
|
0.185494 4.309000 56.247801
|
||||||
|
0.175518 4.312000 56.286962
|
||||||
|
0.165590 4.315000 56.326123
|
||||||
|
0.155705 4.318000 56.365283
|
||||||
|
0.145857 4.321000 56.404444
|
||||||
|
0.136037 4.324000 56.443605
|
||||||
|
0.126238 4.327000 56.482766
|
||||||
|
0.116450 4.330000 56.521926
|
||||||
|
0.106659 4.333000 56.561087
|
||||||
|
0.096850 4.336000 56.600248
|
||||||
|
0.087006 4.339000 56.639408
|
||||||
|
0.077103 4.342000 56.678569
|
||||||
|
0.067110 4.345000 56.717730
|
||||||
|
0.056987 4.348000 56.756890
|
||||||
|
0.046681 4.351000 56.796051
|
||||||
|
0.036116 4.354000 56.835212
|
||||||
|
0.025188 4.357000 56.874372
|
||||||
|
0.013760 4.360000 56.913533
|
||||||
|
0.001928 4.363000 56.952694
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user