16int main(
int argc,
char** argv)
19 bool printUsage = (argc == 1);
21 std::array<std::vector<std::string>, 3> inputFilenames;
22 std::string outputFilename =
"SimulatedAngularCorrelation.root";
23 double gateEnergy = 0.;
24 double fitEnergy = 0.;
26 bool singleCrystal =
false;
27 double distance = 145.;
29 double minEnergy = 0.;
30 double maxEnergy = 2000.;
32 std::string settingsFile;
35 for(
int i = 1; i < argc; ++i) {
36 if(strncmp(argv[i],
"-if", 2) == 0) {
39 if(strcmp(&argv[i][3],
"000") == 0) {
41 }
else if(strcmp(&argv[i][3],
"010") == 0) {
43 }
else if(strcmp(&argv[i][3],
"100") == 0) {
46 std::cerr <<
"Unknown -if* command line flag " << argv[i] <<
", should be -if000, -if010, or -if100!" << std::endl;
52 if(argv[i + 1][0] ==
'-') {
56 inputFilenames[coefficent].emplace_back(argv[++i]);
58 }
else if(strcmp(argv[i],
"-of") == 0) {
60 outputFilename = argv[++i];
62 std::cout <<
"Error, -of flag needs an argument!" << std::endl;
65 }
else if(strcmp(argv[i],
"-g") == 0) {
67 gateEnergy = std::atof(argv[++i]);
69 std::cout <<
"Error, -g flag needs an argument!" << std::endl;
72 }
else if(strcmp(argv[i],
"-f") == 0) {
74 fitEnergy = std::atof(argv[++i]);
76 std::cout <<
"Error, -f flag needs an argument!" << std::endl;
79 }
else if(strcmp(argv[i],
"-ab") == 0) {
81 }
else if(strcmp(argv[i],
"-sc") == 0) {
83 }
else if(strcmp(argv[i],
"-d") == 0) {
85 distance = std::atof(argv[++i]);
87 std::cout <<
"Error, -d flag needs an argument!" << std::endl;
90 }
else if(strcmp(argv[i],
"-vl") == 0) {
92 verboseLevel = std::atoi(argv[++i]);
94 std::cout <<
"Error, -vl flag needs an argument!" << std::endl;
97 }
else if(strcmp(argv[i],
"-sf") == 0) {
99 settingsFile = argv[++i];
101 std::cout <<
"Error, -sf flag needs an argument!" << std::endl;
105 std::cerr <<
"Error, unknown flag \"" << argv[i] <<
"\"!" << std::endl;
112 if(!settingsFile.empty()) {
115 if(inputFilenames[0].empty()) {
118 if(inputFilenames[1].empty()) {
121 if(inputFilenames[2].empty()) {
124 if(outputFilename ==
"SimulatedAngularCorrelation.root") {
125 outputFilename = settings.
GetString(
"OutputFilename",
"SimulatedAngularCorrelation.root");
127 std::cout <<
"Output filename has already been set to \"" << outputFilename <<
"\" via command line, ignoring settings file for this." << std::endl;
129 if(gateEnergy != 0.) {
130 std::cerr <<
"Warning, already got gate energy " << gateEnergy <<
", this could be overwritten by the settings file!" << std::endl;
132 gateEnergy = settings.
GetDouble(
"Energy.Gate", gateEnergy);
133 if(fitEnergy != 0.) {
134 std::cerr <<
"Warning, already got fit energy " << fitEnergy <<
", this could be overwritten by the settings file!" << std::endl;
136 fitEnergy = settings.
GetDouble(
"Energy.Fit", fitEnergy);
139 addback = settings.
GetBool(
"Addback",
true);
140 }
catch(std::out_of_range& e) {}
142 singleCrystal = settings.
GetBool(
"SingleCrystal",
true);
143 }
catch(std::out_of_range& e) {}
144 distance = settings.
GetDouble(
"Distance", distance);
145 bins = settings.
GetInt(
"Bins", bins);
146 minEnergy = settings.
GetDouble(
"Energy.Minimum", minEnergy);
147 maxEnergy = settings.
GetDouble(
"Energy.Minimum", maxEnergy);
148 verboseLevel = settings.
GetInt(
"Verbosity", verboseLevel);
151 if(!printUsage && (inputFilenames[0].empty() || inputFilenames[1].empty() || inputFilenames[2].empty())) {
152 std::cerr <<
"Error, need input files for all three !" << std::endl;
156 if(!printUsage && (gateEnergy <= 0. || fitEnergy <= 0.)) {
157 std::cerr <<
"Error, need energies for the gate (" << gateEnergy <<
") and the fit (" << fitEnergy <<
")!" << std::endl;
161 if(!printUsage && singleCrystal && !addback) {
162 std::cerr <<
"Error, can't have single crystal method without using addback!" << std::endl;
167 std::cerr <<
"Arguments for " << argv[0] <<
":" << std::endl
168 <<
"-if000 <input files> (required, geant4 simulation files for parameters 000)" << std::endl
169 <<
"-if010 <input files> (required, geant4 simulation files for parameters 010)" << std::endl
170 <<
"-if100 <input files> (required, geant4 simulation files for parameters 100)" << std::endl
171 <<
"-g <gate energy> (required)" << std::endl
172 <<
"-f <fit energy> (required)" << std::endl
173 <<
"-of <output filename> (optional, default = \"SimulatedAngularCorrelation.root\")" << std::endl
174 <<
"-ab (optional, enables addback)" << std::endl
175 <<
"-sc (optional, enables single crystal method, needs addback to be enabled!)" << std::endl
176 <<
"-d <GRIFFIN distance (110. or 145.)> (optional, default = 145.)" << std::endl
177 <<
"-vl <verbose level> (optional)" << std::endl;
182 if(distance != 145. && distance != 110.) {
183 std::cout <<
"Warning, distance is set to non-standard " << distance <<
" mm, are you sure this is correct?" << std::endl
184 <<
"Nominal distances are 145 mm in full suppression mode, and 110 mm in forward/high efficiency mode." << std::endl;
188 TFile output(outputFilename.c_str(),
"recreate");
189 if(!output.IsOpen()) {
190 std::cerr <<
"Failed to open file " << outputFilename <<
", maybe check permissions and disk space?" << std::endl;
198 std::map<uint32_t, TFragment> fragments;
203 std::string conditions = addback ?
"using addback" :
"without addback";
204 conditions += singleCrystal ?
" single crystal" :
"";
206 std::array<std::vector<TH2D*>, 3> hists;
207 std::array<TGraphErrors, 3> graph;
209 graph[0].SetName(
"graph000");
210 graph[0].SetTitle(Form(
"Simulated angular correlation coeff. 000, using %s;angle [#circ]", conditions.c_str()));
212 graph[1].SetName(
"graph010");
213 graph[1].SetTitle(Form(
"Simulated angular correlation coeff. 010, using %s;angle [#circ]", conditions.c_str()));
215 graph[2].SetName(
"graph100");
216 graph[2].SetTitle(Form(
"Simulated angular correlation coeff. 100, using %s;angle [#circ]", conditions.c_str()));
219 for(
int c = 0; c < 3; ++c) {
222 for(
auto angle = angles.
begin(); angle != angles.
end(); ++angle) {
223 int i = std::distance(angles.
begin(), angle);
224 hists[c][i] =
new TH2D(Form(
"AngularCorrelation%d_%d", c, i), Form(
"%.1f^{o}: Simulated suppressed #gamma-#gamma %s", *angle, conditions.c_str()), bins, minEnergy, maxEnergy, bins, minEnergy, maxEnergy);
229 TChain chain(
"ntuple");
231 for(
auto filename : inputFilenames[c]) {
232 chain.Add(filename.c_str());
235 Int_t eventNumber = 0;
236 chain.SetBranchAddress(
"eventNumber", &eventNumber);
238 chain.SetBranchAddress(
"systemID", &systemID);
240 chain.SetBranchAddress(
"detNumber", &detNumber);
242 chain.SetBranchAddress(
"cryNumber", &cryNumber);
243 Double_t depEnergy = 0.;
244 chain.SetBranchAddress(
"depEnergy", &depEnergy);
246 chain.SetBranchAddress(
"time", &time);
249 int oldEventNumber = 0;
250 uint32_t address = 0xdead;
251 std::string mnemonic;
252 std::string crystalColor =
"BGRW";
254 long int nEntries = chain.GetEntries();
255 if(verboseLevel > 1) {
256 std::cout <<
"Starting loop over " << nEntries <<
" entries, using angles:" << std::endl;
259 std::map<double, int> unknownAngles;
260 for(
long int e = 0; e < nEntries; ++e) {
261 int status = chain.GetEntry(e);
263 std::cerr <<
"Error occured, couldn't read entry " << e <<
" from tree " << chain.GetName() <<
" in file " << chain.GetFile()->GetName() << std::endl;
265 }
else if(status == 0) {
266 std::cerr <<
"Error occured, entry " << e <<
" in tree " << chain.GetName() <<
" in file " << chain.GetFile()->GetName() <<
" doesn't exist" << std::endl;
269 if(eventNumber != oldEventNumber) {
275 std::vector<TFragment> fragmentCopy;
276 std::transform(fragments.begin(), fragments.end(), std::back_inserter(fragmentCopy), [](std::pair<const uint32_t, TFragment>& kv) { return kv.second; });
277 std::sort(fragmentCopy.begin(), fragmentCopy.end());
279 for(
auto& frag : fragmentCopy) {
281 switch(frag.GetAddress() / 1000) {
283 griffin.
AddFragment(std::make_shared<TFragment>(frag), channel);
286 grifBgo.
AddFragment(std::make_shared<TFragment>(frag), channel);
294 std::cout <<
"New event number is " << eventNumber <<
", processing old event " << oldEventNumber << std::endl;
305 double angle = grif1->GetPosition(distance).Angle(grif2->GetPosition(distance)) * 180. / TMath::Pi();
306 if(verboseLevel > 4) {
307 std::cout <<
"det,/cry. " << grif1->GetDetector() <<
"/" << grif1->GetCrystal() <<
" with " << grif2->GetDetector() <<
"/" << grif2->GetCrystal() <<
" = " << angle << std::endl;
310 if(verboseLevel < 3) {
312 angleIndex = angles.
Index(angle);
314 angleIndex = angles.
Index(angle);
316 if(verboseLevel > 4) {
317 std::cout <<
"Filling histograms at index " << angleIndex <<
" = " << angle <<
" degree, with " << grif1->GetEnergy() <<
", " << grif2->GetEnergy() << std::endl;
319 if(angleIndex >= 0) {
320 hists[c].at(angleIndex)->Fill(grif1->GetEnergy(), grif2->GetEnergy());
321 hists[c].at(angleIndex)->Fill(grif2->GetEnergy(), grif1->GetEnergy());
323 unknownAngles[angle]++;
324 if(verboseLevel > 4) {
325 std::cout <<
"Not filling histogram for griffin hits:" << std::endl;
339 address = 4 * detNumber + cryNumber;
346 address = 1000 + 10 * detNumber + cryNumber;
352 if(fragments.count(address) == 1) {
353 if(verboseLevel > 3) {
354 std::cout <<
"Found second hit for address " << address <<
", updating time and energy from " << fragments[address].GetTime() <<
", " << fragments[address].GetCharge();
357 if(depEnergy > fragments[address].GetCharge()) {
360 fragments[address].SetTimeStamp(time * 1e8);
361 fragments[address].SetCfd(
static_cast<int>(time * 16e8) & 0x3fffff);
363 fragments[address].SetCharge(fragments[address].GetCharge() +
static_cast<float>(depEnergy));
364 if(verboseLevel > 3) {
365 std::cout <<
" to " << fragments[address].GetTime() <<
", " << fragments[address].GetCharge() << std::endl;
368 fragments[address].SetAddress(address);
369 fragments[address].SetTimeStamp(time * 1e8);
370 fragments[address].SetCfd(
static_cast<int>(time * 16e8) & 0x3fffff);
371 fragments[address].SetCharge(
static_cast<float>(depEnergy));
373 if(channel ==
nullptr) {
376 mnemonic = Form(
"GRG%02d%cN00A", detNumber, crystalColor[cryNumber]);
383 mnemonic = Form(
"GRS%02d%cN%02d", detNumber, crystalColor[cryNumber], cryNumber);
390 channel->
SetName(mnemonic.c_str());
398 oldEventNumber = eventNumber;
401 std::cout << std::setw(3) << (100 * e) / nEntries <<
"% done\r" << std::flush;
405 std::cout <<
"100% done" << std::endl;
407 if(verboseLevel > 0) {
408 std::cout <<
"coeff. " << c <<
": done looping over the tree and creating histograms" << std::endl;
411 if(unknownAngles.size() > 0) {
412 std::cout << unknownAngles.size() <<
" unknown angles:" << std::endl;
413 for(
auto& angle : unknownAngles) {
414 std::cout << std::setw(10) << angle.first <<
" found " << std::setw(8) << angle.second <<
" times" << std::endl;
419 for(
size_t i = 0; i < hists[c].size(); ++i) {
420 auto counts = hists[c][i]->GetBinContent(hists[c][i]->GetXaxis()->FindBin(gateEnergy), hists[c][i]->GetYaxis()->FindBin(fitEnergy));
421 graph[c].SetPoint(i, angles.
Angle(i), counts / angles.
Count(angles.
Angle(i)));
422 graph[c].SetPointError(i, 0., TMath::Sqrt(counts) / angles.
Count(angles.
Angle(i)));
426 for(
auto*
hist : hists[c]) {
433 if(verboseLevel > 0) {
434 std::cout << c <<
": done writing histograms and graph" << std::endl;
442 std::cout <<
"done, wrote results to " << outputFilename << std::endl;