9#if __cplusplus >= 201703L
15#include "TGTableLayout.h"
17#include "TLinearFitter.h"
20#include "TPolyMarker.h"
30std::map<double, std::tuple<double, double, double, double>>
RoughCal(std::vector<double> peaks, std::vector<std::tuple<double, double, double, double>> sources,
TSourceTab* sourceTab)
37 for(
size_t i = 0; i < peaks.size() || i < sources.size(); ++i) {
38 std::cout << i <<
".: " << std::setw(8);
39 if(i < peaks.size()) {
40 std::cout << peaks[i];
44 std::cout <<
" - " << std::setw(8);
45 if(i < sources.size()) {
46 std::cout << std::get<0>(sources[i]);
50 std::cout << std::endl;
54 std::map<double, std::tuple<double, double, double, double>> result;
55 std::sort(peaks.begin(), peaks.end());
56 std::sort(sources.begin(), sources.end(), [](
const std::tuple<double, double, double, double>& a,
const std::tuple<double, double, double, double>& b) { return std::get<2>(a) > std::get<2>(b); });
58 auto maxSize = std::max(peaks.size(), sources.size());
63 TLinearFitter fitter(1,
"1 ++ x");
66 std::vector<double> sourceValues(sources.size());
67 std::map<double, double> tmpMap;
69 for(
size_t num_data_points = std::min(peaks.size(), sourceValues.size()); num_data_points > 0; num_data_points--) {
71 double best_chi2 = DBL_MAX;
73 for(
auto peak_values :
combinations(peaks, num_data_points)) {
75 peak_values.push_back(0);
79 sourceValues.resize(num_data_points);
80 for(
size_t i = 0; i < sourceValues.size(); ++i) { sourceValues[i] = std::get<0>(sources[i]); }
81 std::sort(sourceValues.begin(), sourceValues.end());
82 sourceValues.push_back(0);
85 for(
size_t i = 0; i < peak_values.size(); ++i) {
86 std::cout << i <<
".: " << std::setw(8) << peak_values[i] <<
" - " << std::setw(8) << sourceValues[i] << std::endl;
89 if(peaks.size() > 3) {
90 double pratio = peak_values.front() / peak_values.at(peak_values.size() - 2);
91 double sratio = sourceValues.front() / sourceValues.at(sourceValues.size() - 2);
93 if(std::abs(pratio - sratio) > 0.02) {
100 fitter.AssignData(sourceValues.size(), 1, peak_values.data(), sourceValues.data());
103 if(fitter.GetChisquare() < best_chi2) {
105 for(
size_t i = 0; i < num_data_points; i++) {
106 tmpMap[peak_values[i]] = sourceValues[i];
108 best_chi2 = fitter.GetChisquare();
110 sourceTab->
Status(Form(
"%zu/%zu - %zu - %d", num_data_points, peaks.size(), maxSize, iteration), 1);
116 if(tmpMap.size() > 2) {
117 std::vector<double> peak_values;
118 std::vector<double> source_values;
119 for(
auto& item : tmpMap) {
120 peak_values.push_back(item.first);
121 source_values.push_back(item.second);
124 for(
size_t skipped_point = 0; skipped_point < source_values.size(); skipped_point++) {
125 std::swap(peak_values[skipped_point], peak_values.back());
126 std::swap(source_values[skipped_point], source_values.back());
128 fitter.ClearPoints();
129 fitter.AssignData(source_values.size() - 1, 1, peak_values.data(), source_values.data());
132 if(std::abs(fitter.GetParameter(0)) > 10) {
134 std::cout << fitter.GetParameter(0) <<
" too big an offset, clearing map with " << tmpMap.size() <<
" points: ";
135 for(
auto iter : tmpMap) { std::cout << iter.first <<
" - " << iter.second <<
"; "; }
136 std::cout << std::endl;
142 std::swap(peak_values[skipped_point], peak_values.back());
143 std::swap(source_values[skipped_point], source_values.back());
148 if(!tmpMap.empty()) {
152 for(
auto iter : tmpMap) {
153 result[*(std::find_if(peaks.begin(), peaks.end(), [&iter](
auto& item) { return iter.first == item; }))] =
154 *(std::find_if(sources.begin(), sources.end(), [&iter](
auto& item) { return iter.second == std::get<0>(item); }));
157 std::cout <<
"Smart matched " << num_data_points <<
" data points from " << peaks.size() <<
" peaks with " << sources.size() <<
" source energies" << std::endl;
158 std::cout <<
"Returning map with " << result.size() <<
" points: ";
159 for(
auto iter : result) { std::cout << iter.first <<
" - " << std::get<0>(iter.second) <<
"; "; }
160 std::cout << std::endl;
164 sourceTab->
Status(Form(
"%zu/%zu - %zu", num_data_points, peaks.size(), maxSize), 1);
170std::map<TGauss*, std::tuple<double, double, double, double>>
Match(std::vector<TGauss*> peaks, std::vector<std::tuple<double, double, double, double>> sources,
TSourceTab* sourceTab)
177 std::cout <<
"peaks:";
178 for(
auto* peak : peaks) {
179 std::cout <<
" " << peak->Centroid();
181 std::cout << std::endl;
182 std::cout <<
"energies:";
183 for(
auto source : sources) {
184 std::cout <<
" " << std::get<0>(source);
186 std::cout << std::endl;
189 std::map<TGauss*, std::tuple<double, double, double, double>> result;
190 std::sort(peaks.begin(), peaks.end(), [](
const TGauss* a,
const TGauss* b) { return a->Centroid() < b->Centroid(); });
191 std::sort(sources.begin(), sources.end());
193 auto maxSize = std::max(peaks.size(), sources.size());
198 TLinearFitter fitter(1,
"1 ++ x");
201 std::vector<double> peakValues(peaks.size());
202 for(
size_t i = 0; i < peaks.size(); ++i) { peakValues[i] = peaks[i]->Centroid(); }
203 std::vector<double> sourceValues(sources.size());
204 for(
size_t i = 0; i < sources.size(); ++i) { sourceValues[i] = std::get<0>(sources[i]); }
205 std::map<double, double> tmpMap;
207 for(
size_t num_data_points = peakValues.size(); num_data_points > 0; num_data_points--) {
209 double best_chi2 = DBL_MAX;
211 for(
auto peak_values :
combinations(peakValues, num_data_points)) {
213 peak_values.push_back(0);
214 for(
auto source_values :
combinations(sourceValues, num_data_points)) {
215 source_values.push_back(0);
217 if(peakValues.size() > 3) {
218 double pratio = peak_values.front() / peak_values.at(peak_values.size() - 2);
219 double sratio = source_values.front() / source_values.at(source_values.size() - 2);
221 if(std::abs(pratio - sratio) > 0.02) {
228 fitter.ClearPoints();
229 fitter.AssignData(source_values.size(), 1, peak_values.data(), source_values.data());
232 if(fitter.GetChisquare() < best_chi2) {
234 for(
size_t i = 0; i < num_data_points; i++) {
235 tmpMap[peak_values[i]] = source_values[i];
238 std::cout <<
"Chi^2 " << fitter.GetChisquare() <<
" better than " << best_chi2 <<
":" << std::endl;
239 for(
auto iter : tmpMap) {
240 std::cout << std::setw(10) << iter.first <<
" - " << iter.second << std::endl;
243 best_chi2 = fitter.GetChisquare();
246 sourceTab->
Status(Form(
"%zu/%zu - %zu - %d", num_data_points, peakValues.size(), maxSize, iteration), 1);
252 if(tmpMap.size() > 2) {
253 std::vector<double> peak_values;
254 std::vector<double> source_values;
255 for(
auto& item : tmpMap) {
256 peak_values.push_back(item.first);
257 source_values.push_back(item.second);
260 for(
size_t skipped_point = 0; skipped_point < source_values.size(); skipped_point++) {
261 std::swap(peak_values[skipped_point], peak_values.back());
262 std::swap(source_values[skipped_point], source_values.back());
264 fitter.ClearPoints();
265 fitter.AssignData(source_values.size() - 1, 1, peak_values.data(), source_values.data());
268 if(std::abs(fitter.GetParameter(0)) > 10) {
270 std::cout << fitter.GetParameter(0) <<
" too big, clearing map with " << tmpMap.size() <<
" points: ";
271 for(
auto iter : tmpMap) { std::cout << iter.first <<
" - " << iter.second <<
"; "; }
272 std::cout << std::endl;
278 std::swap(peak_values[skipped_point], peak_values.back());
279 std::swap(source_values[skipped_point], source_values.back());
284 if(!tmpMap.empty()) {
285 for(
auto iter : tmpMap) {
286 result[*(std::find_if(peaks.begin(), peaks.end(), [&iter](
auto& item) { return iter.first == item->Centroid(); }))] =
287 *(std::find_if(sources.begin(), sources.end(), [&iter](
auto& item) { return iter.second == std::get<0>(item); }));
293 std::cout <<
"Matched " << num_data_points <<
" data points from " << peaks.size() <<
" peaks with " << sources.size() <<
" source energies" << std::endl;
294 std::cout <<
"Returning map with " << result.size() <<
" points: ";
295 for(
auto iter : result) { std::cout << iter.first->Centroid() <<
" - " << std::get<0>(iter.second) <<
"; "; }
296 std::cout << std::endl;
300 sourceTab->
Status(Form(
"%zu/%zu - %zu", num_data_points, peakValues.size(), maxSize), 1);
306std::map<TGauss*, std::tuple<double, double, double, double>>
SmartMatch(std::vector<TGauss*> peaks, std::vector<std::tuple<double, double, double, double>> sources,
TSourceTab* sourceTab)
313 for(
size_t i = 0; i < peaks.size() || i < sources.size(); ++i) {
314 std::cout << i <<
".: " << std::setw(8);
315 if(i < peaks.size()) {
316 std::cout << peaks[i]->Centroid();
320 std::cout <<
" - " << std::setw(8);
321 if(i < sources.size()) {
322 std::cout << std::get<0>(sources[i]);
326 std::cout << std::endl;
330 std::map<TGauss*, std::tuple<double, double, double, double>> result;
331 std::sort(peaks.begin(), peaks.end(), [](
const TGauss* a,
const TGauss* b) { return a->Centroid() < b->Centroid(); });
332 std::sort(sources.begin(), sources.end(), [](
const std::tuple<double, double, double, double>& a,
const std::tuple<double, double, double, double>& b) { return std::get<2>(a) > std::get<2>(b); });
334 auto maxSize = std::max(peaks.size(), sources.size());
339 TLinearFitter fitter(1,
"1 ++ x");
342 std::vector<double> peakValues(peaks.size());
343 for(
size_t i = 0; i < peaks.size(); ++i) { peakValues[i] = peaks[i]->Centroid(); }
344 std::vector<double> sourceValues(sources.size());
345 std::map<double, double> tmpMap;
347 for(
size_t num_data_points = std::min(peakValues.size(), sourceValues.size()); num_data_points > 0; num_data_points--) {
349 double best_chi2 = DBL_MAX;
351 for(
auto peak_values :
combinations(peakValues, num_data_points)) {
353 peak_values.push_back(0);
357 sourceValues.resize(num_data_points);
358 for(
size_t i = 0; i < sourceValues.size(); ++i) { sourceValues[i] = std::get<0>(sources[i]); }
359 std::sort(sourceValues.begin(), sourceValues.end());
360 sourceValues.push_back(0);
363 for(
size_t i = 0; i < peak_values.size(); ++i) {
364 std::cout << i <<
".: " << std::setw(8) << peak_values[i] <<
" - " << std::setw(8) << sourceValues[i] << std::endl;
367 if(peakValues.size() > 3) {
368 double pratio = peak_values.front() / peak_values.at(peak_values.size() - 2);
369 double sratio = sourceValues.front() / sourceValues.at(sourceValues.size() - 2);
371 if(std::abs(pratio - sratio) > 0.02) {
377 fitter.ClearPoints();
378 fitter.AssignData(sourceValues.size(), 1, peak_values.data(), sourceValues.data());
381 if(fitter.GetChisquare() < best_chi2) {
383 for(
size_t i = 0; i < num_data_points; i++) {
384 tmpMap[peak_values[i]] = sourceValues[i];
386 best_chi2 = fitter.GetChisquare();
388 sourceTab->
Status(Form(
"%zu/%zu - %zu - %d", num_data_points, peakValues.size(), maxSize, iteration), 1);
394 if(tmpMap.size() > 2) {
395 std::vector<double> peak_values;
396 std::vector<double> source_values;
397 for(
auto& item : tmpMap) {
398 peak_values.push_back(item.first);
399 source_values.push_back(item.second);
402 for(
size_t skipped_point = 0; skipped_point < source_values.size(); skipped_point++) {
403 std::swap(peak_values[skipped_point], peak_values.back());
404 std::swap(source_values[skipped_point], source_values.back());
406 fitter.ClearPoints();
407 fitter.AssignData(source_values.size() - 1, 1, peak_values.data(), source_values.data());
410 if(std::abs(fitter.GetParameter(0)) > 10) {
412 std::cout << fitter.GetParameter(0) <<
" too big an offset, clearing map with " << tmpMap.size() <<
" points: ";
413 for(
auto iter : tmpMap) { std::cout << iter.first <<
" - " << iter.second <<
"; "; }
414 std::cout << std::endl;
420 std::swap(peak_values[skipped_point], peak_values.back());
421 std::swap(source_values[skipped_point], source_values.back());
426 if(!tmpMap.empty()) {
430 for(
auto iter : tmpMap) {
431 result[*(std::find_if(peaks.begin(), peaks.end(), [&iter](
auto& item) { return iter.first == item->Centroid(); }))] =
432 *(std::find_if(sources.begin(), sources.end(), [&iter](
auto& item) { return iter.second == std::get<0>(item); }));
435 std::cout <<
"Smart matched " << num_data_points <<
" data points from " << peaks.size() <<
" peaks with " << sources.size() <<
" source energies" << std::endl;
436 std::cout <<
"Returning map with " << result.size() <<
" points: ";
437 for(
auto iter : result) { std::cout << iter.first->Centroid() <<
" - " << std::get<0>(iter.second) <<
"; "; }
438 std::cout << std::endl;
442 sourceTab->
Status(Form(
"%zu/%zu - %zu", num_data_points, peakValues.size(), maxSize), 1);
450 double result = par[1];
451 for(
int i = 1; i <= par[0]; ++i) {
452 result += par[i + 1] * TMath::Power(x[0], i);
459 return (matrix->Integral(bin, bin, 1, matrix->GetNbinsY()) > 1000);
464 : fSourceCalibration(sourceCal), fChannelTab(channel), fSourceFrame(frame), fProjection(projection), fSourceName(sourceName), fSourceEnergy(std::move(sourceEnergy))
498 for(
auto* fit :
fFits) {
506 for(
auto* peak :
fPeaks) {
535 std::array<int, 3> parts = {35, 50, 15};
550 fProjectionCanvas->GetCanvas()->Connect(
"ProcessedEvent(Int_t,Int_t,Int_t,TObject*)",
"TSourceTab",
this,
"ProjectionStatus(Int_t,Int_t,Int_t,TObject*)");
551 fProjectionCanvas->Connect(
"ProcessedEvent(Event_t*)",
"TSourceTab",
this,
"ProjectionStatus(Event_t*)");
557 fProjectionCanvas->Disconnect(
"ProcessedEvent(Event_t*)",
this,
"ProjectionStatus(Event_t*)");
558 fProjectionCanvas->GetCanvas()->Disconnect(
"ProcessedEvent(Int_t,Int_t,Int_t,TObject*)",
this,
"ProjectionStatus(Int_t,Int_t,Int_t,TObject*)");
576 if(event->fType == kEnterNotify) {
578 std::cout <<
"Entered source tab => changing gPad from " << gPad->GetName();
582 std::cout <<
" to " << gPad->GetName() << std::endl;
602 if(selected ==
nullptr) {
return; }
603 Status(selected->GetName(), 0);
604 Status(selected->GetObjectInfo(px, py), 1);
611 std::cout <<
fPeaks.size() <<
" peaks:";
612 for(
auto* peak :
fPeaks) {
613 std::cout <<
" " << peak->Centroid();
615 std::cout << std::endl;
628 if(peak->Area() > 0) {
633 std::cout <<
"Ignoring peak at " << peak->Centroid() <<
" with negative area " << peak->Area() << std::endl;
638 std::sort(
fPeaks.begin(),
fPeaks.end(), [](
const TGauss* a,
const TGauss* b) { return a->Centroid() < b->Centroid(); });
649 Status(Form(
"%d/%d",
static_cast<int>(
fData->GetN()),
static_cast<int>(
fPeaks.size())), 2);
655 }
else if(selected->IsA() == GH1D::Class() &&
fProjection !=
nullptr) {
656 std::cout <<
"selected object " << selected <<
" is a histogram called " << selected->GetName() <<
" and not the projection " <<
fProjection <<
" called " <<
fProjection->GetName() <<
", going to redraw the projection" << std::endl;
659 std::cout <<
DCYAN <<
"Selected object " << selected <<
" (" << selected->ClassName() <<
" called " << selected->GetName() <<
") does not match projection " <<
fProjection <<
" (" <<
fProjection->ClassName() <<
" called " <<
fProjection->GetName() <<
")" << std::endl;
709 std::cout <<
"unprocessed event " <<
event <<
" with px, py " << px <<
", " << py <<
" selected object is a " << selected->ClassName() <<
" with name \"" << selected->GetName() <<
"\" and title \"" << selected->GetTitle() <<
"\" object info is " << selected->GetObjectInfo(px, py) << std::endl;
725 if(obj->InheritsFrom(TRegion::Class())) {
726 auto* region =
static_cast<TRegion*
>(obj);
729 fRegions.emplace_back(std::min(region->GetX1(), region->GetX2()), std::max(region->GetX1(), region->GetX2()));
731 std::cout << obj->GetName() <<
" is not a TRegion but a " << obj->ClassName() << std::endl;
744 TList* functions =
fProjection->GetListOfFunctions();
746 std::cout <<
"Updating functions for histogram " <<
fProjection->GetName() <<
" by deleting " << functions->GetEntries() <<
" functions:" << std::endl;
747 for(
auto* obj : *functions) {
748 std::cout << obj <<
": " << obj->GetName() <<
"/" << obj->GetTitle() <<
" - " << obj->ClassName();
749 if(obj->IsA() == TF1::Class()) {
750 std::cout <<
" line color " <<
static_cast<TF1*
>(obj)->GetLineColor();
752 std::cout <<
" not a TF1";
754 std::cout << std::endl;
759 TObject* fit =
nullptr;
760 while((fit = functions->FindObject(
"gauss_total")) !=
nullptr) {
761 functions->Remove(fit);
764 for(
auto* obj :
fFits) {
765 functions->Add(obj->GetFitFunction()->Clone(
"gauss_total"));
769 functions->Add(obj->GetFitFunction()->Clone(
"gauss_total"));
772 std::cout <<
"And adding " << functions->GetEntries() <<
" functions instead:" << std::endl;
773 for(
auto* obj : *functions) {
774 std::cout << obj <<
": " << obj->GetName() <<
"/" << obj->GetTitle() <<
" - " << obj->ClassName();
775 if(obj->IsA() == TF1::Class()) {
776 std::cout <<
" line color " <<
static_cast<TF1*
>(obj)->GetLineColor();
778 std::cout <<
" not a TF1";
780 std::cout << std::endl;
783 if(!
fFits.empty() &&
fFits.front()->NumberOfPeaks() > 0 &&
fFits.back()->NumberOfPeaks() > 0) {
808 std::cout << __PRETTY_FUNCTION__ <<
": # peaks " <<
fPeaks.size() << std::endl;
816 TList* functions =
fProjection->GetListOfFunctions();
817 std::cout << functions->GetEntries() <<
" functions in projection " <<
fProjection->GetName() <<
" before clearing" << std::endl;
818 for(
auto* obj : *functions) {
819 std::cout << obj->GetName() <<
"/" << obj->GetTitle() <<
" - " << obj->ClassName() << std::endl;
825 std::vector<double> peakPos;
830 nofPeaks = spectrum.GetNPeaks();
831 peakPos.insert(peakPos.end(), spectrum.GetPositionX(), spectrum.GetPositionX() + nofPeaks);
834 fProjection->GetXaxis()->SetRangeUser(region.first, region.second);
836 int tmpNofPeaks = spectrum.GetNPeaks();
837 peakPos.insert(peakPos.end(), spectrum.GetPositionX(), spectrum.GetPositionX() + tmpNofPeaks);
838 nofPeaks += spectrum.GetNPeaks();
849 Status(Form(
"%d/%d",
static_cast<int>(
fData->GetN()), nofPeaks), 2);
859 if(calibration ==
nullptr) {
860 std::cerr << __PRETTY_FUNCTION__ <<
": provided calibration is nullptr, this function can only be called after an initial calibration has been made!" << std::endl;
873 std::cout <<
"calibration has " << calibration->GetNpar() <<
" parameters (";
874 for(
int i = 0; i < calibration->GetNpar(); ++i) {
878 std::cout << i <<
": " << calibration->GetParameter(i);
880 std::cout <<
"), if linear offset is " << calibration->Eval(0) <<
" and gain is " << calibration->Eval(1) - calibration->Eval(0) << std::endl;
881 TList* functions =
fProjection->GetListOfFunctions();
882 std::cout << functions->GetEntries() <<
" functions in projection " <<
fProjection->GetName() <<
" before clearing" << std::endl;
883 for(
auto* obj : *functions) {
884 std::cout << obj->GetName() <<
"/" << obj->GetTitle() <<
" - " << obj->ClassName() << std::endl;
889 std::map<TGauss*, std::tuple<double, double, double, double>> map;
893 std::vector<std::pair<std::tuple<double, double, double, double>,
double>> channelPos;
897 std::cout <<
"Skipping peak at " << std::get<0>(tuple) <<
" keV with intensity " << std::get<2>(tuple) <<
" below required minimum intensity " <<
TSourceCalibration::MinIntensity() << std::endl;
901 channelPos.emplace_back(tuple, calibration->GetX(std::get<0>(tuple)));
903 std::cout <<
"Set channel position for " << channelPos.size() - 1 <<
". peak to " << channelPos.back().second <<
" channels = " << std::get<0>(channelPos.back().first) <<
" keV" << std::endl;
907 for(
size_t i = 0; i < channelPos.size(); ++i) {
913 if(channelPos[i].second - lowRange < channelPos[i - 1].second + highRange) {
915 std::cout << channelPos[i].second - lowRange <<
" < " << channelPos[i - 1].second + highRange <<
": changing low range from " << lowRange <<
" to " << std::max(lowRange / 2., (channelPos[i].second - channelPos[i - 1].second) / 2.) <<
" = std::max(" << lowRange / 2. <<
", " << (channelPos[i].second - channelPos[i - 1].second) / 2. <<
" = (" << channelPos[i].second <<
" - " << channelPos[i - 1].second <<
"/2.)" << std::endl;
917 lowRange = std::max(lowRange / 2., (channelPos[i].second - channelPos[i - 1].second) / 2.);
920 if(i + 1 < channelPos.size()) {
921 if(channelPos[i].second + highRange > channelPos[i + 1].second - lowRange) {
923 std::cout << channelPos[i].second + highRange <<
" > " << channelPos[i + 1].second - lowRange <<
": changing high range from " << highRange <<
" to " << std::max(highRange / 2., (channelPos[i + 1].second - channelPos[i].second) / 2.) <<
" = std::max(" << highRange / 2. <<
", " << (channelPos[i + 1].second - channelPos[i].second) / 2. <<
" = (" << channelPos[i + 1].second <<
" - " << channelPos[i].second <<
"/2.)" << std::endl;
925 highRange = std::min(highRange / 2., (channelPos[i + 1].second - channelPos[i].second) / 2.);
929 std::cout <<
"Trying to fit peak " << channelPos[i].second <<
" in range " << channelPos[i].second - lowRange <<
" - " << channelPos[i].second + highRange << std::endl;
932 auto* pf =
new TPeakFitter(channelPos[i].second - lowRange, channelPos[i].second + highRange);
933 auto* peak =
new TGauss(channelPos[i].second);
941 if(peak->Area() > 0) {
943 if(
Good(peak, channelPos[i].second - lowRange, channelPos[i].second + highRange)) {
946 map[peak] = channelPos[i].first;
948 std::cout <<
"Fitted peak " << channelPos[i].second - lowRange <<
" - " << channelPos[i].second + highRange <<
" -> centroid " << peak->Centroid() <<
", area " << peak->Area() << std::endl;
953 std::cout <<
"We're ignoring bad fits, and this one has position " << peak->Centroid() <<
" +- " << peak->CentroidErr() <<
", area " << peak->Area() <<
" +- " << peak->AreaErr() << std::endl;
957 std::cout <<
"Ignoring peak at " << peak->Centroid() <<
" with negative area " << peak->Area() << std::endl;
964 std::sort(
fFits.begin(),
fFits.end(), [](
const TPeakFitter* a,
const TPeakFitter* b) { return a->GetFitFunction()->GetParameter(
"centroid_0") < b->GetFitFunction()->GetParameter(
"centroid_0"); });
965 std::sort(
fBadFits.begin(),
fBadFits.end(), [](
const TPeakFitter* a,
const TPeakFitter* b) { return a->GetFitFunction()->GetParameter(
"centroid_0") < b->GetFitFunction()->GetParameter(
"centroid_0"); });
966 std::sort(
fPeaks.begin(),
fPeaks.end(), [](
const TGauss* a,
const TGauss* b) { return a->Centroid() < b->Centroid(); });
975 std::cout << __PRETTY_FUNCTION__ <<
": found " <<
fData->GetN() <<
" peaks";
976 Double_t* x =
fData->GetX();
977 Double_t* y =
fData->GetY();
978 for(
int i = 0; i <
fData->GetN(); ++i) {
979 std::cout <<
"; " << x[i] <<
" - " << y[i];
981 std::cout << std::endl;
988 std::cout <<
DCYAN <<
"Adding map (double->tuple) with " << map.size() <<
" data points, fData = " <<
fData << std::endl;
990 if(
fData ==
nullptr) {
991 fData =
new TGraphErrors(map.size());
993 fData->Set(map.size());
995 fData->SetLineColor(2);
996 fData->SetMarkerColor(2);
998 for(
auto iter = map.begin(); iter != map.end();) {
1000 auto peakPos = iter->first;
1001 auto energy = std::get<0>(iter->second);
1002 fData->SetPoint(i, peakPos, energy);
1004 std::cout <<
"Using peak with position " << peakPos <<
", energy " << energy << std::endl;
1010 std::cout <<
"Accepted " << map.size() <<
" peaks" << std::endl;
1018 std::cout <<
DCYAN <<
"Adding map (TGauss*->tuple) with " << map.size() <<
" data points, fData = " <<
fData << std::endl;
1020 if(
fData ==
nullptr) {
1021 fData =
new TGraphErrors(map.size());
1023 fData->Set(map.size());
1025 fData->SetLineColor(2);
1026 fData->SetMarkerColor(2);
1027 if(
fFwhm ==
nullptr) {
1028 fFwhm =
new TGraphErrors(map.size());
1030 fFwhm->Set(map.size());
1032 fFwhm->SetLineColor(4);
1033 fFwhm->SetMarkerColor(4);
1035 for(
auto iter = map.begin(); iter != map.end();) {
1037 auto peakPos = iter->first->Centroid();
1038 auto peakPosErr = iter->first->CentroidErr();
1039 auto peakArea = iter->first->Area();
1040 auto peakAreaErr = iter->first->AreaErr();
1041 auto fwhm = iter->first->FWHM();
1042 auto fwhmErr = iter->first->FWHMErr();
1043 auto energy = std::get<0>(iter->second);
1044 auto energyErr = std::get<1>(iter->second);
1046 if(!
Good(iter->first)) {
1048 std::cout <<
"Dropping peak with position " << peakPos <<
" +- " << peakPosErr <<
", area " << peakArea <<
" +- " << peakAreaErr <<
", energy " << energy << std::endl;
1050 iter = map.erase(iter);
1052 std::cout <<
"Erasing peak returned iterator " << std::distance(map.begin(), iter) << std::endl;
1055 fData->SetPoint(i, peakPos, energy);
1056 fData->SetPointError(i, peakPosErr, energyErr);
1057 fFwhm->SetPoint(i, peakPos, fwhm);
1058 fFwhm->SetPointError(i, peakPosErr, fwhmErr);
1060 std::cout <<
"Using peak with position " << peakPos <<
" +- " << peakPosErr <<
", area " << peakArea <<
" +- " << peakAreaErr <<
", energy " << energy << std::endl;
1067 std::cout <<
"Accepted " << map.size() <<
" peaks" << std::endl;
1070 fData->Set(map.size());
1071 fFwhm->Set(map.size());
1075 TList* functions =
fProjection->GetListOfFunctions();
1077 std::cout << functions->GetEntries() <<
" functions in projection " <<
fProjection->GetName() << std::endl;
1078 for(
auto* obj : *functions) {
1079 std::cout << obj->GetName() <<
"/" << obj->GetTitle() <<
" - " << obj->ClassName() << std::endl;
1082 auto* polym =
static_cast<TPolyMarker*
>(functions->FindObject(
"TPolyMarker"));
1083 if(polym !=
nullptr) {
1084 double* oldX = polym->GetX();
1085 double* oldY = polym->GetY();
1086 int size = polym->GetN();
1087 std::vector<double> newX;
1088 std::vector<double> newY;
1089 std::vector<double> unusedX;
1090 std::vector<double> unusedY;
1091 for(i = 0; i < size; ++i) {
1093 for(
auto point : map) {
1095 newX.push_back(oldX[i]);
1096 newY.push_back(oldY[i]);
1102 unusedX.push_back(oldX[i]);
1103 unusedY.push_back(oldY[i]);
1106 polym->SetPolyMarker(newX.size(), newX.data(), newY.data());
1107 auto* unusedMarkers =
new TPolyMarker(unusedX.size(), unusedX.data(), unusedY.data());
1108 unusedMarkers->SetMarkerStyle(23);
1109 unusedMarkers->SetMarkerColor(16);
1110 functions->Add(unusedMarkers);
1112 std::cout <<
fProjection->GetTitle() <<
": " << size <<
" peaks founds total, " << polym->GetN() <<
" used, and " << unusedMarkers->GetN() <<
" unused" << std::endl;
1114 std::cout <<
"Used: ";
1115 for(
size_t m = 0; m < newX.size(); ++m) { std::cout << newX[m] <<
" - " << newY[m] <<
";"; }
1116 std::cout << std::endl;
1117 std::cout <<
"Unused: ";
1118 for(
size_t m = 0; m < unusedX.size(); ++m) { std::cout << unusedX[m] <<
" - " << unusedY[m] <<
";"; }
1119 std::cout << std::endl;
1122 std::cout << functions->GetEntries() <<
" functions in projection " <<
fProjection->GetTitle() << std::endl;
1123 for(
auto* obj : *functions) {
1124 std::cout << obj->GetName() <<
"/" << obj->GetTitle() <<
" - " << obj->ClassName() << std::endl;
1131 TIter iter(functions);
1132 TObject* item =
nullptr;
1133 while((item = iter.Next()) !=
nullptr) {
1134 if(item->IsA() == TF1::Class() || item->IsA() == TGauss::Class()) {
1135 double centroid = 0.;
1136 if(item->IsA() == TF1::Class()) {
1137 centroid =
static_cast<TF1*
>(item)->GetParameter(1);
1139 centroid =
static_cast<TGauss*
>(item)->Centroid();
1142 for(
auto point : map) {
1151 if(item->IsA() == TF1::Class()) {
1152 static_cast<TF1*
>(item)->SetLineColor(kGray);
1166 std::cout <<
DCYAN << __PRETTY_FUNCTION__ <<
": index " << index <<
", channel " << channel << std::endl;
1167 for(
size_t i = 0; i <
fPeaks.size() && i <
fFits.size(); ++i) {
1168 std::cout << i <<
": " <<
fPeaks[i]->Centroid() <<
" +- " <<
fPeaks[i]->CentroidErr() <<
" - " <<
fFits[i]->GetFitFunction()->GetParameter(
"centroid_0") << std::endl;
1172 if(index >=
fPeaks.size()) {
1173 std::cerr <<
"Trying to replace peak at index " << index <<
" but there are only " <<
fPeaks.size() <<
" peaks!" << std::endl;
1181 double low = channel - range;
1182 double high = channel + range;
1183 if(
fPeaks.at(index)->Centroid() < channel) {
1184 low = (
fPeaks.at(index)->Centroid() + channel) / 2.;
1186 high = (
fPeaks.at(index)->Centroid() + channel) / 2.;
1190 auto* peak =
new TGauss(channel);
1198 if(peak->Area() > 0) {
1199 if(
Good(peak, low, high)) {
1201 std::cout << index <<
". peak/fit out of " <<
fPeaks.size() <<
"/" <<
fFits.size() <<
" peaks/fits: " << std::flush <<
fPeaks.at(index)->Centroid() <<
"/" <<
fFits.at(index)->GetFitFunction()->GetParameter(
"centroid_0") << std::endl;
1202 std::cout <<
"Deleting " << index <<
". peak " <<
fPeaks.at(index) << std::flush;
1204 peak->SetLineColor(
fPeaks.at(index)->GetLineColor());
1208 std::cout <<
" and setting it to " <<
fPeaks.at(index) << std::endl;
1211 std::cout <<
"Deleting " << index <<
". fit " <<
fFits.at(index) << std::flush;
1213 pf->GetFitFunction()->SetLineColor(
fFits.at(index)->GetFitFunction()->GetLineColor());
1214 delete fFits.at(index);
1217 std::cout <<
" and setting it to " <<
fFits.at(index) << std::endl;
1220 fData->SetPoint(index, peak->Centroid(),
fData->GetPointY(index));
1221 fData->SetPointError(index, peak->CentroidErr(),
fData->GetErrorY(index));
1222 fFwhm->SetPoint(index, peak->Centroid(), peak->FWHM());
1223 fFwhm->SetPointError(index, peak->CentroidErr(), peak->FWHMErr());
1225 std::cout <<
"Fitted peak " << low <<
" - " << high <<
" -> centroid " << peak->Centroid() <<
", area " << peak->Area() << std::endl;
1229 std::cout <<
"We're ignoring bad fits, and this one has position " << peak->Centroid() <<
" +- " << peak->CentroidErr() <<
", area " << peak->Area() <<
" +- " << peak->AreaErr() << std::endl;
1233 std::cout <<
"Ignoring peak at " << peak->Centroid() <<
" with negative area " << peak->Area() << std::endl;
1240 std::cout <<
DCYAN << __PRETTY_FUNCTION__ <<
": oldPoint " << oldPoint << std::endl;
1246 auto* erasedFit =
fFits.at(oldPoint);
1249 fData->RemovePoint(oldPoint);
1264 for(
size_t i = 0; i <
fPeaks.size() && i <
fFits.size(); ++i) {
1267 fPeaks[i]->SetLineColor(kRed + 2);
1268 fFits[i]->GetFitFunction()->SetLineColor(kRed);
1271 fPeaks[i]->SetLineColor(kBlue + 2);
1272 fFits[i]->GetFitFunction()->SetLineColor(kBlue);
1277 for(
size_t i = 0; i <
fBadFits.size(); ++i) {
1280 fBadFits[i]->GetFitFunction()->SetLineColor(kGray);
1283 fBadFits[i]->GetFitFunction()->SetLineColor(kGray + 2);
1293 gVirtualX->Update();
1302 std::cout <<
" is null";
1304 std::cout << std::endl;
1306 std::cout <<
"Data " <<
fData;
1307 if(
fData !=
nullptr) {
1308 std::cout <<
" = " <<
fData->GetName() <<
"/" <<
fData->GetTitle();
1310 std::cout <<
" is null";
1312 std::cout << std::endl;
1314 std::cout <<
"Fwhm " <<
fFwhm;
1315 if(
fFwhm !=
nullptr) {
1316 std::cout <<
" = " <<
fFwhm->GetName() <<
"/" <<
fFwhm->GetTitle();
1318 std::cout <<
" is null";
1320 std::cout << std::endl;
1322 std::cout <<
fFits.size() <<
" good fits:";
1323 for(
size_t i = 0; i <
fFits.size(); ++i) {
1324 std::cout <<
" " << std::setw(2) << i <<
" - " << std::setw(8) <<
fFits.at(i)->GetFitFunction()->GetParameter(
"centroid_0");
1326 std::cout << std::endl;
1328 std::cout <<
fBadFits.size() <<
" bad fits:";
1329 for(
size_t i = 0; i <
fBadFits.size(); ++i) {
1330 std::cout <<
" " << std::setw(2) << i <<
" - " << std::setw(8) <<
fBadFits.at(i)->GetFitFunction()->GetParameter(
"centroid_0");
1332 std::cout << std::endl;
1334 std::cout <<
fPeaks.size() <<
" peaks:";
1335 for(
size_t i = 0; i <
fPeaks.size(); ++i) {
1336 std::cout <<
" " << std::setw(2) << i <<
" - " << std::setw(8) <<
fPeaks.at(i)->Centroid();
1338 std::cout << std::endl;
1343 std::cout <<
this <<
": TSourceTab " <<
fSourceName <<
" projection canvas:" << std::endl;
1346 std::cout << obj <<
": " << obj->ClassName() <<
" called " << obj->GetName() << std::endl;
1349 std::cout <<
"--------------------" << std::endl;
1354 std::cout <<
"TSourceTab frame:" << std::endl;
1356 std::cout <<
"TSourceTab canvas:" << std::endl;
1358 std::cout <<
"TSourceTab status bar:" << std::endl;
1363TChannelTab::TChannelTab(
TSourceCalibration* sourceCal, std::vector<TNucleus*> nuclei, std::vector<GH1D*> projections, std::string name, TGCompositeFrame* frame, std::vector<std::vector<std::tuple<double, double, double, double>>> sourceEnergies, TGHProgressBar* progressBar)
1364 : fChannelFrame(frame), fSourceTab(new TGTab(frame,
TSourceCalibration::PanelWidth(),
TSourceCalibration::PanelHeight() + 2 *
TSourceCalibration::StatusbarHeight())), fCanvasTab(new TGTab(frame,
TSourceCalibration::PanelWidth(),
TSourceCalibration::PanelHeight() + 2 *
TSourceCalibration::StatusbarHeight())), fProgressBar(progressBar), fSourceCalibration(sourceCal), fNuclei(std::move(nuclei)), fProjections(std::move(projections)), fName(std::move(name)), fSourceEnergies(std::move(sourceEnergies))
1367 std::cout <<
DYELLOW <<
"========================================" << std::endl;
1368 std::cout << __PRETTY_FUNCTION__ << std::endl
1369 <<
" name = " <<
fName <<
", fData = " <<
fData << std::endl;
1370 std::cout <<
"========================================" << std::endl;
1376 std::cout <<
DYELLOW <<
"----------------------------------------" << std::endl;
1377 std::cout << __PRETTY_FUNCTION__ << std::endl
1378 <<
" channel " <<
fName <<
" done" << std::endl;
1379 std::cout <<
"----------------------------------------" << std::endl;
1414 for(
size_t source = 0; source <
fNuclei.size(); ++source) {
1419 if(*iter ==
nullptr) {
1426 fChannelFrame->AddFrame(
fSourceTab,
new TGLayoutHints(kLHintsLeft | kLHintsTop | kLHintsExpandX | kLHintsExpandY, 2, 2, 2, 2));
1433 std::array<int, 3> parts = {25, 35, 40};
1439 fFwhmFrame->AddFrame(
fFwhmCanvas,
new TGLayoutHints(kLHintsTop | kLHintsExpandX | kLHintsExpandY, 2, 2, 2, 2));
1445 fInitFrame->AddFrame(
fInitCanvas,
new TGLayoutHints(kLHintsTop | kLHintsExpandX | kLHintsExpandY, 2, 2, 2, 2));
1447 fChannelFrame->AddFrame(
fCanvasTab,
new TGLayoutHints(kLHintsRight | kLHintsTop | kLHintsExpandX | kLHintsExpandY, 2, 2, 2, 2));
1460 fLegend =
new TLegend(0.8, 0.3, 0.95, 0.3 +
static_cast<double>(
fNuclei.size()) * 0.05);
1463 fResidualPad =
new TPad(Form(
"res_%s",
fName.c_str()), Form(
"residual for %s",
fName.c_str()), 0.0, 0., 0.2, 1.);
1489 std::cout <<
DYELLOW <<
"Creating source tab " << source <<
", using fSourceCalibration " <<
fSourceCalibration << std::endl;
1491 TGCompositeFrame* tmpTab =
nullptr;
1499 std::cout <<
DYELLOW <<
"Creating source tab " << source <<
" = " <<
fProjections[source]->GetName() <<
", tab name " << tmpTab->GetName() << std::endl;
1511 std::cout <<
DYELLOW <<
"Skipping projection of source " << source <<
" = " <<
fProjections[source]->GetName() <<
", only " <<
fProjections[source]->GetEntries() <<
" entries" << std::endl;
1515 std::cout << __PRETTY_FUNCTION__ <<
" source " << source <<
" done" << std::endl;
1522 fSourceTab->Connect(
"Selected(Int_t)",
"TChannelTab",
this,
"SelectedTab(Int_t)");
1524 source->MakeConnections();
1526 fCalibrationCanvas->GetCanvas()->Connect(
"ProcessedEvent(Int_t,Int_t,Int_t,TObject*)",
"TChannelTab",
this,
"CalibrationStatus(Int_t,Int_t,Int_t,TObject*)");
1527 fCalibrationCanvas->Connect(
"ProcessedEvent(Event_t*)",
"TChannelTab",
this,
"SelectCanvas(Event_t*)");
1528 if(
fData !=
nullptr) {
1530 std::cout <<
DYELLOW << __PRETTY_FUNCTION__ <<
": connecting fData " <<
fData <<
":" << std::endl;
1533 fData->Connect(
"RemovePoint(Int_t, Int_t)",
"TChannelTab",
this,
"RemovePoint(Int_t, Int_t)");
1535 std::cerr <<
DRED <<
"Failed to create connections for the data graph fData since it hasn't been created yet!" << std::endl;
1542 fSourceTab->Disconnect(
"Selected(Int_t)",
this,
"SelectedTab(Int_t)");
1544 source->Disconnect();
1546 fCalibrationCanvas->GetCanvas()->Disconnect(
"ProcessedEvent(Int_t,Int_t,Int_t,TObject*)",
this,
"CalibrationStatus(Int_t,Int_t,Int_t,TObject*)");
1547 fData->Disconnect(
"RemovePoint(Int_t, Int_t)",
this,
"RemovePoint(Int_t, Int_t)");
1576 if(event->fType == kEnterNotify) {
1578 std::cout <<
"Entered channel tab => changing gPad from " << gPad->GetName();
1582 std::cout <<
" to " << gPad->GetName() << std::endl;
1590 std::cout <<
DCYAN << __PRETTY_FUNCTION__ <<
": oldGraph " << oldGraph <<
", oldPoint " << oldPoint << std::endl;
1592 if(0 <= oldGraph && oldGraph <
static_cast<int>(
fSources.size())) {
1594 fSources[oldGraph]->RemovePoint(oldPoint);
1597 std::cout <<
"Can't remove negative point " << oldPoint <<
" from graph " << oldGraph << std::endl;
1599 std::cout <<
"Graph the point was removed from was " << oldGraph <<
", but we only have " <<
fSources.size() <<
" source tabs?" << std::endl;
1618 if(event == kKeyPress) {
1622 if(canvas ==
nullptr) {
1626 auto* pad = canvas->GetSelectedPad();
1627 if(pad ==
nullptr) {
1635 fChannelStatusBar->SetText(Form(
"x = %f, y = %f", pad->AbsPixeltoX(px), pad->AbsPixeltoY(py)), 1);
1643 if(
fData ==
nullptr) {
1649 fData->SetName(Form(
"data%s",
fName.c_str()));
1651 std::cout <<
"set name of fData using " <<
fName.c_str() <<
": " <<
fData->GetName() << std::endl;
1652 std::cout <<
"fData " <<
fData <<
": " << (
fData !=
nullptr ?
fData->
GetN() : -2) <<
" data points after creation" << std::endl;
1653 std::cout <<
"Looping over " <<
fNuclei.size() <<
" sources, fSources.size() = " <<
fSources.size() << std::endl;
1655 for(
size_t source = 0; source <
fNuclei.size() && source <
fSources.size(); ++source) {
1665 std::cout <<
"fData " <<
fData <<
": " << (
fData !=
nullptr ?
fData->
GetN() : -1) <<
" data points after adding " <<
fNuclei.size() <<
" graphs" << std::endl;
1674 if(
fFwhm ==
nullptr) {
1680 fFwhm->SetName(Form(
"fwhm%s",
fName.c_str()));
1682 std::cout <<
"set name of fFwhm using " <<
fName.c_str() <<
": " <<
fFwhm->GetName() << std::endl;
1683 std::cout <<
"fFwhm " <<
fFwhm <<
": " << (
fFwhm !=
nullptr ?
fFwhm->
GetN() : -2) <<
" data points after creation" << std::endl;
1684 std::cout <<
"Looping over " <<
fNuclei.size() <<
" sources, fSources.size() = " <<
fSources.size() << std::endl;
1686 for(
size_t source = 0; source <
fNuclei.size() && source <
fSources.size(); ++source) {
1687 if(
fSources[source]->Fwhm() !=
nullptr &&
fSources[source]->Fwhm()->GetN() > 0) {
1696 std::cout <<
"fFwhm " <<
fFwhm <<
": " << (
fFwhm !=
nullptr ?
fFwhm->
GetN() : -1) <<
" data points after adding " <<
fNuclei.size() <<
" graphs" << std::endl;
1712 TF1* calibration =
new TF1(
"fitfunction",
::Polynomial, 0., 10000., degree + 2);
1713 calibration->FixParameter(0, degree);
1716 if(
fData !=
nullptr) {
1717 std::cout <<
fData->
GetN() <<
" data points being fit, ";
1721 calibration->GetRange(min, max);
1722 std::cout <<
"range " << min <<
" - " << max << std::endl;
1725 TString text = Form(
"%.6f + %.6f*x", calibration->GetParameter(1), calibration->GetParameter(2));
1726 for(
int i = 2; i <= degree; ++i) {
1727 text.Append(Form(
" + %.6f*x^%d", calibration->GetParameter(i + 1), i));
1747 fChi2Label =
new TPaveText(left, bottom, right, top);
1756 fChi2Label->AddText(Form(
"#chi^{2}/NDF = %f", calibration->GetChisquare() / calibration->GetNDF()));
1760 std::cout <<
"fChi2Label set to:" << std::endl;
1762 std::cout <<
"Text size " <<
fChi2Label->GetTextSize() << std::endl;
1765 fInfoLabel =
new TPaveText(0, 0.95, 1., 1.,
"NDCNB");
1790 calibration->GetRange(min, max);
1791 std::cout <<
DYELLOW <<
"calibration has range " << min <<
" - " << max;
1794 std::cout <<
", fit function has range " << min <<
" - " << max;
1796 std::cout << std::endl;
1811 if(
fData ==
nullptr) {
1812 std::cout <<
"No longer have a data for channel " <<
Name() <<
"?" << std::endl;
1817 std::cout <<
"No longer have a total residual graph for channel " <<
Name() <<
". Maybe removed all points? Total graph has " <<
fData->
TotalGraph()->GetN() <<
" points." << std::endl;
1822 std::cout <<
"Recursively removed all data points for channel " <<
Name() << std::endl;
1830 if(std::abs(*maxElement) < maxResidual) {
1852 std::stringstream str;
1853 str << std::hex <<
fName;
1858 if(calibration ==
nullptr) {
1859 std::cout <<
"Failed to find calibration in fData" << std::endl;
1863 std::vector<Float_t> parameters;
1864 for(
int i = 0; i <= calibration->GetParameter(0); ++i) {
1865 parameters.push_back(
static_cast<Float_t
>(calibration->GetParameter(i + 1)));
1868 if(channel ==
nullptr) {
1869 std::cerr <<
"Failed to get channel for address " <<
hex(address, 4) << std::endl;
1879 for(
int i = 0; i <
fData->
GetN(); ++i) {
1893 std::cout <<
DYELLOW <<
"Rough calibration in source tab:" << std::endl;
1896 source->InitialCalibration(force);
1905 std::cout <<
"Cloned data " <<
fData->GetName() <<
" to " <<
fInit->GetName() <<
":" << std::endl;
1908 auto* oldPad = gPad;
1920 fCalLabel =
new TPaveText(left, bottom, right, top);
1927 std::stringstream str;
1931 str <<
"Unknown fit function with " <<
fInit->
FitFunction()->GetNpar() <<
" parameters";
1934 std::cout <<
"Created label text \"" << str.str() <<
"\"" << std::endl;
1949 for(
int tab = 0; tab <
fSourceTab->GetNumberOfTabs(); ++tab) {
1950 std::cout <<
"Tab " << tab <<
" = " <<
fSourceTab->GetTabTab(tab) <<
" = " <<
fSourceTab->GetTabTab(tab)->GetText()->GetString() << (
fSourceTab->GetTabTab(tab)->IsActive() ?
" is active" :
" is inactive") << (
fSourceTab->GetTabTab(tab)->IsEnabled() ?
" is enabled" :
" is not enabled") << std::endl;
1964 std::cout <<
DYELLOW <<
"Finding calibrated peaks in all source tabs" << std::endl;
1968 std::cout <<
DYELLOW <<
"Finding calibrated peaks in source tab " << source->SourceName() << std::endl;
1975 std::cout <<
DYELLOW <<
"Done finding calibrated peaks in all source tabs" << std::endl;
1994 fData->Write(Form(
"calGraph_%s",
fName.c_str()), TObject::kOverwrite);
1995 fFwhm->Write(Form(
"fwhm_%s",
fName.c_str()), TObject::kOverwrite);
2003 TH1* hist1 =
nullptr;
2004 for(
const auto&& obj : *(gPad->GetListOfPrimitives())) {
2005 if(obj->InheritsFrom(TGraph::Class())) {
2006 hist1 =
static_cast<TGraph*
>(obj)->GetHistogram();
2010 if(hist1 ==
nullptr) {
2011 std::cout <<
"ZoomX - Failed to find histogram for pad " << gPad->GetName() << std::endl;
2017 std::string padName = gPad->GetName();
2018 std::string baseName = padName.substr(0, 3);
2019 std::string channelName = padName.substr(4);
2022 std::string newName;
2023 if(baseName ==
"cal") {
2024 newName =
"res_" + channelName;
2025 }
else if(baseName ==
"res") {
2026 newName =
"cal_" + channelName;
2028 std::cout <<
"Unknown combination of pad " << gPad->GetName() <<
" and histogram " << hist1->GetName() << std::endl;
2031 auto* newObj = gPad->GetCanvas()->FindObject(newName.c_str());
2032 if(newObj ==
nullptr) {
2033 std::cout <<
"Failed to find " << newName << std::endl;
2037 if(newObj->IsA() != TPad::Class()) {
2038 std::cout << newObj <<
" = " << newObj->GetName() <<
", " << newObj->GetTitle() <<
" is a " << newObj->ClassName() <<
" not a TPad" << std::endl;
2041 auto* pad2 =
static_cast<TPad*
>(newObj);
2042 if(pad2 ==
nullptr) {
2043 std::cout <<
"Failed to find partner pad " << newName << std::endl;
2047 TH1* hist2 =
nullptr;
2048 for(
const auto&& obj : *(pad2->GetListOfPrimitives())) {
2049 if(obj->InheritsFrom(TGraph::Class())) {
2050 hist2 =
static_cast<TGraph*
>(obj)->GetHistogram();
2054 if(hist2 ==
nullptr) {
2055 std::cout <<
"ZoomX - Failed to find histogram for partner pad " << newName << std::endl;
2060 TAxis* axis1 = hist1->GetXaxis();
2061 Int_t binmin = axis1->GetFirst();
2062 Int_t binmax = axis1->GetLast();
2063 Double_t xmin = axis1->GetBinLowEdge(binmin);
2064 Double_t xmax = axis1->GetBinLowEdge(binmax);
2065 TAxis* axis2 = hist2->GetXaxis();
2066 Int_t newmin = axis2->FindBin(xmin);
2067 Int_t newmax = axis2->FindBin(xmax);
2068 axis2->SetRange(newmin, newmax);
2077 TH1* hist1 =
nullptr;
2078 for(
const auto&& obj : *(gPad->GetListOfPrimitives())) {
2079 if(obj->InheritsFrom(TGraph::Class())) {
2080 hist1 =
static_cast<TGraph*
>(obj)->GetHistogram();
2084 if(hist1 ==
nullptr) {
2085 std::cout <<
"ZoomY - Failed to find histogram for pad " << gPad->GetName() << std::endl;
2091 std::string padName = gPad->GetName();
2092 std::string baseName = padName.substr(0, 3);
2093 std::string channelName = padName.substr(4);
2096 std::string newName;
2097 if(baseName ==
"cal") {
2098 newName =
"res_" + channelName;
2099 }
else if(baseName ==
"res") {
2100 newName =
"cal_" + channelName;
2102 std::cout <<
"Unknown combination of pad " << gPad->GetName() <<
" and histogram " << hist1->GetName() << std::endl;
2105 auto* newObj = gPad->GetCanvas()->FindObject(newName.c_str());
2106 if(newObj ==
nullptr) {
2107 std::cout <<
"Failed to find " << newName << std::endl;
2111 if(newObj->IsA() != TPad::Class()) {
2112 std::cout << newObj <<
" = " << newObj->GetName() <<
", " << newObj->GetTitle() <<
" is a " << newObj->ClassName() <<
" not a TPad" << std::endl;
2115 auto* pad2 =
static_cast<TPad*
>(newObj);
2116 if(pad2 ==
nullptr) {
2117 std::cout <<
"Failed to find partner pad " << newName << std::endl;
2121 TH1* hist2 =
nullptr;
2122 for(
const auto&& obj : *(pad2->GetListOfPrimitives())) {
2123 if(obj->InheritsFrom(TGraph::Class())) {
2124 hist2 =
static_cast<TGraph*
>(obj)->GetHistogram();
2128 if(hist2 ==
nullptr) {
2129 std::cout <<
"ZoomY - Failed to find histogram for partner pad " << newName << std::endl;
2134 hist2->SetMinimum(hist1->GetMinimum());
2135 hist2->SetMaximum(hist1->GetMaximum());
2138 TLine* resLine =
nullptr;
2139 for(
const auto&& obj : *(gPad->GetListOfPrimitives())) {
2140 if(obj->IsA() == TLine::Class()) {
2141 if(resLine !=
nullptr) { std::cout <<
"ZoomY found residual line, old was " << resLine << std::endl; }
2142 resLine =
static_cast<TLine*
>(obj);
2145 for(
const auto&& obj : *(pad2->GetListOfPrimitives())) {
2146 if(obj->IsA() == TLine::Class()) {
2147 if(resLine !=
nullptr) { std::cout <<
"ZoomY found residual line, old was " << resLine << std::endl; }
2148 resLine =
static_cast<TLine*
>(obj);
2153 if(resLine !=
nullptr) {
2154 resLine->SetY1(hist1->GetMinimum());
2155 resLine->SetY2(hist1->GetMaximum());
2164 std::cout <<
"----------------------------------------" << std::endl;
2165 std::cout <<
this <<
": TChannelTab " <<
Name() <<
" calibration canvas:" << std::endl;
2170 std::cout <<
"TChannelTab fwhm canvas:" << std::endl;
2172 for(
auto* obj : *(
fFwhmCanvas->GetCanvas()->GetListOfPrimitives())) {
2176 sourceTab->PrintCanvases();
2178 std::cout <<
"----------------------------------------" << std::endl;
2183 std::cout <<
"TChannelTab frame:" << std::endl;
2185 std::cout <<
"TChannelTab canvas:" << std::endl;
2187 std::cout <<
"TChannelTab status bar:" << std::endl;
2190 sourceTab->PrintLayout();
2213 : TGMainFrame(nullptr, 2 * fPanelWidth, fPanelHeight + 2 * fStatusbarHeight), fDefaultSigma(sigma), fThreshold(threshold), fDefaultDegree(degree)
2215 TH1::AddDirectory(
false);
2218 va_start(args, count);
2219 for(
int i = 0; i < count; ++i) {
2220 fMatrices.push_back(va_arg(args, TH2*));
2222 std::cout <<
"Error, got nullptr as matrix input?" << std::endl;
2228 std::cout <<
DGREEN << __PRETTY_FUNCTION__ <<
": verbose level " <<
static_cast<std::underlying_type_t<EVerbosity>
>(
fVerboseLevel) << std::endl
2229 <<
"using " << count <<
"/" <<
fMatrices.size() <<
" matrices:" << std::endl;
2231 std::cout <<
mat << std::flush <<
" = " <<
mat->GetName() << std::endl;
2236 gErrorIgnoreLevel = kError;
2237 gPrintViaErrorHandler =
true;
2241 std::cout <<
"Starting redirect to " <<
fLogFile << std::endl;
2247 std::map<int, int> channelToIndex;
2248 for(
int bin = 1; bin <=
fMatrices[0]->GetNbinsX(); ++bin) {
2261 for(
size_t i = 1; i <
fMatrices.size(); ++i) {
2263 for(
int bin = 1; bin <=
fMatrices[i]->GetNbinsX(); ++bin) {
2266 if(channelToIndex.find(bin) == channelToIndex.end() || tmpBins != channelToIndex[bin]) {
2267 std::ostringstream error;
2268 error <<
"Mismatch in " << i <<
". matrix (" <<
fMatrices[i]->GetName() <<
"), bin " << bin <<
" is " << tmpBins <<
". filled bin, but should be " << (channelToIndex.find(bin) == channelToIndex.end() ?
"not filled" : Form(
"%d", channelToIndex[bin])) << std::endl;
2269 throw std::invalid_argument(error.str());
2271 if(strcmp(
fMatrices[0]->GetXaxis()->GetBinLabel(bin),
fMatrices[i]->GetXaxis()->GetBinLabel(bin)) != 0) {
2272 std::ostringstream error;
2273 error << i <<
". matrix, " << bin <<
". bin: label (" <<
fMatrices[i]->GetXaxis()->GetBinLabel(bin) <<
") doesn't match bin label of the first matrix (" <<
fMatrices[0]->GetXaxis()->GetBinLabel(bin) <<
")" << std::endl;
2274 throw std::invalid_argument(error.str());
2278 if(channelToIndex.find(bin) != channelToIndex.end()) {
2279 std::ostringstream error;
2280 error <<
"Mismatch in " << i <<
". matrix (" <<
fMatrices[i]->GetName() <<
"), bin " << bin <<
" is empty, but should be " << channelToIndex[bin] <<
". filled bin" << std::endl;
2281 throw std::invalid_argument(error.str());
2289 fOutput =
new TFile(
"TSourceCalibration.root",
"recreate");
2291 throw std::runtime_error(
"Unable to open output file \"TSourceCalibration.root\"!");
2299 SetWindowName(
"SourceCalibration");
2305 Resize(GetDefaultSize());
2325 auto* layoutManager =
new TGTableLayout(
this,
fMatrices.size() + 1, 2,
true, 5);
2327 SetLayoutManager(layoutManager);
2342 std::string name =
fMatrices[i]->GetName();
2343 std::transform(name.begin(), name.end(), name.begin(), ::tolower);
2345#if __cplusplus >= 201703L
2346 for(
const auto& file : std::filesystem::directory_iterator(path)) {
2347 if(file.is_regular_file() && file.path().extension().compare(
".sou") == 0) {
2348 fSourceBox.back()->AddEntry(file.path().stem().c_str(), index);
2350 if(std::strstr(
fMatrices[i]->GetName(), file.path().stem().c_str()) !=
nullptr) {
2355 std::cout <<
"matrix name " <<
fMatrices[i]->GetName() <<
" not matching " << file.path().stem().c_str() << std::endl;
2363 if(std::strstr(
fMatrices[i]->GetName(),
"22na") !=
nullptr) {
2369 if(std::strstr(
fMatrices[i]->GetName(),
"56co") !=
nullptr) {
2375 if(std::strstr(
fMatrices[i]->GetName(),
"60co") !=
nullptr) {
2381 if(std::strstr(
fMatrices[i]->GetName(),
"133ba") !=
nullptr) {
2387 if(std::strstr(
fMatrices[i]->GetName(),
"152eu") !=
nullptr) {
2393 if(std::strstr(
fMatrices[i]->GetName(),
"241am") !=
nullptr) {
2402 if(
fVerboseLevel >
EVerbosity::kSubroutines) { std::cout <<
"Attaching " << i <<
". label to 0, 1, " << i <<
", " << i + 1 <<
", and box to 1, 2, " << i <<
", " << i + 1 << std::endl; }
2403 AddFrame(
fMatrixNames.back(),
new TGTableLayoutHints(0, 1, i, i + 1, kLHintsRight | kLHintsCenterY));
2404 AddFrame(
fSourceBox.back(),
new TGTableLayoutHints(1, 2, i, i + 1, kLHintsLeft | kLHintsCenterY));
2411 AddFrame(
fStartButton,
new TGTableLayoutHints(0, 2, i, i + 1, kLHintsCenterX | kLHintsCenterY));
2421 box->Connect(
"Selected(Int_t, Int_t)",
"TSourceCalibration",
this,
"SetSource(Int_t, Int_t)");
2425 fStartButton->Connect(
"Clicked()",
"TSourceCalibration",
this,
"Start()");
2432 box->Disconnect(
"Selected(Int_t, Int_t)",
this,
"SetSource(Int_t, Int_t)");
2435 fStartButton->Disconnect(
"Clicked()",
this,
"Start()");
2441 RemoveFrame(element);
2465 auto* nucleus =
new TNucleus(
fSourceBox[index]->GetListBox()->GetEntry(entryId)->GetTitle());
2466 TIter iter(nucleus->GetTransitionList());
2468 while(
auto* transition =
static_cast<TTransition*
>(iter.Next())) {
2469 fSourceEnergy[index].emplace_back(transition->GetEnergy(), transition->GetEnergyUncertainty(), transition->GetIntensity(), transition->GetIntensityUncertainty());
2481 if(channelTab ==
nullptr) {
continue; }
2485 std::cout <<
"Closing window" << std::endl;
2487 std::cout <<
"all done" << std::endl;
2497 TTimer::SingleShot(
fWaitMs,
"TSourceCalibration",
this,
"HandleTimer()");
2505 for(
size_t i = 0; i <
fSource.size(); ++i) {
2507 std::cerr <<
"Source " << i <<
" not set!" << std::endl;
2512 for(
size_t i = 0; i <
fSource.size(); ++i) {
2513 for(
size_t j = i + 1; j <
fSource.size(); ++j) {
2515 std::cerr <<
"Duplicate sources: " << i <<
" - " <<
fSource[i]->GetName() <<
" and " << j <<
" - " <<
fSource[j]->GetName() << std::endl;
2526 SetLayoutManager(
new TGVerticalLayout(
this));
2532 fProgressBar->ShowPosition(
true,
false,
"Creating source tabs: %.0f");
2534 AddFrame(
fProgressBar,
new TGLayoutHints(kLHintsCenterX | kLHintsCenterY | kLHintsExpandX | kLHintsExpandY, 0, 0, 0, 0));
2562 if(channelTab !=
nullptr) {
2571 SetLayoutManager(
new TGVerticalLayout(
this));
2577 std::vector<GH1D*> projections(
fMatrices.size());
2580 projections[index] =
new GH1D(matrix->ProjectionY(Form(
"%s_%s",
fSource[index]->GetName(), matrix->GetXaxis()->GetBinLabel(bin)), bin, bin));
2583 auto* frame =
fTab->AddTab(
fMatrices[0]->GetXaxis()->GetBinLabel(bin));
2616 AddFrame(
fTab,
new TGLayoutHints(kLHintsTop | kLHintsExpandX | kLHintsExpandY, 0, 0, 0, 0));
2688 AddFrame(
fBottomFrame,
new TGLayoutHints(kLHintsBottom | kLHintsExpandX, 2, 2, 2, 2));
2693 fProgressBar->ShowPosition(
true,
false,
"Finding peaks for tab #%.0f");
2695 if(channelTab !=
nullptr) {
2697 for(
int i = 0; i < 20; ++i) { std::cout << std::endl; }
2698 for(
int i = 0; i < 5; ++i) {
2699 std::cout <<
"================================================================================" << std::endl;
2701 for(
int i = 0; i < 20; ++i) { std::cout << std::endl; }
2703 channelTab->Initialize(
true);
2704 channelTab->FindAllCalibratedPeaks();
2705 channelTab->Calibrate();
2708 channelTab->PrintCanvases();
2719 fNavigationGroup->Connect(
"Clicked(Int_t)",
"TSourceCalibration",
this,
"Navigate(Int_t)");
2720 fFittingGroup->Connect(
"Clicked(Int_t)",
"TSourceCalibration",
this,
"Fitting(Int_t)");
2721 fTab->Connect(
"Selected(Int_t)",
"TSourceCalibration",
this,
"SelectedTab(Int_t)");
2724 if(channelTab !=
nullptr) {
2725 channelTab->MakeConnections();
2734 fFittingGroup->Disconnect(
"Clicked(Int_t)",
this,
"Fitting(Int_t)");
2735 fTab->Disconnect(
"Selected(Int_t)",
this,
"SelectedTab(Int_t)");
2737 if(channelTab !=
nullptr) {
2738 channelTab->Disconnect();
2748 int currentChannelId =
fTab->GetCurrent();
2750 int nofTabs =
fTab->GetNumberOfTabs();
2751 if(
fVerboseLevel >
EVerbosity::kBasicFlow) { std::cout <<
DGREEN << __PRETTY_FUNCTION__ <<
": id " <<
id <<
", channel tab id " << currentChannelId <<
", actual channel tab id " << actualChannelId <<
", # of tabs " << nofTabs << std::endl; }
2755 fTab->SetTab(currentChannelId - 1);
2760 if(currentChannelId < nofTabs - 1) {
2761 fTab->SetTab(currentChannelId + 1);
2763 fTab->SetTab(currentChannelId - 1);
2766 fTab->RemoveTab(currentChannelId);
2778 fTab->SetTab(currentChannelId + 1);
2792 int currentChannelId =
fTab->GetCurrent();
2794 int nofTabs =
fTab->GetNumberOfTabs();
2795 if(
fVerboseLevel >
EVerbosity::kBasicFlow) { std::cout <<
DGREEN << __PRETTY_FUNCTION__ <<
": id " <<
id <<
", channel tab id " << currentChannelId <<
", actual channel tab id " << actualChannelId <<
", # of tabs " << nofTabs << std::endl; }
2824 if(
id < 0) {
return; }
2831 if(
id >=
fTab->GetNumberOfTabs() - 1) {
2840 std::cout <<
"Failed to get fChannelTab[" <<
fActiveBins[id] - 1 <<
" = fActiveBins[" <<
id <<
"]-1]" <<
RESET_COLOR << std::endl;
2844 std::cout <<
"Failed to get fChannelTab[" <<
fActiveBins[id] - 1 <<
" = fActiveBins[" <<
id <<
"]-1]->SelectedSourceTab()" <<
RESET_COLOR << std::endl;
2848 std::cout <<
"Failed to get fChannelTab[" <<
fActiveBins[id] - 1 <<
" = fActiveBins[" <<
id <<
"]-1]->SelectedSourceTab()->ProjectionCanvas()" <<
RESET_COLOR << std::endl;
2852 std::cout <<
"Failed to get fChannelTab[" <<
fActiveBins[id] - 1 <<
" = fActiveBins[" <<
id <<
"]-1]->SelectedSourceTab()->ProjectionCanvas()->GetCanvas()" <<
RESET_COLOR << std::endl;
2866 int nofTabs =
fTab->GetNumberOfTabs();
2868 int maxChannel = nofTabs - 1;
2869 if(channelId >= 0) {
2870 minChannel = channelId;
2871 maxChannel = channelId;
2876 for(
int currentChannelId = maxChannel; currentChannelId >= minChannel; --currentChannelId) {
2878 if(
fVerboseLevel >
EVerbosity::kLoops) { std::cout << __PRETTY_FUNCTION__ <<
": currentChannelId " << currentChannelId <<
", actualChannelId " << actualChannelId <<
", fChannelTab.size() " <<
fChannelTab.size() <<
", fActualChannelId.size() " <<
fActualChannelId.size() <<
", nofTabs " << nofTabs << std::endl; }
2880 if(minChannel == maxChannel) {
2881 if(currentChannelId < nofTabs) {
2882 fTab->SetTab(currentChannelId + 1);
2885 fTab->SetTab(currentChannelId - 1);
2891 fTab->RemoveTab(currentChannelId);
2902 TTimer::SingleShot(
fWaitMs,
"TSourceCalibration",
this,
"HandleTimer()");
2911 auto* window =
CreateProgressbar(
"Finding current source peaks in channel #%.0f");
2920 window->CloseWindow();
2926 std::cout << __PRETTY_FUNCTION__ <<
": fChannelTab[" <<
fActiveBins[
fTab->GetCurrent()] <<
" = fActiveBins[" <<
fTab->GetCurrent() <<
"]] is a nullptr (fApplyToAll is " << (
fApplyToAll->IsDown() ?
"down" :
"up") <<
")!" << std::endl;
2938 std::cout << __PRETTY_FUNCTION__ <<
": fChannelTab[" <<
fActiveBins[
fTab->GetCurrent()] <<
" = fActiveBins[" <<
fTab->GetCurrent() <<
"]] is a nullptr!" << std::endl;
2953 std::cout << __PRETTY_FUNCTION__ <<
": fChannelTab[" << bin <<
"] is a nullptr!" << std::endl;
2957 window->CloseWindow();
2974 window->CloseWindow();
2979 std::cout << __PRETTY_FUNCTION__ <<
": fChannelTab[" <<
fActiveBins[
fTab->GetCurrent()] <<
" = fActiveBins[" <<
fTab->GetCurrent() <<
"]] is a nullptr (fApplyToAll is " << (
fApplyToAll->IsDown() ?
"down" :
"up") <<
")!" << std::endl;
2988 auto* window =
CreateProgressbar(
"Recursively removing peaks for channel #%.0f");
2997 window->CloseWindow();
3003 std::cout << __PRETTY_FUNCTION__ <<
": fChannelTab[" <<
fActiveBins[
fTab->GetCurrent()] <<
" = fActiveBins[" <<
fTab->GetCurrent() <<
"]] is a nullptr (fApplyToAll is " << (
fApplyToAll->IsDown() ?
"down" :
"up") <<
")!" << std::endl;
3012 if(channelTab ==
nullptr) {
continue; }
3013 channelTab->UpdateChannel();
3015 std::ostringstream fileName;
3017 fileName << source->GetName();
3032 window->AddFrame(
fProgressBar,
new TGLayoutHints(kLHintsCenterX | kLHintsCenterY | kLHintsExpandX | kLHintsExpandY, 0, 0, 0, 0));
3033 window->CenterOnParent();
3034 window->MapSubwindows();
3035 window->MapWindow();
3036 window->Resize(window->GetDefaultSize());
3049 if(
fTab !=
nullptr) {
fTab->Print(); }
3050 std::cout <<
"TSourceCalibration all " <<
fChannelTab.size() <<
" channel tabs:" << std::endl;
3052 if(channelTab !=
nullptr) { channelTab->PrintLayout(); }
3061 if(channelTab !=
nullptr) { channelTab->PrintCanvases(); }
std::string hex(T val, int width=-1)
void Print(Option_t *opt="") const override
void Clear(Option_t *opt="") override
void Draw(Option_t *opt="") override
void DrawResidual(Option_t *opt="", TLegend *legend=nullptr)
int GetN()
Returns GetN(), i.e. number of points of the total graph.
void SetMarkerColor(int index, Color_t color)
bool SetResidual(const bool &force=false)
TGraphErrors * TotalResidualGraph()
double GetMaximumY() const
Return maximum y-value.
void SetLineColor(int index, Color_t color)
double * GetY()
Returns an array of y-values of the total graph.
void Print(Option_t *opt="") const override
void Fit(TF1 *function, Option_t *opt="")
Fits the provided function to the total graph.
double GetMinimumY() const
Return minimum y-value.
double GetMinimumX() const
Return minimum x-value.
TGraphErrors * TotalGraph()
double GetMaximumX() const
Return maximum x-value.
int Add(TGraphErrors *, const std::string &label)
Add new graph to set, using the label when creating legends during plotting.
void DrawCalibration(Option_t *opt="", TLegend *legend=nullptr)
void Clear(Option_t *option="") override
Int_t RemovePoint(const Int_t &px, const Int_t &py)
double * GetX()
Returns an array of x-values of the total graph.
TF1 * FitFunction()
Gets the calibration from the total graph (might be nullptr!).
static void WriteCalFile(const std::string &outfilename="")
TGraph GetEnergyNonlinearity() const
static TChannel * GetChannel(unsigned int temp_address, bool warn=false)
void SetENGCoefficients(const std::vector< Float_t > &tmp, size_t range=0)
void DestroyEnergyNonlinearity()
void AddEnergyNonlinearityPoint(double x, double y)
static size_t GetNumberOfChannels()
void FindCalibratedPeaks()
TSourceCalibration * fSourceCalibration
the parent of this tab
std::vector< GH1D * > fProjections
vector of all projections
TGCompositeFrame * fChannelFrame
main frame of this tab
std::vector< TSourceTab * > fSources
tabs for all sources
TCalibrationGraphSet * fFwhm
combined fwhm from all sources
TGraphErrors * Data(int channelId) const
TGTab * fSourceTab
tab for sources
void SelectCanvas(Event_t *event)
void Write(TFile *output)
void FindAllCalibratedPeaks()
TRootEmbeddedCanvas * fInitCanvas
TChannelTab(TSourceCalibration *sourceCal, std::vector< TNucleus * > nuclei, std::vector< GH1D * > projections, std::string name, TGCompositeFrame *frame, std::vector< std::vector< std::tuple< double, double, double, double > > > sourceEnergies, TGHProgressBar *progressBar)
void CalibrationStatus(Int_t event, Int_t px, Int_t py, TObject *selected)
void Initialize(const bool &force)
void RemovePoint(Int_t oldGraph, Int_t oldPoint)
TGCompositeFrame * fCalibrationFrame
frame of tab with calibration
std::vector< std::vector< std::tuple< double, double, double, double > > > fSourceEnergies
vector with source energies and uncertainties
void CreateSourceTab(size_t source)
TGCompositeFrame * fFwhmFrame
frame of tab with fwhm
TCalibrationGraphSet * fInit
combined initial data from all sources
TRootEmbeddedCanvas * fFwhmCanvas
int fActiveSourceTab
id of the currently active source tab
std::string fName
name of this tab
std::vector< TNucleus * > fNuclei
the source nucleus
void SelectedTab(Int_t id)
TGStatusBar * fChannelStatusBar
void RecursiveRemove(const double &maxResidual)
TGTab * fCanvasTab
tab for canvases (calibration with residuals, and FWHM)
TGCompositeFrame * fInitFrame
frame of tab with initial calibration
void PrintCanvases() const
TGHProgressBar * fProgressBar
TRootEmbeddedCanvas * fCalibrationCanvas
TCalibrationGraphSet * fData
combined data from all sources
Double_t CentroidErr() const override
void Centroid(const Double_t ¢roid) override
static std::string & SourceDirectory()
void SetLineColor(Color_t color)
unsigned int fLineHeight
Height of text boxes and progress bar.
int fWaitMs
How many milliseconds we wait before we process the navigation input (to avoid double triggers?...
TGTextButton * fPreviousButton
TRedirect * fRedirect
redirect, created in constructor and destroyed in destructor if a log file name has been provided
static std::string LogFile()
static int fStatusbarHeight
Height of status bar (also extra height needed for tabs)
TGVerticalFrame * fRightFrame
TGTransientFrame * CreateProgressbar(const char *format)
static std::string fLogFile
name of log file, if empty no log file is written
static void FitRange(int val)
TSourceCalibration(double sigma, double threshold, int degree, int count...)
TGCheckButton * fWriteNonlinearities
TGNumberEntry * fMaxResidualEntry
void SelectedTab(Int_t id)
int fDefaultDegree
The default degree of the polynomial used for calibrating, can be changed later.
static EVerbosity VerboseLevel()
TGGroupFrame * fParameterFrame
std::vector< TGLabel * > fMatrixNames
TGTextButton * fFindSourcePeaksButton
TGTextButton * fCalibrateButton
static double MinIntensity()
TGTextButton * fAcceptAllButton
void AcceptChannel(const int &channelId=-1)
TGNumberEntry * fSigmaEntry
static int MaxIterations()
double fDefaultSigma
The default sigma used for the peak finding algorithm, can be changed later.
static int fMaxIterations
Maximum iterations over combinations in Match and SmartMatch.
TGTextButton * fFindAllPeaksButton
TGHProgressBar * fProgressBar
void PrintCanvases() const
TGHButtonGroup * fNavigationGroup
void SetSource(Int_t windowId, Int_t entryId)
static int StatusbarHeight()
std::vector< int > fActiveBins
TGTextButton * fDiscardButton
std::vector< TNucleus * > fSource
TGNumberEntry * fFitRangeEntry
TGLabel * fMaxResidualLabel
static bool fFast
Do we use the fast peak finding method on startup or not.
bool WriteNonlinearities()
std::vector< const char * > fChannelLabel
std::vector< TChannelTab * > fChannelTab
static bool fAcceptBadFits
Do we accept peaks where the fit was bad (position or area uncertainties too large or not numbers)
TGTextButton * fAcceptButton
static int fPanelWidth
Width of one panel.
static size_t fNumberOfThreads
Maximum number of threads to run while creating the channel tabs.
double fDefaultMaxResidual
The default maximum residual accepted when trying to iteratively find peaks.
static int fPanelHeight
Height of one panel.
TGTextButton * fRecursiveRemoveButton
std::vector< TH2 * > fMatrices
static bool fUseCalibratedPeaks
Do we use the initial calibration to find more peaks in the source spectra?
int fOldErrorLevel
Used to store old value of gErrorIgnoreLevel (set to kError for the scope of the class)
void BuildFirstInterface()
static int fDigitWidth
Number of digits used for parameter entries (if they are floating point)
TGHButtonGroup * fFittingGroup
TGTextButton * fWriteButton
std::vector< TGComboBox * > fSourceBox
std::vector< int > fActualChannelId
int fNofBins
Number of filled bins in first matrix.
TGTextButton * fFindChannelPeaksButton
TGNumberEntry * fDegreeEntry
void MakeSecondConnections()
static double fMinIntensity
Minimum intensity of source peaks to be considered when trying to find them in the spectrum.
void DeleteElement(TGFrame *element)
static int fParameterHeight
Height of the frame for the parameters.
void MakeFirstConnections()
std::vector< std::vector< std::tuple< double, double, double, double > > > fSourceEnergy
vector to hold source energy, energy uncertainty, intensity, and intensity uncertainty
static bool AcceptBadFits()
static std::vector< int > fBadBins
Bins of the 2D matrix to be ignored even if there are enough counts in them.
static int fSourceboxWidth
Width of the box to select which source each histogram is from.
TGTextButton * fStartButton
TGCheckButton * fApplyToAll
TGTextButton * fNextButton
TGVerticalFrame * fLeftFrame
static EVerbosity fVerboseLevel
Changes verbosity from kQuiet to kAll.
TGGroupFrame * fSettingsFrame
TGHorizontalFrame * fBottomFrame
void BuildSecondInterface()
static int fFitRange
range in sigma used for fitting peaks (peak position - range to peas position + range)
void InitialCalibration(const bool &force)
void Status(const char *status, int position)
void ReplacePeak(const size_t &index, const double &channel)
TRootEmbeddedCanvas * fProjectionCanvas
std::vector< std::pair< double, double > > fRegions
void RemovePoint(Int_t oldPoint)
TChannelTab * fChannelTab
void ProjectionStatus(Event_t *event)
TSourceTab(TSourceCalibration *sourceCal, TChannelTab *channel, TGCompositeFrame *frame, GH1D *projection, const char *sourceName, std::vector< std::tuple< double, double, double, double > > sourceEnergy)
TGCompositeFrame * fSourceFrame
std::vector< TPeakFitter * > fBadFits
all bad fits (centroid err > 10%, area err > 100%, or either of them not a number at all)
std::vector< std::tuple< double, double, double, double > > fSourceEnergy
gamma rays from the source, with their energies, uncertainties in the energies, intensities,...
std::vector< TPeakFitter * > fFits
all good fits
void Add(std::map< double, std::tuple< double, double, double, double > > map)
TSourceCalibration * fSourceCalibration
std::vector< TGauss * > fPeaks
all peaks that have been fitted and are good
void FindCalibratedPeaks(const TF1 *calibration)
TGStatusBar * fSourceStatusBar
void PrintCanvases() const
std::map< TGauss *, std::tuple< double, double, double, double > > SmartMatch(std::vector< TGauss * > peaks, std::vector< std::tuple< double, double, double, double > > sources, TSourceTab *sourceTab)
std::map< TGauss *, std::tuple< double, double, double, double > > Match(std::vector< TGauss * > peaks, std::vector< std::tuple< double, double, double, double > > sources, TSourceTab *sourceTab)
bool FilledBin(TH2 *matrix, const int &bin)
std::map< double, std::tuple< double, double, double, double > > RoughCal(std::vector< double > peaks, std::vector< std::tuple< double, double, double, double > > sources, TSourceTab *sourceTab)
double Polynomial(double *x, double *par)