Compare commits

..

7 Commits

Author SHA1 Message Date
vs19g 20bf766dc5 modified: .gitignore
modified:   Analyzer.C
2025-01-17 11:09:46 -05:00
vs19g f5a4b750fc Your branch is ahead of 'origin/master' by 1 commit. 2025-01-16 11:29:18 -05:00
vs19g f18b51e334 modified: Analyzer.C added sections for crossover calculation
modified:   Armory/ClassPW.h
	modified:   ProcessRun.sh
2025-01-16 11:27:33 -05:00
vs19g 9bf83f8028 modified: .vscode/settings.json
modified:   Armory/ClassPW.h
2025-01-16 09:56:39 -05:00
vs19g d8b11bdcf3 modified: .vscode/c_cpp_properties.json 2024-06-27 14:57:59 -04:00
vs19g 7a8b64c805 deleted: archivist 2024-06-27 14:34:40 -04:00
vs19g 862c4012eb chore: Adjust range in Analysis() function 2024-06-27 14:26:47 -04:00
36 changed files with 1228 additions and 4812 deletions

6
.gitignore vendored
View File

@ -4,12 +4,10 @@ EventBuilder*
*.pcm
*.root
*.exe
*.txt
Mapper
AnasenMS
data/
data_proton/
Analyzer_C_ACLiC_dict0713aaa966_dictContent.h
.gitignore
Analyzer_C_ACLiC_dict5411fecd5c_dictUmbrella.h
root_data/

View File

@ -59,19 +59,7 @@
"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/**"
"/usr/local/cern/root/include/**",
],
"defines": [],
"compilerPath": "/usr/bin/gcc",

18
.vscode/settings.json vendored
View File

@ -100,23 +100,7 @@
"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"
"Fitting.C": "cpp"
},
"github-enterprise.uri": "https://fsunuc.physics.fsu.edu"
}

View File

@ -16,5 +16,5 @@ void Analysis(int start, int end) {
// Define a macro with the same name as the script
void Analysis() {
Analysis(72, 194); // Adjust the range if needed
Analysis(150, 194); // Adjust the range if needed
}

View File

@ -1,31 +1,26 @@
#define Analyzer_cxx
#include "Analyzer.h"
#include "Armory/ClassSX3.h"
#include "Armory/ClassPW.h"
#include <TH2.h>
#include <TStyle.h>
#include <TCanvas.h>
#include <TMath.h>
#include "TVector3.h"
#include <fstream>
#include <iostream>
#include <sstream>
#include <map>
#include <utility>
#include <algorithm>
#include "Armory/ClassSX3.h"
#include "Armory/ClassPW.h"
#include "TVector3.h"
TH2F *hsx3IndexVE;
TH2F *hqqqIndexVE;
TH2F *hpcIndexVE;
TH2F *hpcIndexVE_GM;
TH2F *hsx3Coin;
TH2F *hqqqCoin;
TH2F *hpcCoin;
TH2F *hAVCcoin;
TH2F *hqqqPolar;
TH2F *hsx3VpcIndex;
@ -33,37 +28,15 @@ TH2F *hqqqVpcIndex;
TH2F *hqqqVpcE;
TH2F *hsx3VpcE;
TH2F *hanVScatsum;
TH2F *hanVScatsum_a[24];
TH1F *hPC_E[48];
TH1F *hCat4An;
TH1F *hCat0An;
TH1F *hAnodehits;
TH2F *hNosvAe;
int padID = 0;
SX3 sx3_contr;
PW pw_contr;
PW pwinstance;
TVector3 hitPos;
// TVector3 anodeIntersection;
std::map<int, std::pair<double, double>> slopeInterceptMap;
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}}}};
bool HitNonZero;
bool sx3ecut;
bool qqqEcut;
TH1F *hZProj;
TH1F *hPCZProj;
void Analyzer::Begin(TTree * /*tree*/)
{
@ -73,15 +46,12 @@ void Analyzer::Begin(TTree * /*tree*/)
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, 16000);
hpcIndexVE = new TH2F("hpcIndexVE", "PC index vs Energy; PC index ; Energy", 2 * 24, 0, 2 * 24, 400, 0, 4000);
hpcIndexVE->SetNdivisions(-1204, "x");
hpcIndexVE_GM = new TH2F("hpcIndexVE_GM", "PC index vs Energy; PC index ; Energy", 2 * 24, 0, 2 * 24, 400, 0, 16000);
hpcIndexVE_GM->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);
hAVCcoin = new TH2F("hAVCcoin", "Anode vs Cathode Coincident", 24, 0, 24, 24, 0, 24);
hqqqPolar = new TH2F("hqqqPolar", "QQQ Polar ID", 16 * 4, -TMath::Pi(), TMath::Pi(), 16, 10, 50);
@ -100,93 +70,11 @@ void Analyzer::Begin(TTree * /*tree*/)
hsx3VpcE->SetNdivisions(-612, "x");
hsx3VpcE->SetNdivisions(-12, "y");
hZProj = new TH1F("hZProj", "Z Projection", 1200, -600, 600);
hPCZProj = new TH1F("hPCZProj", "PC Z Projection", 600, -300, 300);
hZProj = new TH1F("hZProj", "Z Projection", 200, -600, 600);
hanVScatsum = new TH2F("hanVScatsum", "Anode vs Cathode Sum; Anode E; Cathode E", 400, 0, 16000, 400, 0, 20000);
hCat4An = new TH1F("hCat4An", "Number of Cathodes/Anode", 24, 0, 24);
hCat0An = new TH1F("hCat0An", "Number of Cathodes without Anode", 24, 0, 24);
hAnodehits = new TH1F("hAnodehits", "Number of Anode hits", 24, 0, 24);
hNosvAe = new TH2F("hnosvAe", "Number of Cathodes/Anode vs Anode Energy", 20, 0, 20, 400, 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, 16000, 400, 0, 20000);
// }
// for (int i = 0; i < 48; i++)
// {
// TString histName = Form("hCathode_%d", i);
// TString histTitle = Form("Cathode_E_%d;", i);
// hPC_E[i] = new TH1F(histName, histTitle, 3200, 0, 32000);
// }
hanVScatsum = new TH2F("hanVScatsum", "Anode vs Cathode Sum; Anode E; Cathode E", 400, 0, 10000, 400, 0, 16000);
sx3_contr.ConstructGeo();
pw_contr.ConstructGeo();
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;
// wires 37, 39, 44 have fit data that is incorrect or not present, they have thus been set to 1,0 (slope, intercept) for convenience
// wire 19 the 4th point was genereated using the slope of the line produced uising the other 3 points from the wire 1 vs wire 19 plot
if (index >= 0 && index <= 47)
{
slopeInterceptMap[index] = std::make_pair(slope, intercept);
}
}
inputFile.close();
}
else
{
std::cerr << "Error opening slope_intercept.txt" << std::endl;
}
std::string filename = "sx3_GainMatchback.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;
}
infile.close();
std::cout << "Loaded back gains from " << filename << std::endl;
std::string filename1 = "sx3_GainMatchfront.txt";
std::ifstream infile1(filename1);
if (!infile1.is_open())
{
std::cerr << "Error opening " << filename1 << "!" << std::endl;
return;
}
int idf, bkf, uf, df;
double fgain;
while (infile1 >> idf >> bkf >> uf >> df >> fgain)
{
frontGain[idf][bkf][uf][df] = fgain;
frontGainValid[idf][bkf][uf][df] = true;
}
}
Bool_t Analyzer::Process(Long64_t entry)
@ -224,17 +112,13 @@ Bool_t Analyzer::Process(Long64_t entry)
// ########################################################### Raw data
// //======================= SX3
sx3ecut = false;
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]);
if (sx3.e[i] > 100)
{
sx3ecut = true;
}
hsx3IndexVE->Fill(sx3.index[i], sx3.e[i]);
for (int j = i + 1; j < sx3.multi; j++)
{
@ -243,13 +127,10 @@ Bool_t Analyzer::Process(Long64_t entry)
for (int j = 0; j < pc.multi; j++)
{
if (pc.index[j] < 24 && pc.e[j] > 100)
{
hsx3VpcIndex->Fill(sx3.index[i], pc.index[j]);
// if( sx3.ch[index] > 8 ){
// hsx3VpcE->Fill( sx3.e[i], pc.e[j] );
// }
}
hsx3VpcIndex->Fill(sx3.index[i], pc.index[j]);
// if( sx3.ch[index] > 8 ){
// hsx3VpcE->Fill( sx3.e[i], pc.e[j] );
// }
}
}
@ -331,19 +212,12 @@ Bool_t Analyzer::Process(Long64_t entry)
}
// //======================= QQQ
qqqEcut = false;
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]);
// }
// printf("QQQ ID : %d, ch : %d, e : %d \n", qqq.id[i], qqq.ch[i], qqq.e[i]);
if (qqq.e[i] > 100)
{
qqqEcut = true;
}
// }
for (int j = 0; j < qqq.multi; j++)
{
@ -352,20 +226,18 @@ Bool_t Analyzer::Process(Long64_t entry)
hqqqCoin->Fill(qqq.index[i], qqq.index[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[k]);
}
}
// }
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
@ -384,10 +256,11 @@ Bool_t Analyzer::Process(Long64_t entry)
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 = 50. + 40. / 16. * (chRing + 0.5);
double rho = 10. + 40. / 16. * (chRing + 0.5);
// if(qqq.e[i]>50){
hqqqPolar->Fill(theta, rho);
// }
@ -406,292 +279,129 @@ Bool_t Analyzer::Process(Long64_t entry)
}
// //======================= PC
// Calculate the crossover points and put them into an array
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 );
pwinstance.ConstructGeo();
Coord Crossover[24][24][2];
Coord Crossover[24][24];
TVector3 a, c, diff;
double a2, ac, c2, adiff, cdiff, denom, alpha, beta;
int index = 0;
for (int i = 0; i < pwinstance.An.size(); i++)
{
a = pwinstance.An[i].first - pwinstance.An[i].second;
for (int j = 0; j < pwinstance.Ca.size(); j++)
{
// Ok so this method uses what is essentially the solution of 2 equations to find the point of intersection between the anode and cathode wires
// here a and c are the vectors of the anode and cathode wires respectively
// diff is the perpendicular vector between the anode and cathode wires
// The idea behind this is to then find the scalars alpha and beta that give a ratio between 0 and -1,
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);
c2 = c.Dot(c);
adiff = a.Dot(diff);
cdiff = c.Dot(diff);
denom = a2 * c2 - ac * ac;
alpha = (ac * cdiff - c2 * adiff) / denom;
beta = (a2 * cdiff - ac * 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)
Crossover[i][j].x = pwinstance.An[i].first.X() + alpha * a.X();
Crossover[i][j].y = pwinstance.An[i].first.Y() + alpha * a.Y();
Crossover[i][j].z = pwinstance.An[i].first.Z() + alpha * a.Z();
if (i == 23)
{
Crossover[i][j][0].z = 9999999;
}
// placeholder variable Crossover[i][j][1].x has nothing to do with the geometry of the crossover and is being used to store the alpha value-
//-so that it can be used to sort "good" hits later
Crossover[i][j][1].x = alpha;
Crossover[i][j][1].y = 0;
// if(i==0){
// printf("CID, Crossover z and alpha are : %d %f %f \n", j, Crossover[i][j][0].z, Crossover[i][j][1].x /*this is alpha*/);
// }
// }
// }
}
}
// printf("Anode and cathode indices, alpha, denom, andiff, cndiff : %d %d %f %f %f %f\n", i, j, alpha, denom, adiff, cdiff);
// anodeIntersection.Clear();
for (int i = 0; i < pc.multi; i++)
{
if (pc.e[i] > 100)
{
hpcIndexVE->Fill(pc.index[i], pc.e[i]); // non gain matched energy
}
// Gain Matching of PC wires
if (pc.index[i] >= 0 && pc.index[i] < 48)
{
// printf("index: %d, Old cathode energy: %d \n", pc.index[i],pc.e[i]);
auto it = slopeInterceptMap.find(pc.index[i]);
if (it != slopeInterceptMap.end())
{
double slope = it->second.first;
double intercept = it->second.second;
// printf("slope: %f, intercept:%f\n" ,slope, intercept);
pc.e[i] = slope * pc.e[i] + intercept;
// printf("index: %d, New cathode energy: %d \n",pc.index[i], pc.e[i]);
}
hpcIndexVE_GM->Fill(pc.index[i], pc.e[i]);
// hPC_E[pc.index[i]]->Fill(pc.e[i]); // gain matched energy per channel
}
}
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>> corrcatnextMax = {};
std::vector<std::pair<int, double>> commcat = {};
int aID = 0;
int cID = 0;
float aE = 0;
float cE = 0;
float aESum = 0;
float cESum = 0;
float aEMax = 0;
float cEMax = 0;
float aEnextMax = 0;
float cEnextMax = 0;
int aIDMax = 0;
int cIDMax = 0;
int aIDnextMax = 0;
int cIDnextMax = 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] > 100 /*&& pc.multi < 7*/)
{
// creating a vector of pairs of anode and cathode hits
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]));
}
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]);
}
}
}
// sorting the anode and cathode hits in descending order of energy
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; });
bool SiPCflag;
corrcatMax.clear();
if (anodeHits.size() >= 1 && cathodeHits.size() > 1)
{
if (((TMath::TanH(hitPos.Y() / hitPos.X())) > (TMath::TanH(a.Y() / a.X()) - TMath::PiOver4())) || ((TMath::TanH(hitPos.Y() / hitPos.X())) < (TMath::TanH(a.Y() / a.X()) + TMath::PiOver4())))
{
for (const auto &anode : anodeHits)
{
aID = anode.first;
aE = anode.second;
aESum += aE;
if (aE > aEMax)
if (abs(i - j) < 7 || abs(i - j) > 17)
{
aEMax = aE;
aIDMax = aID;
}
if (aE > aEnextMax && aE < aEMax)
{
aEnextMax = aE;
aIDnextMax = aID;
}
// for(const auto &cat : cathodeHits){
// hAVCcoin->Fill(aID, cat.first);
// }
}
// std::cout << " Anode iD : " << aIDMax << " Energy : " << aEMax << std::endl;
// printf("aID : %d, aE : %f, cE : %f\n", aID, aE, cE);
for (const auto &cathode : cathodeHits)
{
cID = cathode.first;
cE = cathode.second;
// std::cout << "Cathode ID : " << cID << " Energy : " << cE << std::endl;
hAVCcoin->Fill(aIDMax, cID);
// This section of code is used to find the cathodes are correlated with the max and next max anodes, as well as to figure out if there are any common cathodes
// the anodes are correlated with the cathodes +/-3 from the anode number in the reverse order
for (int j = -4; j < 3; j++)
{
if ((aIDMax + 24 + j) % 24 == 23 - cID)
/* the 23-cID is used to accomodate for the fact that the order of the cathodes was reversed relative top the physical geometry */
// if (Crossover[aIDMax][cID][0].z != 9999999)
if (alpha < 0 && alpha > -1)
{
corrcatMax.push_back(std::pair<int, double>(cID, cE));
cESum += cE;
// printf("Max Anode : %d Correlated Cathode : %d Anode Energy : %f z value : %f \n", aIDMax, cID, cESum, Crossover[aIDMax][cID][1].z /*prints alpha*/);
// std::cout << " Cathode iD : " << cID << " Energy : " << cE << std::endl;
printf("Anode and cathode indices and coord : %d %d %f %f %f %f\n", i, j, pwinstance.Ca[j].first.X(), pwinstance.Ca[j].first.Y(), pwinstance.Ca[j].first.Z(), alpha);
printf("Crossover wires, points and alpha are : %f %f %f %f \n", Crossover[i][j].x, Crossover[i][j].y, Crossover[i][j].z, alpha);
}
}
}
}
}
TVector3 anodeIntersection;
anodeIntersection.Clear();
// Implementing a method for PC reconstruction using a single Anode event
// if (anodeHits.size() == 1)
if (E.size() >= 3)
{
float x, y, z = 0;
for (const auto &corr : corrcatMax)
int aID = 0;
int cID = 0;
float aE = 0;
float cE = 0;
// 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 (cESum > 0)
if (qqq.index[k] == 75 && pc.index[k] == 2 && pc.e[k] > 100)
{
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;
// printf("Max Anode : %d Correlated Cathode : %d cathode Energy : %f cESum Energy : %f z value : %f \n", aIDMax, corr.first, corr.second, cESum, Crossover[aIDMax][corr.first][1].z /*prints alpha*/);
}
else
{
printf("Warning: No valid cathode hits to correlate with anode %d! \n", aIDMax);
}
// printf("EventID : %llu, Max Anode : %d Cathode: %d PC X and Y : (%f, %f) \n", entry, aIDMax, cID, Crossover[aIDMax][cID][0].x, Crossover[aIDMax][cID][0].y);
// for (int i = 0; i < sx3.multi; i++)
// {
// printf("EventID : %llu, HitPos X, Y, Z: %f %f %f SX3ID : %d %d \n", entry, hitPos.X(), hitPos.Y(), hitPos.Z(), sx3.id[i], sx3.ch[i]);
// }
// for (int i = 0; i < qqq.multi; i++)
// {
// printf("Max Anode : %d Cathode: %d PC X and Y : %f %f \n", aIDMax, cID, Crossover[aIDMax][cID][0].x, Crossover[aIDMax][cID][0].y);
// printf("HitPos X, Y, Z, QQQID : %f %f %f %d \n", hitPos.X(), hitPos.Y(), hitPos.Z(), qqq.id[i]);
// }
int multi_an = 0;
for (int l = 0; l < E.size(); l++)
{
if (E[l].first < 24)
{
multi_an++;
}
}
if (multi_an >= 1)
{
for (int l = 0; l < E.size(); l++)
{
if (E[l].first < 24 && E[l].first != 19 && E[l].first != 12)
{
aE = E[l].second;
}
else if (E[l].first > 24)
{
cE = E[l].second;
}
}
}
}
}
anodeIntersection = TVector3(x, y, z);
// std::cout << "Anode Intersection " << anodeIntersection.Z() << " " << x << " " << y << " " << z << std::endl;
}
hanVScatsum->Fill(aE, cE);
if (anodeIntersection.Z() != 0)
{
hPCZProj->Fill(anodeIntersection.Z());
}
// Filling the PC Z projection histogram
// std::cout << anodeIntersection.Z() << std::endl;
// hPCZProj->Fill(anodeIntersection.Z());
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];
}
// }
// 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(aEMax, cESum);
// }
// if (sx3ecut)
// {
hCat4An->Fill(corrcatMax.size());
hNosvAe->Fill(corrcatMax.size(), aEMax);
hAnodehits->Fill(anodeHits.size());
// }
// }
if (anodeHits.size() < 1)
{
hCat0An->Fill(cathodeHits.size());
}
if (HitNonZero && anodeIntersection.Z() != 0)
{
pw_contr.CalTrack2(hitPos, anodeIntersection);
hZProj->Fill(pw_contr.GetZ0());
if (HitNonZero)
{
pw_contr.CalTrack(hitPos, aID, cID);
hZProj->Fill(pw_contr.GetZ0());
}
}
// ########################################################### Track constrcution
@ -704,99 +414,80 @@ Bool_t Analyzer::Process(Long64_t entry)
void Analyzer::Terminate()
{
// gStyle->SetOptStat("neiou");
// TCanvas *canvas = new TCanvas("cANASEN", "ANASEN", 2000, 2000);
// canvas->Divide(3, 3);
gStyle->SetOptStat("neiou");
TCanvas *canvas = new TCanvas("cANASEN", "ANASEN", 2000, 2000);
canvas->Divide(3, 3);
// // hsx3VpcIndex->Draw("colz");
// hsx3VpcIndex->Draw("colz");
// //=============================================== pad-1
// padID++;
// canvas->cd(padID);
// canvas->cd(padID)->SetGrid(1);
//=============================================== pad-1
padID++;
canvas->cd(padID);
canvas->cd(padID)->SetGrid(1);
// hsx3IndexVE->Draw("colz");
hsx3IndexVE->Draw("colz");
// //=============================================== pad-2
// padID++;
// canvas->cd(padID);
// canvas->cd(padID)->SetGrid(1);
//=============================================== pad-2
padID++;
canvas->cd(padID);
canvas->cd(padID)->SetGrid(1);
// hqqqIndexVE->Draw("colz");
hqqqIndexVE->Draw("colz");
// //=============================================== pad-3
// padID++;
// canvas->cd(padID);
// canvas->cd(padID)->SetGrid(1);
//=============================================== pad-3
padID++;
canvas->cd(padID);
canvas->cd(padID)->SetGrid(1);
// hpcIndexVE->Draw("colz");
hpcIndexVE->Draw("colz");
// //=============================================== pad-4
// padID++;
// canvas->cd(padID);
// canvas->cd(padID)->SetGrid(1);
//=============================================== pad-4
padID++;
canvas->cd(padID);
canvas->cd(padID)->SetGrid(1);
// hsx3Coin->Draw("colz");
hsx3Coin->Draw("colz");
// //=============================================== pad-5
// padID++;
// canvas->cd(padID);
// canvas->cd(padID)->SetGrid(1);
//=============================================== pad-5
padID++;
canvas->cd(padID);
canvas->cd(padID)->SetGrid(1);
// canvas->cd(padID)->SetLogz(true);
canvas->cd(padID)->SetLogz(true);
// hqqqCoin->Draw("colz");
hqqqCoin->Draw("colz");
// //=============================================== pad-6
// padID++;
// canvas->cd(padID);
// canvas->cd(padID)->SetGrid(1);
//=============================================== pad-6
padID++;
canvas->cd(padID);
canvas->cd(padID)->SetGrid(1);
// hpcCoin->Draw("colz");
hpcCoin->Draw("colz");
// //=============================================== pad-7
// padID++;
// canvas->cd(padID);
// canvas->cd(padID)->SetGrid(1);
//=============================================== pad-7
padID++;
canvas->cd(padID);
canvas->cd(padID)->SetGrid(1);
// // hsx3VpcIndex ->Draw("colz");
// hsx3VpcE->Draw("colz");
// hsx3VpcIndex ->Draw("colz");
hsx3VpcE->Draw("colz");
// //=============================================== pad-8
// padID++;
// canvas->cd(padID);
// canvas->cd(padID)->SetGrid(1);
//=============================================== pad-8
padID++;
canvas->cd(padID);
canvas->cd(padID)->SetGrid(1);
// // hqqqVpcIndex ->Draw("colz");
// hqqqVpcIndex ->Draw("colz");
// hqqqVpcE->Draw("colz");
// //=============================================== pad-9
// padID++;
hqqqVpcE->Draw("colz");
//=============================================== pad-9
padID++;
// // canvas->cd(padID)->DrawFrame(-50, -50, 50, 50);
// // hqqqPolar->Draw("same colz pol");
// 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");
// // TFile *outRoot = new TFile("Histograms.root", "RECREATE");
// // if (!outRoot->IsOpen())
// // {
// // std::cerr << "Error opening file for writing!" << std::endl;
// // return;
// // }
// // // Loop through histograms and write them to the ROOT file
// // for (int i = 0; i < 48; i++)
// // {
// // if (hPC_E[i] != nullptr)
// // {
// // hPC_E[i]->Write(); // Write histogram to file
// // }
// // }
// // outRoot->Close();
canvas->cd(padID);
canvas->cd(padID)->SetGrid(1);
// hZProj->Draw();
hanVScatsum->Draw("colz");
}

View File

@ -18,7 +18,6 @@ public :
Det sx3;
Det qqq;
Det pc ;
Det misc;
ULong64_t evID;
UInt_t run;
@ -41,13 +40,6 @@ public :
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; //!
Analyzer(TTree * /*tree*/ =0) : fChain(0) { }
virtual ~Analyzer() { }
@ -100,13 +92,6 @@ void Analyzer::Init(TTree *tree){
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);
// fChain->SetBranchAddress("miscF", &misc.tf, &b_miscTf);
}

View File

@ -1,402 +0,0 @@
#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");
}

283
Armory/#ClassPW.h# Normal file
View File

@ -0,0 +1,283 @@
#ifndef ClassPW_h
#define ClassPW_h
#include <cstdio>
#include <TMath.h>
#include <TVector3.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;
}
};
//!########################################################
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;}
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, PWHitInfo 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 | 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
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 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 sx3Pos, PWHitInfo hitInfo, double sigmaA, double sigmaC, bool verbose){
trackPos = sx3Pos;
double p1 = TMath::Abs(hitInfo.nearestDist.first + gRandom->Gaus(0, sigmaA));
double p2 = TMath::Abs(hitInfo.nextNearestDist.first + gRandom->Gaus(0, sigmaA));
double fracA = p1 / (p1 + p2);
short anodeID1 = hitInfo.nearestWire.first;
short anodeID2 = hitInfo.nextNearestWire.first;
TVector3 shiftA1 = (An[anodeID2].first - An[anodeID1].first) * fracA;
TVector3 shiftA2 = (An[anodeID2].second - An[anodeID1].second) * fracA;
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());
}
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 trackPos.Z() - rho / TMath::Tan(theta);
}
#endif

View File

@ -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.)));
}
const int qqqR1 = 50;
const int qqqR2 = 100;
const int qqqR1 = 10;
const int qqqR2 = 50;
TGeoVolume *qqq = geom->MakeTubs("qqq", Al, qqqR1, qqqR2, 0.5, 5, 85);
qqq->SetLineColor(7);
for( int i = 0; i < 4; i++){

View File

@ -82,7 +82,7 @@ public:
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 CalTrack2(TVector3 sx3Pos, PWHitInfo hitInfo, double sigmaA = 0, double sigmaC = 0, bool verbose = false);
void Print()
{
@ -154,20 +154,15 @@ inline void PW::ConstructGeo()
-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()),
// 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 + 1) + TMath::PiOver2()),
radiusC * TMath::Sin(TMath::TwoPi() / nWire * (i + 1) + TMath::PiOver2()),
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);
}
// 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));
@ -283,22 +278,41 @@ inline void PW::CalTrack(TVector3 sx3Pos, int anodeID, int cathodeID, bool verbo
printf("Theta, Phi = %f, %f \n", trackVec.Theta() * TMath::RadToDeg(), trackVec.Phi() * TMath::RadToDeg());
}
inline void PW::CalTrack2(TVector3 siPos, TVector3 anodeInt, bool verbose)
inline void PW::CalTrack2(TVector3 sx3Pos, PWHitInfo hitInfo, double sigmaA, double sigmaC, bool verbose)
{
float 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);
}
trackPos = sx3Pos;
double p1 = TMath::Abs(hitInfo.nearestDist.first + gRandom->Gaus(0, sigmaA));
double p2 = TMath::Abs(hitInfo.nextNearestDist.first + gRandom->Gaus(0, sigmaA));
double fracA = p1 / (p1 + p2);
short anodeID1 = hitInfo.nearestWire.first;
short anodeID2 = hitInfo.nextNearestWire.first;
TVector3 shiftA1 = (An[anodeID2].first - An[anodeID1].first) * fracA;
TVector3 shiftA2 = (An[anodeID2].second - An[anodeID1].second) * fracA;
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("X slope = %f and Y slope = %f \n", mx, my);
printf("Theta, Phi = %f, %f \n", trackVec.Theta() * TMath::RadToDeg(), trackVec.Phi() * TMath::RadToDeg());
}
inline double PW::GetZ0()
@ -309,7 +323,7 @@ inline double PW::GetZ0()
double rho = TMath::Sqrt(x * x + y * y);
double theta = trackVec.Theta();
return trackVec.Z();
return trackPos.Z() - rho / TMath::Tan(theta);
}
#endif

View File

@ -1,463 +0,0 @@
#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 <TProfile.h>
#include <TVector3.h>
#include "Armory/ClassSX3.h"
#include "Armory/ClassPW.h"
#include "TGraphErrors.h"
#include "Calibration.h"
int padID = 0;
SX3 sx3_contr;
PW pw_contr;
PW pwinstance;
TVector3 hitPos;
// TVector3 anodeIntersection;
std::map<int, std::pair<double, double>> slopeInterceptMap;
bool HitNonZero;
bool sx3ecut;
bool qqqEcut;
TH2F *hSX3FvsB;
TH2F *hSX3FvsB_g;
TH2F *hSX3;
TH1F *hZProj;
TH2F *hsx3IndexVE;
TH2F *hsx3IndexVE_gm;
TH2F *hqqqIndexVE;
TH2F *hqqqIndexVE_gm;
TH2F *hsx3Coin;
TH2F *hqqqCoin;
TH2F *hqqqPolar;
TH1F *hsx3E_raw;
TH1F *hsx3E_calib;
TCutG *cut;
TCutG *cut1;
// Gain arrays
const int MAX_SX3 = 24;
const int MAX_UP = 4;
const int MAX_DOWN = 4;
const int MAX_BK = 4;
const int MAX_QQQ = 4;
const int MAX_RING = 16;
const int MAX_WEDGE = 16;
double backGain[MAX_SX3][MAX_BK] = {{0}};
bool backGainValid[MAX_SX3][MAX_BK] = {{false}};
double frontGain[MAX_SX3][MAX_BK][MAX_UP][MAX_DOWN] = {{{{0}}}};
bool frontGainValid[MAX_SX3][MAX_BK][MAX_UP][MAX_DOWN] = {{{{false}}}};
double uvdslope[MAX_SX3][MAX_BK][MAX_UP][MAX_DOWN] = {{{{0}}}};
double qqqGain[MAX_QQQ][MAX_BK][MAX_UP] = {{{0}}};
bool qqqGainValid[MAX_QQQ][MAX_BK][MAX_UP] = {{{false}}};
TH1F *hSX3Spectra[MAX_SX3][MAX_BK][MAX_UP][MAX_DOWN];
TH1F *hQQQSpectra[MAX_QQQ][MAX_RING][MAX_WEDGE];
void Calibration::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);
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);
hsx3IndexVE = new TH2F("hsx3IndexVE", "SX3 index vs Energy; sx3 index ; Energy", 24 * 12, 0, 24 * 12, 400, 0, 5000);
hsx3IndexVE_gm = new TH2F("hsx3IndexVE_cal", "SX3 index vs Energy (calibrated); SX3 index ; Energy", 24 * 12, 0, 24 * 12, 400, 0, 5000);
hsx3E_raw = new TH1F("hsx3E_raw", "SX3 Back Energy (raw); Energy (arb); Counts", 4000, 0, 16000);
hsx3E_calib = new TH1F("hsx3E_calib", "SX3 Back Energy (gm); Energy (kev); Counts", 4000, 0, 16000);
hqqqIndexVE = new TH2F("hqqqIndexVE", "QQQ index vs Energy; QQQ index ; Energy", 4 * 2 * 16, 0, 4 * 2 * 16, 400, 0, 5000);
hqqqIndexVE_gm = new TH2F("hqqqIndexVE_cal", "QQQ index vs Energy (calibrated); QQQ index ; Energy", 4 * 2 * 16, 0, 4 * 2 * 16, 400, 0, 5000);
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);
hqqqPolar = new TH2F("hqqqPolar", "QQQ Polar ID", 16 * 4, -TMath::Pi(), TMath::Pi(), 16, 10, 50);
sx3_contr.ConstructGeo();
pw_contr.ConstructGeo();
// ----------------------- Load Back Gains
{
std::string filename = "sx3_GainMatchback.txt";
std::ifstream infile(filename);
if (!infile.is_open())
{
std::cerr << "Error opening " << filename << "!" << std::endl;
}
else
{
int id, bk;
double gain;
while (infile >> id >> bk >> gain)
{
backGain[id][bk] = gain;
backGainValid[id][bk] = (gain > 0);
}
infile.close();
std::cout << "Loaded back gains from " << filename << std::endl;
}
}
// ----------------------- Load Front Gains
{
std::string filename = "sx3_GainMatchfront.txt";
std::ifstream infile(filename);
if (!infile.is_open())
{
std::cerr << "Error opening " << filename << "!" << std::endl;
}
else
{
int id, bk, u, d;
double gain;
while (infile >> id >> bk >> u >> d >> gain)
{
frontGain[id][bk][u][d] = gain;
frontGainValid[id][bk][u][d] = (gain > 0);
}
infile.close();
std::cout << "Loaded front gains from " << filename << std::endl;
}
}
// ----------------------- 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 gain;
while (infile >> det >> ring >> wedge >> gain)
{
qqqGain[det][ring][wedge] = gain;
qqqGainValid[det][ring][wedge] = (gain > 0);
}
infile.close();
std::cout << "Loaded QQQ gains from " << filename << std::endl;
}
}
for (int id = 0; id < MAX_SX3; id++)
{
for (int bk = 0; bk < MAX_BK; bk++)
{
for (int up = 0; up < MAX_UP; up++)
{
for (int dn = 0; dn < MAX_DOWN; dn++)
{
TString hname = Form("hCal_id%d_bk%d_up%d_dn%d", id, bk, up, dn);
TString htitle = Form("SX3 id%d bk%d up%d dn%d; Energy (arb); Counts", id, bk, up, dn);
hSX3Spectra[id][bk][up][dn] = new TH1F(hname, htitle, 4000, 0, 16000);
}
}
}
}
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);
}
}
}
SX3 sx3_contr;
}
Bool_t Calibration::Process(Long64_t entry)
{
hitPos.Clear();
HitNonZero = false;
// Load branches
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);
sx3.CalIndex();
qqq.CalIndex();
pc.CalIndex();
// ########################################################### Raw data
sx3ecut = false;
std::vector<std::pair<int, int>> ID; // first = id, 2nd = index
for (int i = 0; i < sx3.multi; i++)
{
ID.emplace_back(sx3.id[i], i);
hsx3IndexVE->Fill(sx3.index[i], sx3.e[i]);
if (sx3.e[i] > 100)
sx3ecut = true;
for (int j = i + 1; j < sx3.multi; j++)
hsx3Coin->Fill(sx3.index[i], sx3.index[j]);
}
// --- SX3 safe handling ---
if (!ID.empty())
{
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)
{
int sx3ChUp = -1, sx3ChDn = -1, sx3ChBk = -1;
float sx3EUp = 0.0f, sx3EDn = 0.0f, sx3EBk = 0.0f;
for (size_t i = 0; i < sx3ID.size(); i++)
{
int index = sx3ID[i].second;
if (sx3.ch[index] < 8)
{
if ((sx3.ch[index] % 2) == 0) // even -> down
{
sx3ChDn = sx3.ch[index];
sx3EDn = sx3.e[index];
}
else // odd -> up
{
sx3ChUp = sx3.ch[index];
sx3EUp = sx3.e[index];
}
}
else
{
sx3ChBk = sx3.ch[index];
sx3EBk = sx3.e[index];
}
bool haveFrontPair = (sx3ChUp >= 0 || sx3ChDn >= 0);
bool haveBack = (sx3ChBk >= 0);
double GM_EUp = 0.0, GM_EDn = 0.0, calibEBack = 0.0;
if (haveBack)
{
// --- ALWAYS fill raw ADC for diagnostics
// (temporarily use the existing spectrum to confirm fills)
// If you don't want raw values mixed with calibrated later, create a separate _raw array.
hSX3Spectra[sx3ID[i].first][sx3ChBk][sx3ChUp][sx3ChDn]->Fill(sx3EUp);
// --- If gain is available, also fill calibrated energy
if (frontGainValid[sx3ID[i].first][sx3ChBk][sx3ChUp][sx3ChDn])
{
GM_EUp = frontGain[sx3ID[i].first][sx3ChBk][sx3ChUp][sx3ChDn] * sx3EUp;
if (GM_EUp > 50.0)
hSX3Spectra[sx3ID[i].first][sx3ChBk][sx3ChUp][sx3ChDn]->Fill(GM_EUp); // optional: mixes raw+calib
}
// --- If back gain is available, also fill calibrated energy
hsx3E_raw->Fill(sx3EBk);
if (backGainValid[sx3ID[i].first][sx3ChBk])
{
calibEBack = backGain[sx3ID[i].first][sx3ChBk] * sx3EBk;
if (calibEBack > 50.0)
hsx3E_calib->Fill(calibEBack); // optional: mixes raw+calib
}
// Keep the other diagnostic plots
hsx3IndexVE_gm->Fill(sx3.index[sx3ID[i].second], GM_EUp);
hSX3->Fill(sx3ChDn + 4, sx3ChBk);
hSX3->Fill(sx3ChUp, sx3ChBk);
hSX3FvsB->Fill(sx3EUp + sx3EDn, sx3EBk);
if (GM_EUp > 50.0 && sx3EBk > 50.0)
{
sx3_contr.CalSX3Pos(sx3ID[i].first, sx3ChUp, sx3ChDn, sx3ChBk, GM_EUp, sx3EDn);
hitPos = sx3_contr.GetHitPos();
HitNonZero = true;
}
}
}
}
}
// ======================= QQQ =======================
for (int i = 0; i < qqq.multi; i++)
{
int det = qqq.id[i];
if (qqq.e[i] > 100)
qqqEcut = true;
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++)
{
if (qqq.id[i] == qqq.id[j])
{
int chWedge = -1, 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;
}
double Ecal = qqq.e[i];
if (det >= 0 && det < MAX_QQQ &&
chRing >= 0 && chRing < MAX_RING &&
chWedge >= 0 && chWedge < MAX_WEDGE)
{
// ALWAYS fill raw energy for diagnostics
hQQQSpectra[det][chRing][chWedge]->Fill(qqq.e[i]);
// If calibrated gain is present, also fill calibrated energy
if (qqqGainValid[det][chRing][chWedge])
{
double Ecal = qqq.e[i] * qqqGain[det][chRing][chWedge];
hQQQSpectra[det][chRing][chWedge]->Fill(Ecal); // optional: mixes raw+calib
}
}
hqqqIndexVE_gm->Fill(qqq.index[i], Ecal);
hqqqIndexVE->Fill(qqq.index[i], qqq.e[i]);
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);
hqqqPolar->Fill(theta, rho);
if (!HitNonZero)
{
double x = rho * TMath::Cos(theta);
double y = rho * TMath::Sin(theta);
hitPos.SetXYZ(x, y, 23 + 75 + 30);
HitNonZero = true;
}
}
}
}
return kTRUE;
}
void Calibration::Terminate()
{
const double AM241_ALPHA = 5486.0; // keV
// ----------------------- Summary Plots
TH2F *hSX3Summary = new TH2F("hSX3Summary", "SX3 Channel Means;Channel Index;Mean (ADC)",
MAX_SX3 * MAX_BK * MAX_UP * MAX_DOWN, 0, MAX_SX3 * MAX_BK * MAX_UP * MAX_DOWN,
200, 0, 10000);
TH2F *hQQQSummary = new TH2F("hQQQSummary", "QQQ Channel Means;Channel Index;Mean (ADC)",
MAX_QQQ * MAX_RING * MAX_WEDGE, 0, MAX_QQQ * MAX_RING * MAX_WEDGE,
200, 0, 10000);
// ----------------------- SX3 Calibration (quick check with mean)
for (int id = 0; id < MAX_SX3; id++)
{
for (int bk = 0; bk < MAX_BK; bk++)
{
for (int up = 0; up < MAX_UP; up++)
{
for (int dn = 0; dn < MAX_DOWN; dn++)
{
TH1F *hSpec = hSX3Spectra[id][bk][up][dn];
if (!hSpec || hSpec->GetEntries() < 200)
continue;
double mean = hSpec->GetMean();
int sx3Index = (((id * MAX_BK + bk) * MAX_UP + up) * MAX_DOWN + dn);
hSX3Summary->Fill(sx3Index, mean);
std::cout << Form("SX3 id%d bk%d up%d dn%d → mean %.1f",
id, bk, up, dn, mean)
<< std::endl;
}
}
}
}
// ----------------------- QQQ Calibration (quick check with mean)
for (int det = 0; det < MAX_QQQ; det++)
{
for (int ring = 0; ring < MAX_RING; ring++)
{
for (int wedge = 0; wedge < MAX_WEDGE; wedge++)
{
TH1F *hSpec = hQQQSpectra[det][ring][wedge];
if (!hSpec || hSpec->GetEntries() < 200)
continue;
double mean = hSpec->GetMean();
int qqqIndex = ((det * MAX_RING + ring) * MAX_WEDGE + wedge);
hQQQSummary->Fill(qqqIndex, mean);
std::cout << Form("QQQ det%d ring%d wedge%d → mean %.1f",
det, ring, wedge, mean)
<< std::endl;
}
}
}
// ----------------------- Draw Summary
TCanvas *cSum = new TCanvas("cSum", "Calibration Summary (Means)", 1200, 600);
cSum->Divide(2, 1);
cSum->cd(1);
hSX3Summary->Draw("COLZ");
cSum->cd(2);
hQQQSummary->Draw("COLZ");
cSum->Update();
}

View File

@ -1,114 +0,0 @@
#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

View File

@ -1,124 +0,0 @@
#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;
}

View File

@ -1,180 +0,0 @@
#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 "TVector3.h"
TH2F *hQQQFVB;
int padID = 0;
TCutG *cut;
std::map<std::tuple<int, int, int>, std::vector<std::pair<double, double>>> dataPoints;
void GainMatchQQQ::Begin(TTree * /*tree*/)
{
TString option = GetOption();
hQQQFVB = new TH2F("hQQQFVB", "QQQ Front vs Back; Front E; Back E", 400, 0, 16000, 400, 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)
{
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;
hQQQFVB->Fill(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))
{
// Accumulate data for gain matching
dataPoints[{qqq.id[i], chRing, chWedge}].emplace_back(eWedge, eRing);
}
}
}
}
return kTRUE;
}
void GainMatchQQQ::Terminate()
{
const int MAX_DET = 4;
const int MAX_RING = 16;
const int MAX_WEDGE = 16;
double gainArray[MAX_DET][MAX_RING][MAX_WEDGE] = {{{0}}};
bool gainValid[MAX_DET][MAX_RING][MAX_WEDGE] = {{{false}}};
std::ofstream outFile("qqq_GainMatch.txt");
if (!outFile.is_open())
{
std::cerr << "Error opening output file!" << std::endl;
return;
}
for (const auto &kv : dataPoints)
{
auto [id, ring, wedge] = kv.first;
const auto &pts = kv.second;
if (pts.size() < 5)
continue;
std::vector<double> wE, rE;
for (const auto &pr : pts)
{
wE.push_back(pr.first);
rE.push_back(pr.second);
}
TGraph g(wE.size(), wE.data(), rE.data());
TF1 f("f", "[0]*x", 0, 16000);
g.Fit(&f, "QNR");
gainArray[id][ring][wedge] = f.GetParameter(0);
gainValid[id][ring][wedge] = true;
}
for (int id = 0; id < MAX_DET; ++id)
{
for (int ring = 0; ring < MAX_RING; ++ring)
{
for (int wedge = 0; wedge < MAX_WEDGE; ++wedge)
{
if (gainValid[id][ring][wedge])
{
outFile << id << " " << wedge << " " << ring << " " << gainArray[id][ring][wedge] << std::endl;
printf("Gain match Det%d Ring%d Wedge%d → %.4f \n", id, ring, wedge, gainArray[id][ring][wedge]);
}
}
}
}
outFile.close();
std::cout << "Gain matching complete." << std::endl;
// === Plot all gain-matched QQQ points together with a 2D histogram ===
TH2F *hAll = new TH2F("hAll", "All QQQ Gain-Matched;Corrected Wedge E;Ring E",
400, 0, 16000, 400, 0, 16000);
// Fill the combined TH2F with corrected data
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 * gainArray[id][ring][wedge];
double ringE = pr.second;
hAll->Fill(corrWedge, ringE);
}
}
}

View File

@ -1,114 +0,0 @@
#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

View File

@ -1,418 +0,0 @@
#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_GainMatchfront0.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;
}
}
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];
}
}
sx3EUp*=frontGainUp[sx3ID[i].first][sx3ChBk][sx3ChUp / 2][sx3ChDn / 2];
sx3EDn*=frontGainDown[sx3ID[i].first][sx3ChBk][sx3ChUp / 2][sx3ChDn / 2];
}
// 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);
// 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_BackGains1.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();
}

View File

@ -1,420 +0,0 @@
#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;
}

View File

@ -1,104 +0,0 @@
#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

View File

@ -1,245 +0,0 @@
#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;
}

View File

@ -1,414 +0,0 @@
#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

View File

@ -1,133 +0,0 @@
#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;
}

View File

@ -1,454 +0,0 @@
#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();
}

View File

@ -1,114 +0,0 @@
#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

View File

@ -1,8 +1,7 @@
#!/bin/bash
if [ "$#" -ne 3 ]; then
echo "Usage: $0 runID timeWindow_ns option"
echo "option: 0 - process raw data, 1 - process mapped data"
if [ "$#" -ne 2 ]; then
echo "Usage: $0 runID timeWindow_ns"
echo "Exiting..."
exit 1
fi
@ -10,9 +9,7 @@ fi
runID=$1
timeWindow=$2
option=$3
rawFolder=/home/tandem/data1/2024_09_17Fap/data
rawFolder=/home/tandem/Desktop/analysis/data
rootFolder=../root_data
if [ $option -eq 0 ]; then
@ -29,5 +26,4 @@ if [ $option -eq 0 ]; then
./Mapper ${rootFolder}/*${runID}*${timeWindow}.root
fi
root "processRun.C(\"${rootFolder}/ProtonRun_${runID}_mapped.root\")"
root "processRun.C(\"${rootFolder}/Run_${runID}_mapped.root\")"

View File

@ -1,6 +1,6 @@
#define Analyzer_cxx
#define TrackRecon_cxx
#include "Analyzer.h"
#include "TrackRecon.h"
#include <TH2.h>
#include <TStyle.h>
#include <TCanvas.h>
@ -14,20 +14,6 @@
#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;
@ -37,7 +23,7 @@ bool HitNonZero;
TH1F * hZProj;
void Analyzer::Begin(TTree * /*tree*/){
void TrackRecon::Begin(TTree * /*tree*/){
TString option = GetOption();
hZProj = new TH1F("hZProj", "Z Projection", 200, -600, 600);
@ -47,17 +33,14 @@ void Analyzer::Begin(TTree * /*tree*/){
}
Bool_t Analyzer::Process(Long64_t entry){
Bool_t TrackRecon::Process(Long64_t entry){
// if ( entry > 100 ) return kTRUE;
hitPos.Clear();
HitNonZero = false;
// if( entry > 1) return kTRUE;
if( entry > 1) return kTRUE;
// printf("################### ev : %llu \n", entry);
b_sx3Multi->GetEntry(entry);
@ -133,13 +116,6 @@ Bool_t Analyzer::Process(Long64_t entry){
}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);
@ -170,7 +146,7 @@ Bool_t Analyzer::Process(Long64_t entry){
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);
// hqqqPolar->Fill( theta, rho);
// }
// qqq.used[i] = true;
// qqq.used[j] = true;
@ -187,7 +163,6 @@ Bool_t Analyzer::Process(Long64_t entry){
}
// //======================= PC
PCHit_1An hitInfo;
ID.clear();
int counter=0;
@ -197,33 +172,51 @@ Bool_t Analyzer::Process(Long64_t entry){
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;
}
int multi_an =0;
for(int l=0;l<E.size();l++){
if(E[l].first<24 && E[l].first!=20 && E[l].first!=12){
multi_an++;
}
// 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(multi_an==1){
for(int l=0;l<E.size();l++){
if(E[l].first<24 && E[l].first!=20 && E[l].first!=12){
aE = E[l].second;
}else if(E[l].first>24){
cE = E[l].second;
}
}
}
//using CalTrack3 to get the track position and direction
// hanVScatsum->Fill(aE,cE);
if( HitNonZero){
pw_contr.CalTrack3( hitPos, hitinfo, cID);
hZProj->Fill(pw_contr.GetZ0());
if (ID.size() == 3) {
int aID = -1;
int cID1 = -1;
int cID2 = -1;
for (int i = 0; i < ID.size(); i++) {
if (pc.ch[ID[i].second] < 24 && pc.ch[ID[i].second] != 20 && pc.ch[ID[i].second] != 12) {
aID = pc.ch[ID[i].second];
} else if (pc.ch[ID[i].second] > 24) {
if (cID1 == -1) {
cID1 = pc.ch[ID[i].second];
} else {
cID2 = pc.ch[ID[i].second];
}
}
}
if (aID != -1 && cID1 != -1 && cID2 != -1) {
pw_contr.CalTrack3(hitPos, aID, cID1, cID2);
pw_contr.Print();
printf("###################\n");
hZProj->Fill(pw_contr.GetZ0());
}
}
}
// }
@ -240,64 +233,13 @@ Bool_t Analyzer::Process(Long64_t entry){
return kTRUE;
}
void Analyzer::Terminate(){
void TrackRecon::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);
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");
TCanvas * canvas = new TCanvas("cANASEN", "ANASEN", 200, 200);
padID=1;
canvas->cd(padID); canvas->cd(padID)->SetGrid(1);
hZProj->Draw();
// hanVScatsum->Draw("colz");
}

View File

@ -1,5 +1,5 @@
#ifndef Analyzer1_h
#define Analyzer1_h
#ifndef TrackRecon_h
#define TrackRecon_h
#include <TROOT.h>
#include <TChain.h>
@ -8,7 +8,7 @@
#include "Armory/ClassDet.h"
class Analyzer1 : public TSelector {
class TrackRecon : public TSelector {
public :
TTree *fChain; //!pointer to the analyzed TTree or TChain
@ -41,8 +41,8 @@ public :
TBranch *b_pcE; //!
TBranch *b_pcT; //!
Analyzer1(TTree * /*tree*/ =0) : fChain(0) { }
virtual ~Analyzer1() { }
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);
@ -57,13 +57,13 @@ public :
virtual void SlaveTerminate();
virtual void Terminate();
ClassDef(Analyzer1,0);
ClassDef(TrackRecon,0);
};
#endif
#ifdef Analyzer1_cxx
void Analyzer1::Init(TTree *tree){
#ifdef TrackRecon_cxx
void TrackRecon::Init(TTree *tree){
// Set branch addresses and branch pointers
if (!tree) return;
@ -95,20 +95,20 @@ void Analyzer1::Init(TTree *tree){
}
Bool_t Analyzer1::Notify(){
Bool_t TrackRecon::Notify(){
return kTRUE;
}
void Analyzer1::SlaveBegin(TTree * /*tree*/){
void TrackRecon::SlaveBegin(TTree * /*tree*/){
TString option = GetOption();
}
void Analyzer1::SlaveTerminate(){
void TrackRecon::SlaveTerminate(){
}
#endif // #ifdef Analyzer_cxx
#endif // #ifdef TrackRecon_cxx

View File

@ -1,97 +0,0 @@
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

View File

@ -1,89 +0,0 @@
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

541
gainmatch.C Normal file
View File

@ -0,0 +1,541 @@
#define gainmatch_cxx
#include "gainmatch.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 * hqqqIndexVE_cut;
TH2F * hpcIndexVE;
TH2F * hsx3Coin;
TH2F * hqqqCoin;
TH2F * hpcCoin;
TH2F * hpcCoin_cut;
TH2F * hGoodQQQ;
TH2F * hGoodQQQRingVWedge;
TH2F * hqqqPolar;
TH2F * hsx3VpcIndex;
TH2F * hqqqVpcIndex;
TH2F * hqqqVpcIndex_cut;
TH2F * hqqqVpcE;
TH2F * hqqqVpcE_cut;
TH2F * hqqqVpcE_cut1;
TH2F * hqqqVpcE_cut2;
TH2F * hqqqVpcE_cutCoinc;
TH2F * hsx3VpcE;
TH2F * hanVScatsum;
TH2F * hanVScatsum_cut;
TH2F * hanVScatsum_cut1;
TH2F * hanVScatsum_cut2;
TH2F * hsx3Vsx3;
TH2F * hsx3uVsx3d_01;
TH2F * hsx3uVsx3d_23;
TH2F * hsx3uVsx3d_45;
TH2F * hsx3uVsx3d_67;
TH2F * hVCID;
TH1F *hsx3bk_9_shifted ;
TH1F *hsx3bk_10_shifted ;
TH1F *hsx3bk_11_shifted ;
int padID = 0;
TCutG *Coinc_cut_set1;
//TCutG *crap_cut;
TCutG *AnCathCoinc_cut;
TCutG *AnCathCoinc_cut1;
TCutG *AnCathCoinc_cut2;
SX3 sx3_contr;
PW pw_contr;
TVector3 hitPos;
bool HitNonZero;
bool inCut;
bool inCut1;
bool inCut2;
bool inCutCoinc;
TH1F *hZd_01_1;
TH1F *hZd_01_2;
TH1F *hZd_01_3;
TH1F *hZd_01_4;
TH1F * hZProj;
TH1F * hsx3bk_11;
TH1F * hsx3bk_10;
TH1F * hsx3bk_9;
TH1F * hsx3bk_8;
void gainmatch::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");
hqqqIndexVE_cut = new TH2F("hqqqIndexVE_cut", "QQQ index vs Energy gated; 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");
hGoodQQQ = new TH2F("hGoodQQQ", "number of good QQQ vs QQQ id", 10, 0, 10, 4, 0, 4);
hGoodQQQRingVWedge = new TH2F("hGoodQQQRingVWedge", "Ring index, Wedge index", 16*4, 0, 16*4, 16*4, 0, 16*4);
hZd_01_1 =new TH1F("hZd_01_1", "Z position", 100, -1, 1);
hZd_01_2 =new TH1F("hZd_01_2", "Z position", 100, -1, 1);
hZd_01_3 =new TH1F("hZd_01_3", "Z position", 100, -1, 1);
hZd_01_4 =new TH1F("hZd_01_4", "Z position", 100, -1, 1);
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);
hpcCoin_cut = new TH2F("hpcCoin_cut", "PC Coincident gated", 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);
hsx3Vsx3 = new TH2F("hsx3Vsx3", "sx3 vs sx3; sx3 E; sx3 E", 8000, 0, 16000, 8000, 0, 16000);
hsx3uVsx3d_01 = new TH2F("hsx3uVsx3d_01", "sx3u vs sx3d; sx3u E; sx3d E", 100, 0, 1, 100, 0, 1);
hsx3uVsx3d_23 = new TH2F("hsx3uVsx3d_23", "sx3u vs sx3d; sx3u E; sx3d E", 100, 0, 1, 100, 0, 1);
hsx3uVsx3d_45 = new TH2F("hsx3uVsx3d_45", "sx3u vs sx3d; sx3u E; sx3d E", 1000, 0, 5000, 1000, 0, 5000);
hsx3uVsx3d_67 = new TH2F("hsx3uVsx3d_67", "sx3u vs sx3d; sx3u E; sx3d E", 1000, 0, 5000, 1000, 0, 5000);
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");
hqqqVpcIndex_cut = new TH2F("hqqqVpcindex_cut", "qqq vs pc gated; qqq index; pc index", 4*2*16, 0, 4*2*16, 48, 0, 48);
hqqqVpcIndex_cut->SetNdivisions( -612, "x");
hqqqVpcIndex_cut->SetNdivisions( -12, "y");
hqqqVpcE = new TH2F("hqqqVpcEnergy", "qqq vs pc; qqq energy; pc energy", 8000, 0, 16000, 8000, 0, 16000);
hqqqVpcE->SetNdivisions( -612, "x");
hqqqVpcE->SetNdivisions( -12, "y");
hqqqVpcE_cut = new TH2F("hqqqVpcEnergy_cut", "qqq vs pc gated; qqq energy; pc energy", 8000, 0, 16000, 8000, 0, 16000);
hqqqVpcE_cut->SetNdivisions( -612, "x");
hqqqVpcE_cut->SetNdivisions( -12, "y");
hqqqVpcE_cut1 = new TH2F("hqqqVpcEnergy_cut1", "qqq vs pc gated; qqq energy; pc energy", 8000, 0, 16000, 8000, 0, 16000);
hqqqVpcE_cut1->SetNdivisions( -612, "x");
hqqqVpcE_cut1->SetNdivisions( -12, "y");
hqqqVpcE_cut2 = new TH2F("hqqqVpcEnergy_cut2", "qqq vs pc gated; qqq energy; pc energy", 8000, 0, 16000, 8000, 0, 16000);
hqqqVpcE_cut2->SetNdivisions( -612, "x");
hqqqVpcE_cut2->SetNdivisions( -12, "y");
hqqqVpcE_cutCoinc = new TH2F("hqqqVpcEnergy_cutCoinc", "qqq vs pc gated; qqq energy; pc energy", 8000, 0, 16000, 8000, 0, 16000);
hqqqVpcE_cutCoinc->SetNdivisions( -612, "x");
hqqqVpcE_cutCoinc->SetNdivisions( -12, "y");
hsx3bk_8=new TH1F("hsx3bk_8", "hsx3bk_8",1000, 0,5000);
hsx3bk_9=new TH1F("hsx3bk_9", "hsx3bk_9",1000, 0,5000);
hsx3bk_10=new TH1F("hsx3bk_10", "hsx3bk_10",1000, 0,5000);
hsx3bk_11=new TH1F("hsx3bk_11", "hsx3bk_11",1000, 0,5000);
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");
hsx3bk_9_shifted = new TH1F("hsx3bk_9_shifted", "hsx3bk_9",1000, 0,5000);
hsx3bk_10_shifted = new TH1F("hsx3bk_10_shifted", "hsx3bk_9",1000, 0,5000);
hsx3bk_11_shifted = new TH1F("hsx3bk_11_shifted", "hsx3bk_9",1000, 0,5000);
hZProj = new TH1F("hZProj", "Z Projection", 200, -600, 600);
hanVScatsum = new TH2F("hanVScatsum", "Anode vs Cathode Sum; Anode E; Cathode E", 8000,0 , 16000, 8000, 0 , 16000);
hanVScatsum_cut = new TH2F("hanVScatsum_cut", "Anode vs Cathode Sum gated; Anode E; Cathode E", 1600,0 , 16000, 1600, 0 , 16000);
hanVScatsum_cut1 = new TH2F("hanVScatsum_cut1", "Anode vs Cathode Sum gated; Anode E; Cathode E", 1600,0 , 16000, 1600, 0 , 16000);
hanVScatsum_cut2 = new TH2F("hanVScatsum_cut2", "Anode vs Cathode Sum gated; Anode E; Cathode E", 1600,0 , 16000, 1600, 0 , 16000);
hVCID = new TH2F("hVCID", "Virtual Cathod ID vs total Cath. Energy", 200, 0, 24, 200, 0, 10000);
sx3_contr.ConstructGeo();
pw_contr.ConstructGeo();
TFile *f3 = new TFile("Coinc_cut_set1.root");
//TFile *f4 = new TFile("crap_cut.root");
TFile *f = new TFile("AnCathCoinc_cut.root");
TFile *f1 = new TFile("AnCathCoinc_cut1.root");
TFile *f2 = new TFile("AnCathCoinc_cut2.root");
Coinc_cut_set1 = (TCutG*)f3->Get("Coinc_cut_set1");
//crap_cut = (TCutG*)f4->Get("crap_cut");
AnCathCoinc_cut = (TCutG*)f->Get("AnCathCoinc_cut");
AnCathCoinc_cut1 = (TCutG*)f1->Get("AnCathCoinc_cut1");
AnCathCoinc_cut2 = (TCutG*)f2->Get("AnCathCoinc_cut2");
}
Bool_t gainmatch::Process(Long64_t entry){
// if ( entry > 100 ) return kTRUE;
hitPos.Clear();
HitNonZero = false;
inCut = 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 (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;
});
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) {
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;
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];
sx3EBk = sx3.e[index];
}
int ch = sx3.ch[index];
float energy = sx3.e[index];
if (sx3ID[0].first == 9) {
float peak8 = 0.0;
float peak9 = 0.0;
int peak10 = 0.0;
float peak11 = 0.0;
float shift9 =0.0;
float shift10 =0.0;
float shift11 =0.0;
int minBin_8 = hsx3bk_8->FindBin(1);
int maxBin_8 = hsx3bk_8->FindBin(5000);
int maxRangeBinContent_8 = -1;
double maxBinCenter_8 = 0.0;
int minBin_9 = hsx3bk_9->FindBin(1);
int maxBin_9 = hsx3bk_9->FindBin(5000);
int maxRangeBinContent_9 = -1;
double maxBinCenter_9 = 0.0;
int minBin_10 = hsx3bk_10->FindBin(1);
int maxBin_10 = hsx3bk_10->FindBin(5000);
int maxRangeBinContent_10 = -1;
double maxBinCenter_10 = 0.0;
int minBin_11 = hsx3bk_11->FindBin(1);
int maxBin_11 = hsx3bk_11->FindBin(5000);
int maxRangeBinContent_11 = -1;
double maxBinCenter_11 = 0.0;
if (sx3ChBk == 8) {
hsx3bk_8->Fill(sx3EBk);
for (int bin = minBin_8; bin <= maxBin_8; ++bin) {
if (hsx3bk_8->GetBinContent(bin) > maxRangeBinContent_8) {
maxRangeBinContent_8 = hsx3bk_8->GetBinContent(bin);
maxBinCenter_8 = hsx3bk_8->GetBinCenter(bin);
}
}
//peak8 = hsx3bk_8->GetMaximumBin();
//peak8 = hsx3bk_8->GetMaximumBin();
//printf("peak8: %f\n", maxBinCenter_8);
}
//printf("peak8_mm: %f\n", maxBinCenter);
else if (sx3ChBk == 9) {
hsx3bk_9->Fill(sx3EBk);
for (int bin = minBin_9; bin <= maxBin_9; ++bin) {
if (hsx3bk_9->GetBinContent(bin) > maxRangeBinContent_9) {
maxRangeBinContent_9 = hsx3bk_9->GetBinContent(bin);
maxBinCenter_9 = hsx3bk_9->GetBinCenter(bin);
}
}
//peak8 = hsx3bk_8->GetMaximumBin();
//peak8 = hsx3bk_8->GetMaximumBin();
//printf("peak9: %f\n", maxBinCenter_9);
//hsx3bk_9_shifted->Fill(sx3EBk*0.76);
peak9 = 2097.5/maxBinCenter_9;
//printf("peak9_shift: %f\n", peak9);
hsx3bk_9_shifted->Fill(sx3EBk*(2097.5/maxBinCenter_9));
//printf("peak9 %d\n", peak9);
}
else if(sx3ChBk == 10) {
hsx3bk_10->Fill(sx3EBk);
for (int bin = minBin_10; bin <= maxBin_10; ++bin) {
if (hsx3bk_10->GetBinContent(bin) > maxRangeBinContent_10) {
maxRangeBinContent_10 = hsx3bk_10->GetBinContent(bin);
maxBinCenter_10 = hsx3bk_10->GetBinCenter(bin);
}
}
//peak8 = hsx3bk_8->GetMaximumBin();
//peak8 = hsx3bk_8->GetMaximumBin();
//printf("peak10: %f\n", maxBinCenter_10);
//hsx3bk_9_shifted->Fill(sx3EBk*0.76);
peak10= 2097.5/maxBinCenter_10;
//printf("peak10_shift: %f\n", 1787.5/maxBinCenter_10);
hsx3bk_10_shifted->Fill(sx3EBk*(2097.5/maxBinCenter_10));
//printf("peak9 %d\n", peak9);
}
//peak10 = hsx3bk_10->GetMaximumBin();
// printf("peak10 %d\n" ,peak10);
else if(sx3ChBk == 11) {
hsx3bk_11->Fill(sx3EBk);
for (int bin = minBin_11; bin <= maxBin_11; ++bin) {
if (hsx3bk_11->GetBinContent(bin) > maxRangeBinContent_11) {
maxRangeBinContent_11 = hsx3bk_11->GetBinContent(bin);
maxBinCenter_11 = hsx3bk_11->GetBinCenter(bin);
}
}
//peak8 = hsx3bk_8->GetMaximumBin();
//peak8 = hsx3bk_8->GetMaximumBin();
//printf("peak9: %f\n", maxBinCenter_11);
//hsx3bk_9_shifted->Fill(sx3EBk*0.76);
peak11 = 2097.5/maxBinCenter_11;
//printf("peak11_shift: %f\n", peak11);
hsx3bk_11_shifted->Fill(sx3EBk*(2097.5/maxBinCenter_11));
//printf("peak9 %d\n", peak9);
}
float sx3EBk_shifted = 0.0;
float sx3E_u_matched_01 = 0.0;
float sx3E_d_matched_01 = 0.0;
float sx3E_fb_matched_01 = 0.0;
float sx3E_fbu_matched_01 = 0.0;
float sx3E_fbd_matched_01 = 0.0;
float diff =0.0;
float ratio = 0.0;
float coeff = 0.0;
if (sx3ChBk == 9) {
sx3EBk_shifted = (sx3EBk *(2097.5/maxBinCenter_9));
} else if (sx3ChBk == 10) {
sx3EBk_shifted = (sx3EBk * (2097.5/maxBinCenter_10));
} else if (sx3ChBk == 11) {
sx3EBk_shifted = (sx3EBk * (2097.5/maxBinCenter_11)) ;
} else {
sx3EBk_shifted = sx3EBk; // Use unshifted value for sx3ChBk == 8
}
if ((sx3ChUp == 1 && sx3ChDn == 0)) {
sx3E_u_matched_01= (sx3EUp-0.898729)/0.836243;
//sx3E_u_matched_01= (0.836243*sx3EDn)+0.898729;
sx3E_d_matched_01= (sx3EDn-0.898729)/0.836243;
sx3E_fb_matched_01=(sx3EBk_shifted+9.2423)/0.924773 ;
sx3E_fbu_matched_01=(sx3E_u_matched_01+9.2423)/0.924773 ;
sx3E_fbd_matched_01=(sx3E_d_matched_01+9.2423)/0.924773 ;
diff = sx3E_fb_matched_01 - (sx3EUp+sx3E_fbd_matched_01);
ratio = sx3EUp/sx3E_fbd_matched_01;
coeff = ((sx3EUp+diff) - (sx3E_fbd_matched_01*ratio))/(diff*(1+ratio));
}
//TH2F *hsx3uVsx3d_01 = nullptr;
if (sx3ChBk >=8) {
//if (sx3ChBk == 9) {
if ((sx3ChUp == 1 && sx3ChDn == 0)) {
if (sx3ChUp != -1 && sx3ChDn != -1 && sx3ChBk !=-1) {
if (sx3EBk_shifted > 50 && sx3EUp > 50 && sx3EDn > 50) {
printf("sx3EUp: %f, sx3EDn: %f, sx3E_u_matched_01: %f,sx3E_d_matched_01: %f\n", sx3EUp, sx3EDn, sx3E_u_matched_01,sx3E_d_matched_01);
//printf("Filling hsx3uVsx3d_01_shifted: %f\n", sx3EBk_ud_matched_01 / sx3EBk_shifted);
// hsx3uVsx3d_01->Fill(sx3E_u_matched_01 / sx3EBk_shifted, sx3E_d_matched_01 / sx3EBk_shifted);
hsx3uVsx3d_01->Fill(sx3EUp / sx3EBk_shifted, sx3E_d_matched_01 / sx3EBk_shifted);
hsx3uVsx3d_23->Fill(sx3EUp / sx3EBk_shifted, sx3EDn/ sx3EBk_shifted);
}
}
//}
}
else if ((sx3ChUp == 3 && sx3ChDn == 2)) {
if (sx3ChUp != -1 && sx3ChDn != -1 && sx3ChBk !=-1) {
if (sx3EBk_shifted != 0 && sx3EBk_shifted > 50 && sx3EUp > 50 && sx3EDn > 50) {
printf("sx3EUp: %f, sx3EDn: %f, sx3EBk_shifted: %f\n", sx3EUp, sx3EDn, sx3EBk_shifted);
printf("Filling hsx3uVsx3d_23_shifted: %f\n", sx3EUp / sx3EBk_shifted);
// hsx3uVsx3d_23->Fill(sx3EUp / sx3EBk_shifted, (-0.924754*sx3EUp+0.916671) / sx3EBk_shifted);
}
}
}
/* if ((sx3ChUp == 1 && sx3ChDn == 0)) {
if (sx3ChUp != -1 && sx3ChDn != -1 && sx3ChBk !=-1) {
if (sx3EBk != 0 && sx3EBk > 50 && sx3EUp > 50 && sx3EDn > 50) {
printf("sx3EUp: %f, sx3EDn: %f, sx3EBk: %f\n", sx3EUp, sx3EDn, sx3EBk);
printf("Filling hsx3uVsx3d_01: %f\n", sx3EUp / sx3EBk);
hsx3uVsx3d_45->Fill(sx3EUp / sx3EBk, sx3EDn / sx3EBk);
}
}
}
else if ((sx3ChUp == 3 && sx3ChDn == 2)) {
if (sx3ChUp != -1 && sx3ChDn != -1 && sx3ChBk !=-1) {
if (sx3EBk != 0 && sx3EBk > 50 && sx3EUp > 50 && sx3EDn > 50) {
printf("sx3EUp: %f, sx3EDn: %f, sx3EBk: %f\n", sx3EUp, sx3EDn, sx3EBk);
printf("Filling hsx3uVsx3d_23: %f\n", sx3EUp / sx3EBk);
hsx3uVsx3d_67->Fill(sx3EUp / sx3EBk, sx3EDn / sx3EBk);
}
}
}*/
if (sx3ChUp == 1 && sx3ChDn == 0){
//if (sx3ChUp == 1 || sx3ChDn == 0 || sx3ChUp == 3 || sx3ChDn == 2 || sx3ChUp == 5 || sx3ChDn == 4 || sx3ChUp == 7 || sx3ChDn == 6) {
if (sx3ChUp != -1 && sx3ChBk !=-1 && sx3ChDn !=-1) {
if (sx3EBk_shifted > 50 && sx3EUp > 50 && sx3EDn>50 &&sx3E_u_matched_01>50 && sx3E_u_matched_01>50) {
//printf("sx3EUp: %f, sx3EDn: %f, sx3E_u_matched_01: %f,sx3E_d_matched_01: %f\n", sx3EUp, sx3EDn, sx3E_u_matched_01,sx3E_d_matched_01);
printf("Filling hsx3uVsx3d_nn: %f, gggggg: %f \n", (sx3EUp+sx3EDn),(sx3E_u_matched_01+sx3E_d_matched_01) );
hsx3uVsx3d_45->Fill((sx3EUp+sx3E_d_matched_01),sx3EBk_shifted);
hsx3uVsx3d_67->Fill((sx3EUp+sx3E_d_matched_01),sx3E_fb_matched_01);
}
}
}
/*if (sx3ChBk > 8) {
if ((sx3ChUp == 7 && sx3ChDn == 6) ||
(sx3ChUp == 5 && sx3ChDn == 4) ||
(sx3ChUp == 3 && sx3ChDn == 2) ||
(sx3ChUp == 1 && sx3ChDn == 0)) {
if (sx3ChUp != -1 && sx3ChDn != -1 && sx3ChBk !=-1) {
if (sx3EBk != 0 && sx3EBk > 50 && sx3EUp > 50 && sx3EDn > 50) {
hsx3uVsx3d->Fill(sx3EUp / sx3EBk, sx3EDn / sx3EBk);
hsx3Vsx3->Fill(sx3EUp ,sx3EDn);
printf("sx3EUp: %f | sx3EDn: %f | sx3EBk: %f | sx3ChUp: %d | sx3ChDn: %d | sx3ChBk: %d\n", sx3EUp, sx3EDn, sx3EBk, sx3ChUp, sx3ChDn, sx3ChBk);
}
}
}
}*/
//else {
//printf("sx3EUp\n");
//}
if (sx3ChUp == 1 && sx3ChDn == 0){
if (sx3ChUp != -1 && sx3ChBk !=-1 && sx3ChDn !=-1) {
if (sx3E_d_matched_01> sx3EUp ) {
//printf("hZd_01_1_dn: %f\n", sx3E_d_matched_01);
//printf("hZd_01_1_b: %f\n", sx3E_fb_matched_01);
hZd_01_1->Fill((2*(sx3E_d_matched_01+(coeff*diff))/sx3E_fb_matched_01)-1);
}
else if(sx3EUp> sx3E_d_matched_01) {
//printf("hZd_01_2_sx3EUp: %f\n",sx3EUp );
//printf("hZd_01_2_sx3EDn: %f\n",sx3E_fb_matched_01);
hZd_01_2->Fill(1-(2*(sx3EUp+(1-coeff)*diff))/sx3E_fb_matched_01);
}
else if(sx3EUp>0.0 && sx3E_d_matched_01>0.0 && sx3E_d_matched_01>=sx3EUp ) {
hZd_01_3->Fill((2*(sx3E_d_matched_01+ coeff*diff)/sx3E_fb_matched_01)-1);
}
else if(sx3EUp>0.0 && sx3E_d_matched_01>0.0 && sx3E_d_matched_01<sx3EUp ) {
hZd_01_4->Fill(1-(2*(sx3EUp+ (1-coeff)*diff)/sx3E_fb_matched_01));
}
}
}
}
for (int j = 0; j < pc.multi; j++) {
if (sx3.ch[index] > 8) {
hsx3VpcE->Fill(sx3.e[i], pc.e[j]);
}
}
}
sx3_contr.CalSX3Pos(sx3ID[0].first, sx3ChUp, sx3ChDn, sx3ChBk, sx3EUp, sx3EDn);
hitPos = sx3_contr.GetHitPos();
HitNonZero = true;
// hitPos.Print();
}
}
// //======================= PC
//########################################################### Track constrcution
//############################## DO THE KINEMATICS
}
return kTRUE;
}
void gainmatch::Terminate(){
}

View File

@ -1,5 +1,5 @@
#ifndef GainMatchSX3_h
#define GainMatchSX3_h
#ifndef gainmatch_h
#define gainmatch_h
#include <TROOT.h>
#include <TChain.h>
@ -8,7 +8,7 @@
#include "Armory/ClassDet.h"
class GainMatchSX3 : public TSelector {
class gainmatch : public TSelector {
public :
TTree *fChain; //!pointer to the analyzed TTree or TChain
@ -41,8 +41,8 @@ public :
TBranch *b_pcE; //!
TBranch *b_pcT; //!
GainMatchSX3(TTree * /*tree*/ =0) : fChain(0) { }
virtual ~GainMatchSX3() { }
gainmatch(TTree * /*tree*/ =0) : fChain(0) { }
virtual ~gainmatch() { }
virtual Int_t Version() const { return 2; }
virtual void Begin(TTree *tree);
virtual void SlaveBegin(TTree *tree);
@ -57,13 +57,13 @@ public :
virtual void SlaveTerminate();
virtual void Terminate();
ClassDef(GainMatchSX3,0);
ClassDef(gainmatch,0);
};
#endif
#ifdef GainMatchSX3_cxx
void GainMatchSX3::Init(TTree *tree){
#ifdef gainmatch_cxx
void gainmatch::Init(TTree *tree){
// Set branch addresses and branch pointers
if (!tree) return;
@ -95,20 +95,20 @@ void GainMatchSX3::Init(TTree *tree){
}
Bool_t GainMatchSX3::Notify(){
Bool_t gainmatch::Notify(){
return kTRUE;
}
void GainMatchSX3::SlaveBegin(TTree * /*tree*/){
void gainmatch::SlaveBegin(TTree * /*tree*/){
TString option = GetOption();
}
void GainMatchSX3::SlaveTerminate(){
void gainmatch::SlaveTerminate(){
}
#endif // #ifdef GainMatchSX3_cxx
#endif // #ifdef gainmatch_cxx

View File

@ -19,7 +19,6 @@ const std::map<int, unsigned short> board = {
{4, 22129},
{5, 15529},
{6, 15528},
// {7,89},
{7, 334},
{8, 379},
{9, 325},
@ -28,14 +27,13 @@ const std::map<int, unsigned short> board = {
const int nBd = board.size();
const int nV1740 = 7;
const int nV1725 = 4;
const int nV1725 = 3;
//+++++++++++++++++++ detID;
// The detectors are seperated into 2 type: SuperX3, QQQ, and PC
// the SuperX3 has 24 detectors for each kind, wach detector has 12 channels
// the QQQ has 4 detectors for each kind, each detector has 32 channels
// the PC has 2 types, anode and cathode, each has 24 channels
// the MISC has 6 channels, the lollipop IC and siliscon followed by the hotneedle IC, as well as the Rf and MCP
// The detID = Type * 10000 + index * 100 + channel
// fro example, detID(superX3-8, ch-7) = 00807
@ -78,23 +76,17 @@ const std::vector<int> mapping = {
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
//================== 89
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
// 30004, -1, 30003, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
//================== 334
20116, 20117, 20118, 20119, -1, 20121, 20122, 20123, 20016, 20017, 20018, -1, 20020, 20021, 20022, 20023,
20116, 20117, 20118, 20119, 20120, 20121, 20122, 20123, 20016, 20017, 20018, 20019, 20020, 20021, 20022, 20023,
//================== 379
-1 , 20001, 20002, 20003, 20004, 20005, -1, 20007, 20008, -1, 20010, 20011, 20012, 20013, 20014, 20015,
20000, 20001, 20002, 20003, 20004, 20005, -1, 20007, 20008, -1, 20010, 20011, 20012, 20013, 20014, 20015,
//================== 325
20100, 20101, 20102, 20103, 20104, 20105, 20106, 20107, 20108, 20109, 20110, 20111, 20112, -1, 20114, 20115,
20100, 20101, 20102, 20103, 20104, 20105, 20106, 20107, 20108, 20109, 20110, 20111, 20112, 20113, 20114, 20115,
//================== 405
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
20006, -1, 30005, 20009, -1, 20120, 20000, 20019, 20113, 30000, 30004, 30001, 30002, -1, 30003, -1
20006, -1, -1, 20009, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1
};
//MCP moved from channel 1 to 2 after Run number 322
//MCP and Rf moved to ch 0 and 1 after Run number after Run282
//moved back to ch
void PrintMapping(){
int digiID = 0;
@ -149,9 +141,8 @@ void PrintMapping(){
printf("\033[35m%3d(%2d)\033[0m|", detID, ch);
}else if( typeID == 3){ // MISC
}else{
printf("\033[33m%3d(%2d)\033[0m|", detID, ch);
}
}
@ -224,6 +215,7 @@ void GenMapping(std::string mapFile){
detID += 20000;
if( words[3] == "ANODE") detID += atoi(words[4].c_str());
if( words[3] == "CATHODE") detID += 100 + atoi(words[4].c_str());
}
if( words[2] == "blank") {

View File

@ -1,23 +0,0 @@
Histogram Number Slope Intercept
24 1 -2.89219e-10
25 0.942098 -0.105169
26 0.980862 -0.732032
27 0.982975 -2.22704
28 0.978815 -1.51477
29 0.965245 -2.19515
30 0.945384 -0.892599
31 0.977408 -0.908592
32 0.919546 3.25464
33 0.972194 2.44956
34 0.92852 5.44745
35 0.947098 1.40531
36 0.875491 -1.13145
37 1.95496 -1735.58
38 0.970862 2.86019
40 0.91793 -3.80615
41 0.913897 -2.12964
42 0.954014 -0.760604
43 0.993616 -1.40278
45 0.926169 -21.2016
46 1.00577 -2.14281
47 0.943312 -1.26464

View File

@ -1,49 +0,0 @@
Histogram Number Slope Intercept
0 0.931015 -1.35431
1 1 -1.87356e-10
2 0.964185 1.49989
3 0.92638 -1.30621
4 0.905569 1.00834
5 0.901182 0.470903
6 0.853932 3.32687
7 0.942785 1.08887
8 0.878904 -0.0107433
9 0.922662 -2.32259
10 0.903343 8.38332
11 0.914227 6.56108
12 0.961008 23.0982
13 0.920976 5.22104
14 0.936584 31.5073
15 0.959044 5.43267
16 0.95263 -0.404053
17 0.90953 4.82833
18 0.940277 10.3629
19 0.86746 -17.8678
20 1.00683 4.76371
21 0.968342 -43.9496
22 0.892882 -32.0742
23 0.933615 1.10704
24 1 -2.89219e-10
25 0.942098 -0.105169
26 0.980862 -0.732032
27 0.982975 -2.22704
28 0.978815 -1.51477
29 0.965245 -2.19515
30 0.945384 -0.892599
31 0.977408 -0.908592
32 0.919546 3.25464
33 0.972194 2.44956
34 0.92852 5.44745
35 0.947098 1.40531
36 0.875491 -1.13145
37 1 0
38 0.970862 2.86019
39 1 0
40 0.91793 -3.80615
41 0.913897 -2.12964
42 0.954014 -0.760604
43 0.993616 -1.40278
44 1 0
45 0.926169 -21.2016
46 1.00577 -2.14281
47 0.943312 -1.26464

View File

@ -1,21 +0,0 @@
Histogram Number Slope Intercept
1 1 -1.87356e-10
2 0.964185 1.49989
3 0.92638 -1.30621
4 0.905569 1.00834
5 0.901182 0.470903
7 0.942785 1.08887
8 0.878904 -0.0107433
10 0.903343 8.38332
11 0.914227 6.56108
12 0.961008 23.0982
13 0.920976 5.22104
14 0.936584 31.5073
15 0.959044 5.43267
16 0.95263 -0.404053
17 0.90953 4.82833
18 0.940277 10.3629
20 1.00683 4.76371
21 0.968342 -43.9496
22 0.892882 -32.0742
23 0.933615 1.10704

View File

@ -1,12 +0,0 @@
7 0 1.20298
7 1 0.995493
7 2 0.993613
7 3 1.2514
9 0 1.01574
9 1 0.961032
9 2 0.988379
9 3 1.05832
19 0 1.07936
19 1 0.97626
19 2 1.00078
19 3 1.03335

View File

@ -1,8 +0,0 @@
3 0 1 1 -0.852399 0.881228
3 0 2 2 -0.813845 0.975967
3 0 3 3 -0.859643 0.863715
3 1 1 1 -0.76728 0.942438
3 1 2 2 -0.780302 0.929008
3 2 2 2 -0.729082 1.02005
3 3 2 2 -0.759098 1.05376
3 3 3 3 -0.821183 0.952335