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 = peaks.size();
59 if(sources.size() > maxSize) { maxSize = sources.size(); }
64 TLinearFitter fitter(1,
"1 ++ x");
67 std::vector<double> sourceValues(sources.size());
68 std::map<double, double> tmpMap;
70 for(
size_t num_data_points = std::min(peaks.size(), sourceValues.size()); num_data_points > 0; num_data_points--) {
72 double best_chi2 = DBL_MAX;
74 for(
auto peak_values :
combinations(peaks, num_data_points)) {
76 peak_values.push_back(0);
80 sourceValues.resize(num_data_points);
81 for(
size_t i = 0; i < sourceValues.size(); ++i) { sourceValues[i] = std::get<0>(sources[i]); }
82 std::sort(sourceValues.begin(), sourceValues.end());
83 sourceValues.push_back(0);
86 for(
size_t i = 0; i < peak_values.size(); ++i) {
87 std::cout << i <<
".: " << std::setw(8) << peak_values[i] <<
" - " << std::setw(8) << sourceValues[i] << std::endl;
90 if(peaks.size() > 3) {
91 double pratio = peak_values.front() / peak_values.at(peak_values.size() - 2);
92 double sratio = sourceValues.front() / sourceValues.at(sourceValues.size() - 2);
94 if(std::abs(pratio - sratio) > 0.02) {
100 fitter.ClearPoints();
101 fitter.AssignData(sourceValues.size(), 1, peak_values.data(), sourceValues.data());
104 if(fitter.GetChisquare() < best_chi2) {
106 for(
size_t i = 0; i < num_data_points; i++) {
107 tmpMap[peak_values[i]] = sourceValues[i];
109 best_chi2 = fitter.GetChisquare();
111 sourceTab->
Status(Form(
"%zu/%zu - %zu - %d", num_data_points, peaks.size(), maxSize, iteration), 1);
117 if(tmpMap.size() > 2) {
118 std::vector<double> peak_values;
119 std::vector<double> source_values;
120 for(
auto& item : tmpMap) {
121 peak_values.push_back(item.first);
122 source_values.push_back(item.second);
125 for(
size_t skipped_point = 0; skipped_point < source_values.size(); skipped_point++) {
126 std::swap(peak_values[skipped_point], peak_values.back());
127 std::swap(source_values[skipped_point], source_values.back());
129 fitter.ClearPoints();
130 fitter.AssignData(source_values.size() - 1, 1, peak_values.data(), source_values.data());
133 if(std::abs(fitter.GetParameter(0)) > 10) {
135 std::cout << fitter.GetParameter(0) <<
" too big an offset, clearing map with " << tmpMap.size() <<
" points: ";
136 for(
auto iter : tmpMap) { std::cout << iter.first <<
" - " << iter.second <<
"; "; }
137 std::cout << std::endl;
143 std::swap(peak_values[skipped_point], peak_values.back());
144 std::swap(source_values[skipped_point], source_values.back());
149 if(!tmpMap.empty()) {
153 for(
auto iter : tmpMap) {
154 result[*(std::find_if(peaks.begin(), peaks.end(), [&iter](
auto& item) { return iter.first == item; }))] =
155 *(std::find_if(sources.begin(), sources.end(), [&iter](
auto& item) { return iter.second == std::get<0>(item); }));
158 std::cout <<
"Smart matched " << num_data_points <<
" data points from " << peaks.size() <<
" peaks with " << sources.size() <<
" source energies" << std::endl;
159 std::cout <<
"Returning map with " << result.size() <<
" points: ";
160 for(
auto iter : result) { std::cout << iter.first <<
" - " << std::get<0>(iter.second) <<
"; "; }
161 std::cout << std::endl;
165 sourceTab->
Status(Form(
"%zu/%zu - %zu", num_data_points, peaks.size(), maxSize), 1);
171std::map<TGauss*, std::tuple<double, double, double, double>>
Match(std::vector<TGauss*> peaks, std::vector<std::tuple<double, double, double, double>> sources,
TSourceTab* sourceTab)
178 std::cout <<
"peaks:";
179 for(
auto* peak : peaks) {
180 std::cout <<
" " << peak->Centroid();
182 std::cout << std::endl;
183 std::cout <<
"energies:";
184 for(
auto source : sources) {
185 std::cout <<
" " << std::get<0>(source);
187 std::cout << std::endl;
190 std::map<TGauss*, std::tuple<double, double, double, double>> result;
191 std::sort(peaks.begin(), peaks.end(), [](
const TGauss* a,
const TGauss* b) { return a->Centroid() < b->Centroid(); });
192 std::sort(sources.begin(), sources.end());
194 auto maxSize = peaks.size();
195 if(sources.size() > maxSize) { maxSize = sources.size(); }
200 TLinearFitter fitter(1,
"1 ++ x");
203 std::vector<double> peakValues(peaks.size());
204 for(
size_t i = 0; i < peaks.size(); ++i) { peakValues[i] = peaks[i]->Centroid(); }
205 std::vector<double> sourceValues(sources.size());
206 for(
size_t i = 0; i < sources.size(); ++i) { sourceValues[i] = std::get<0>(sources[i]); }
207 std::map<double, double> tmpMap;
209 for(
size_t num_data_points = peakValues.size(); num_data_points > 0; num_data_points--) {
211 double best_chi2 = DBL_MAX;
213 for(
auto peak_values :
combinations(peakValues, num_data_points)) {
215 peak_values.push_back(0);
216 for(
auto source_values :
combinations(sourceValues, num_data_points)) {
217 source_values.push_back(0);
219 if(peakValues.size() > 3) {
220 double pratio = peak_values.front() / peak_values.at(peak_values.size() - 2);
221 double sratio = source_values.front() / source_values.at(source_values.size() - 2);
223 if(std::abs(pratio - sratio) > 0.02) {
230 fitter.ClearPoints();
231 fitter.AssignData(source_values.size(), 1, peak_values.data(), source_values.data());
234 if(fitter.GetChisquare() < best_chi2) {
236 for(
size_t i = 0; i < num_data_points; i++) {
237 tmpMap[peak_values[i]] = source_values[i];
240 std::cout <<
"Chi^2 " << fitter.GetChisquare() <<
" better than " << best_chi2 <<
":" << std::endl;
241 for(
auto iter : tmpMap) {
242 std::cout << std::setw(10) << iter.first <<
" - " << iter.second << std::endl;
245 best_chi2 = fitter.GetChisquare();
248 sourceTab->
Status(Form(
"%zu/%zu - %zu - %d", num_data_points, peakValues.size(), maxSize, iteration), 1);
254 if(tmpMap.size() > 2) {
255 std::vector<double> peak_values;
256 std::vector<double> source_values;
257 for(
auto& item : tmpMap) {
258 peak_values.push_back(item.first);
259 source_values.push_back(item.second);
262 for(
size_t skipped_point = 0; skipped_point < source_values.size(); skipped_point++) {
263 std::swap(peak_values[skipped_point], peak_values.back());
264 std::swap(source_values[skipped_point], source_values.back());
266 fitter.ClearPoints();
267 fitter.AssignData(source_values.size() - 1, 1, peak_values.data(), source_values.data());
270 if(std::abs(fitter.GetParameter(0)) > 10) {
272 std::cout << fitter.GetParameter(0) <<
" too big, clearing map with " << tmpMap.size() <<
" points: ";
273 for(
auto iter : tmpMap) { std::cout << iter.first <<
" - " << iter.second <<
"; "; }
274 std::cout << std::endl;
280 std::swap(peak_values[skipped_point], peak_values.back());
281 std::swap(source_values[skipped_point], source_values.back());
286 if(!tmpMap.empty()) {
287 for(
auto iter : tmpMap) {
288 result[*(std::find_if(peaks.begin(), peaks.end(), [&iter](
auto& item) { return iter.first == item->Centroid(); }))] =
289 *(std::find_if(sources.begin(), sources.end(), [&iter](
auto& item) { return iter.second == std::get<0>(item); }));
295 std::cout <<
"Matched " << num_data_points <<
" data points from " << peaks.size() <<
" peaks with " << sources.size() <<
" source energies" << std::endl;
296 std::cout <<
"Returning map with " << result.size() <<
" points: ";
297 for(
auto iter : result) { std::cout << iter.first->Centroid() <<
" - " << std::get<0>(iter.second) <<
"; "; }
298 std::cout << std::endl;
302 sourceTab->
Status(Form(
"%zu/%zu - %zu", num_data_points, peakValues.size(), maxSize), 1);
308std::map<TGauss*, std::tuple<double, double, double, double>>
SmartMatch(std::vector<TGauss*> peaks, std::vector<std::tuple<double, double, double, double>> sources,
TSourceTab* sourceTab)
315 for(
size_t i = 0; i < peaks.size() || i < sources.size(); ++i) {
316 std::cout << i <<
".: " << std::setw(8);
317 if(i < peaks.size()) {
318 std::cout << peaks[i]->Centroid();
322 std::cout <<
" - " << std::setw(8);
323 if(i < sources.size()) {
324 std::cout << std::get<0>(sources[i]);
328 std::cout << std::endl;
332 std::map<TGauss*, std::tuple<double, double, double, double>> result;
333 std::sort(peaks.begin(), peaks.end(), [](
const TGauss* a,
const TGauss* b) { return a->Centroid() < b->Centroid(); });
334 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); });
336 auto maxSize = peaks.size();
337 if(sources.size() > maxSize) { maxSize = sources.size(); }
342 TLinearFitter fitter(1,
"1 ++ x");
345 std::vector<double> peakValues(peaks.size());
346 for(
size_t i = 0; i < peaks.size(); ++i) { peakValues[i] = peaks[i]->Centroid(); }
347 std::vector<double> sourceValues(sources.size());
348 std::map<double, double> tmpMap;
350 for(
size_t num_data_points = std::min(peakValues.size(), sourceValues.size()); num_data_points > 0; num_data_points--) {
352 double best_chi2 = DBL_MAX;
354 for(
auto peak_values :
combinations(peakValues, num_data_points)) {
356 peak_values.push_back(0);
360 sourceValues.resize(num_data_points);
361 for(
size_t i = 0; i < sourceValues.size(); ++i) { sourceValues[i] = std::get<0>(sources[i]); }
362 std::sort(sourceValues.begin(), sourceValues.end());
363 sourceValues.push_back(0);
366 for(
size_t i = 0; i < peak_values.size(); ++i) {
367 std::cout << i <<
".: " << std::setw(8) << peak_values[i] <<
" - " << std::setw(8) << sourceValues[i] << std::endl;
370 if(peakValues.size() > 3) {
371 double pratio = peak_values.front() / peak_values.at(peak_values.size() - 2);
372 double sratio = sourceValues.front() / sourceValues.at(sourceValues.size() - 2);
374 if(std::abs(pratio - sratio) > 0.02) {
380 fitter.ClearPoints();
381 fitter.AssignData(sourceValues.size(), 1, peak_values.data(), sourceValues.data());
384 if(fitter.GetChisquare() < best_chi2) {
386 for(
size_t i = 0; i < num_data_points; i++) {
387 tmpMap[peak_values[i]] = sourceValues[i];
389 best_chi2 = fitter.GetChisquare();
391 sourceTab->
Status(Form(
"%zu/%zu - %zu - %d", num_data_points, peakValues.size(), maxSize, iteration), 1);
397 if(tmpMap.size() > 2) {
398 std::vector<double> peak_values;
399 std::vector<double> source_values;
400 for(
auto& item : tmpMap) {
401 peak_values.push_back(item.first);
402 source_values.push_back(item.second);
405 for(
size_t skipped_point = 0; skipped_point < source_values.size(); skipped_point++) {
406 std::swap(peak_values[skipped_point], peak_values.back());
407 std::swap(source_values[skipped_point], source_values.back());
409 fitter.ClearPoints();
410 fitter.AssignData(source_values.size() - 1, 1, peak_values.data(), source_values.data());
413 if(std::abs(fitter.GetParameter(0)) > 10) {
415 std::cout << fitter.GetParameter(0) <<
" too big an offset, clearing map with " << tmpMap.size() <<
" points: ";
416 for(
auto iter : tmpMap) { std::cout << iter.first <<
" - " << iter.second <<
"; "; }
417 std::cout << std::endl;
423 std::swap(peak_values[skipped_point], peak_values.back());
424 std::swap(source_values[skipped_point], source_values.back());
429 if(!tmpMap.empty()) {
433 for(
auto iter : tmpMap) {
434 result[*(std::find_if(peaks.begin(), peaks.end(), [&iter](
auto& item) { return iter.first == item->Centroid(); }))] =
435 *(std::find_if(sources.begin(), sources.end(), [&iter](
auto& item) { return iter.second == std::get<0>(item); }));
438 std::cout <<
"Smart matched " << num_data_points <<
" data points from " << peaks.size() <<
" peaks with " << sources.size() <<
" source energies" << std::endl;
439 std::cout <<
"Returning map with " << result.size() <<
" points: ";
440 for(
auto iter : result) { std::cout << iter.first->Centroid() <<
" - " << std::get<0>(iter.second) <<
"; "; }
441 std::cout << std::endl;
445 sourceTab->
Status(Form(
"%zu/%zu - %zu", num_data_points, peakValues.size(), maxSize), 1);
453 double result = par[1];
454 for(
int i = 1; i <= par[0]; ++i) {
455 result += par[i + 1] * TMath::Power(x[0], i);
462 return (matrix->Integral(bin, bin, 1, matrix->GetNbinsY()) > 1000);
467 : fSourceCalibration(sourceCal), fChannelTab(channel), fSourceFrame(frame), fProjection(projection), fSourceName(sourceName), fSourceEnergy(std::move(sourceEnergy))
497 for(
auto* fit :
fFits) {
505 for(
auto* peak :
fPeaks) {
533 std::array<int, 3> parts = {35, 50, 15};
547 fProjectionCanvas->GetCanvas()->Connect(
"ProcessedEvent(Int_t,Int_t,Int_t,TObject*)",
"TSourceTab",
this,
"ProjectionStatus(Int_t,Int_t,Int_t,TObject*)");
548 fProjectionCanvas->Connect(
"ProcessedEvent(Event_t*)",
"TSourceTab",
this,
"ProjectionStatus(Event_t*)");
554 fProjectionCanvas->Disconnect(
"ProcessedEvent(Event_t*)",
this,
"ProjectionStatus(Event_t*)");
555 fProjectionCanvas->GetCanvas()->Disconnect(
"ProcessedEvent(Int_t,Int_t,Int_t,TObject*)",
this,
"ProjectionStatus(Int_t,Int_t,Int_t,TObject*)");
573 if(event->fType == kEnterNotify) {
575 std::cout <<
"Entered source tab => changing gPad from " << gPad->GetName();
579 std::cout <<
" to " << gPad->GetName() << std::endl;
599 Status(selected->GetName(), 0);
600 Status(selected->GetObjectInfo(px, py), 1);
607 std::cout <<
fPeaks.size() <<
" peaks:";
608 for(
auto* peak :
fPeaks) {
609 std::cout <<
" " << peak->Centroid();
611 std::cout << std::endl;
613 auto* polym =
static_cast<TPolyMarker*
>(
fProjection->GetListOfFunctions()->FindObject(
"TPolyMarker"));
614 if(polym ==
nullptr) {
615 std::cerr <<
"No peaks defined yet?" << std::endl;
624 if(peak->Area() > 0) {
629 std::cout <<
"Ignoring peak at " << peak->Centroid() <<
" with negative area " << peak->Area() << std::endl;
634 std::sort(
fPeaks.begin(),
fPeaks.end(), [](
const TGauss* a,
const TGauss* b) { return a->Centroid() < b->Centroid(); });
640 Status(Form(
"%d/%d",
static_cast<int>(
fData->GetN()),
static_cast<int>(
fPeaks.size())), 2);
695 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;
711 if(obj->InheritsFrom(TRegion::Class())) {
712 auto* region =
static_cast<TRegion*
>(obj);
715 fRegions.emplace_back(std::min(region->GetX1(), region->GetX2()), std::max(region->GetX1(), region->GetX2()));
717 std::cout << obj->GetName() <<
" is not a TRegion but a " << obj->ClassName() << std::endl;
730 TList* functions =
fProjection->GetListOfFunctions();
732 std::cout <<
"Updating functions for histogram " <<
fProjection->GetName() <<
" by deleting " << functions->GetEntries() <<
" functions:" << std::endl;
733 for(
auto* obj : *functions) {
734 std::cout << obj <<
": " << obj->GetName() <<
"/" << obj->GetTitle() <<
" - " << obj->ClassName();
735 if(obj->IsA() == TF1::Class()) {
736 std::cout <<
" line color " <<
static_cast<TF1*
>(obj)->GetLineColor();
738 std::cout <<
" not a TF1";
740 std::cout << std::endl;
745 TObject* fit =
nullptr;
746 while((fit = functions->FindObject(
"gauss_total")) !=
nullptr) {
747 functions->Remove(fit);
750 for(
auto* obj :
fFits) {
751 functions->Add(obj->GetFitFunction()->Clone(
"gauss_total"));
755 functions->Add(obj->GetFitFunction()->Clone(
"gauss_total"));
758 std::cout <<
"And adding " << functions->GetEntries() <<
" functions instead:" << std::endl;
759 for(
auto* obj : *functions) {
760 std::cout << obj <<
": " << obj->GetName() <<
"/" << obj->GetTitle() <<
" - " << obj->ClassName();
761 if(obj->IsA() == TF1::Class()) {
762 std::cout <<
" line color " <<
static_cast<TF1*
>(obj)->GetLineColor();
764 std::cout <<
" not a TF1";
766 std::cout << std::endl;
769 if(!
fFits.empty() &&
fFits.front()->NumberOfPeaks() > 0 &&
fFits.back()->NumberOfPeaks() > 0) {
793 std::cout << __PRETTY_FUNCTION__ <<
": # peaks " <<
fPeaks.size() << std::endl;
801 TList* functions =
fProjection->GetListOfFunctions();
802 std::cout << functions->GetEntries() <<
" functions in projection " <<
fProjection->GetName() <<
" before clearing" << std::endl;
803 for(
auto* obj : *functions) {
804 std::cout << obj->GetName() <<
"/" << obj->GetTitle() <<
" - " << obj->ClassName() << std::endl;
810 std::vector<double> peakPos;
815 nofPeaks = spectrum.GetNPeaks();
816 peakPos.insert(peakPos.end(), spectrum.GetPositionX(), spectrum.GetPositionX() + nofPeaks);
819 fProjection->GetXaxis()->SetRangeUser(region.first, region.second);
821 int tmpNofPeaks = spectrum.GetNPeaks();
822 peakPos.insert(peakPos.end(), spectrum.GetPositionX(), spectrum.GetPositionX() + tmpNofPeaks);
823 nofPeaks += spectrum.GetNPeaks();
834 Status(Form(
"%d/%d",
static_cast<int>(
fData->GetN()), nofPeaks), 2);
844 if(calibration ==
nullptr) {
845 std::cerr << __PRETTY_FUNCTION__ <<
": provided calibration is nullptr, this function can only be called after an initial calibration has been made!" << std::endl;
858 std::cout <<
"calibration has " << calibration->GetNpar() <<
" parameters (";
859 for(
int i = 0; i < calibration->GetNpar(); ++i) {
863 std::cout << i <<
": " << calibration->GetParameter(i);
865 std::cout <<
"), if linear offset is " << calibration->Eval(0) <<
" and gain is " << calibration->Eval(1) - calibration->Eval(0) << std::endl;
866 TList* functions =
fProjection->GetListOfFunctions();
867 std::cout << functions->GetEntries() <<
" functions in projection " <<
fProjection->GetName() <<
" before clearing" << std::endl;
868 for(
auto* obj : *functions) {
869 std::cout << obj->GetName() <<
"/" << obj->GetTitle() <<
" - " << obj->ClassName() << std::endl;
874 std::map<TGauss*, std::tuple<double, double, double, double>> map;
878 std::vector<std::pair<std::tuple<double, double, double, double>,
double>> channelPos;
882 std::cout <<
"Skipping peak at " << std::get<0>(tuple) <<
" keV with intensity " << std::get<2>(tuple) <<
" below required minimum intensity " <<
TSourceCalibration::MinIntensity() << std::endl;
886 channelPos.emplace_back(tuple, calibration->GetX(std::get<0>(tuple)));
888 std::cout <<
"Set channel position for " << channelPos.size() - 1 <<
". peak to " << channelPos.back().second <<
" channels = " << std::get<0>(channelPos.back().first) <<
" keV" << std::endl;
892 for(
size_t i = 0; i < channelPos.size(); ++i) {
898 if(channelPos[i].second - lowRange < channelPos[i - 1].second + highRange) {
900 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;
902 lowRange = std::max(lowRange / 2., (channelPos[i].second - channelPos[i - 1].second) / 2.);
905 if(i + 1 < channelPos.size()) {
906 if(channelPos[i].second + highRange > channelPos[i + 1].second - lowRange) {
908 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;
910 highRange = std::min(highRange / 2., (channelPos[i + 1].second - channelPos[i].second) / 2.);
914 std::cout <<
"Trying to fit peak " << channelPos[i].second <<
" in range " << channelPos[i].second - lowRange <<
" - " << channelPos[i].second + highRange << std::endl;
917 auto* pf =
new TPeakFitter(channelPos[i].second - lowRange, channelPos[i].second + highRange);
918 auto* peak =
new TGauss(channelPos[i].second);
926 if(peak->Area() > 0) {
928 if(
Good(peak, channelPos[i].second - lowRange, channelPos[i].second + highRange)) {
931 map[peak] = channelPos[i].first;
933 std::cout <<
"Fitted peak " << channelPos[i].second - lowRange <<
" - " << channelPos[i].second + highRange <<
" -> centroid " << peak->Centroid() <<
", area " << peak->Area() << std::endl;
938 std::cout <<
"We're ignoring bad fits, and this one has position " << peak->Centroid() <<
" +- " << peak->CentroidErr() <<
", area " << peak->Area() <<
" +- " << peak->AreaErr() << std::endl;
942 std::cout <<
"Ignoring peak at " << peak->Centroid() <<
" with negative area " << peak->Area() << std::endl;
949 std::sort(
fFits.begin(),
fFits.end(), [](
const TPeakFitter* a,
const TPeakFitter* b) { return a->GetFitFunction()->GetParameter(
"centroid_0") < b->GetFitFunction()->GetParameter(
"centroid_0"); });
950 std::sort(
fBadFits.begin(),
fBadFits.end(), [](
const TPeakFitter* a,
const TPeakFitter* b) { return a->GetFitFunction()->GetParameter(
"centroid_0") < b->GetFitFunction()->GetParameter(
"centroid_0"); });
951 std::sort(
fPeaks.begin(),
fPeaks.end(), [](
const TGauss* a,
const TGauss* b) { return a->Centroid() < b->Centroid(); });
960 std::cout << __PRETTY_FUNCTION__ <<
": found " <<
fData->GetN() <<
" peaks";
961 Double_t* x =
fData->GetX();
962 Double_t* y =
fData->GetY();
963 for(
int i = 0; i <
fData->GetN(); ++i) {
964 std::cout <<
"; " << x[i] <<
" - " << y[i];
966 std::cout << std::endl;
973 std::cout <<
DCYAN <<
"Adding map with " << map.size() <<
" data points, fData = " <<
fData << std::endl;
975 if(
fData ==
nullptr) {
976 fData =
new TGraphErrors(map.size());
978 fData->Set(map.size());
980 fData->SetLineColor(2);
981 fData->SetMarkerColor(2);
983 for(
auto iter = map.begin(); iter != map.end();) {
985 auto peakPos = iter->first;
986 auto energy = std::get<0>(iter->second);
987 fData->SetPoint(i, peakPos, energy);
989 std::cout <<
"Using peak with position " << peakPos <<
", energy " << energy << std::endl;
995 std::cout <<
"Accepted " << map.size() <<
" peaks" << std::endl;
1003 std::cout <<
DCYAN <<
"Adding map with " << map.size() <<
" data points, fData = " <<
fData << std::endl;
1005 if(
fData ==
nullptr) {
1006 fData =
new TGraphErrors(map.size());
1008 fData->Set(map.size());
1010 fData->SetLineColor(2);
1011 fData->SetMarkerColor(2);
1012 if(
fFwhm ==
nullptr) {
1013 fFwhm =
new TGraphErrors(map.size());
1015 fFwhm->Set(map.size());
1017 fFwhm->SetLineColor(4);
1018 fFwhm->SetMarkerColor(4);
1020 for(
auto iter = map.begin(); iter != map.end();) {
1022 auto peakPos = iter->first->Centroid();
1023 auto peakPosErr = iter->first->CentroidErr();
1024 auto peakArea = iter->first->Area();
1025 auto peakAreaErr = iter->first->AreaErr();
1026 auto fwhm = iter->first->FWHM();
1027 auto fwhmErr = iter->first->FWHMErr();
1028 auto energy = std::get<0>(iter->second);
1029 auto energyErr = std::get<1>(iter->second);
1031 if(!
Good(iter->first)) {
1033 std::cout <<
"Dropping peak with position " << peakPos <<
" +- " << peakPosErr <<
", area " << peakArea <<
" +- " << peakAreaErr <<
", energy " << energy << std::endl;
1035 iter = map.erase(iter);
1037 std::cout <<
"Erasing peak returned iterator " << std::distance(map.begin(), iter) << std::endl;
1040 fData->SetPoint(i, peakPos, energy);
1041 fData->SetPointError(i, peakPosErr, energyErr);
1042 fFwhm->SetPoint(i, peakPos, fwhm);
1043 fFwhm->SetPointError(i, peakPosErr, fwhmErr);
1045 std::cout <<
"Using peak with position " << peakPos <<
" +- " << peakPosErr <<
", area " << peakArea <<
" +- " << peakAreaErr <<
", energy " << energy << std::endl;
1052 std::cout <<
"Accepted " << map.size() <<
" peaks" << std::endl;
1055 fData->Set(map.size());
1056 fFwhm->Set(map.size());
1060 TList* functions =
fProjection->GetListOfFunctions();
1062 std::cout << functions->GetEntries() <<
" functions in projection " <<
fProjection->GetName() << std::endl;
1063 for(
auto* obj : *functions) {
1064 std::cout << obj->GetName() <<
"/" << obj->GetTitle() <<
" - " << obj->ClassName() << std::endl;
1067 auto* polym =
static_cast<TPolyMarker*
>(functions->FindObject(
"TPolyMarker"));
1068 if(polym !=
nullptr) {
1069 double* oldX = polym->GetX();
1070 double* oldY = polym->GetY();
1071 int size = polym->GetN();
1072 std::vector<double> newX;
1073 std::vector<double> newY;
1074 std::vector<double> unusedX;
1075 std::vector<double> unusedY;
1076 for(i = 0; i < size; ++i) {
1078 for(
auto point : map) {
1080 newX.push_back(oldX[i]);
1081 newY.push_back(oldY[i]);
1087 unusedX.push_back(oldX[i]);
1088 unusedY.push_back(oldY[i]);
1091 polym->SetPolyMarker(newX.size(), newX.data(), newY.data());
1092 auto* unusedMarkers =
new TPolyMarker(unusedX.size(), unusedX.data(), unusedY.data());
1093 unusedMarkers->SetMarkerStyle(23);
1094 unusedMarkers->SetMarkerColor(16);
1095 functions->Add(unusedMarkers);
1097 std::cout <<
fProjection->GetTitle() <<
": " << size <<
" peaks founds total, " << polym->GetN() <<
" used, and " << unusedMarkers->GetN() <<
" unused" << std::endl;
1099 std::cout <<
"Used: ";
1100 for(
size_t m = 0; m < newX.size(); ++m) { std::cout << newX[m] <<
" - " << newY[m] <<
";"; }
1101 std::cout << std::endl;
1102 std::cout <<
"Unused: ";
1103 for(
size_t m = 0; m < unusedX.size(); ++m) { std::cout << unusedX[m] <<
" - " << unusedY[m] <<
";"; }
1104 std::cout << std::endl;
1107 std::cout << functions->GetEntries() <<
" functions in projection " <<
fProjection->GetTitle() << std::endl;
1108 for(
auto* obj : *functions) {
1109 std::cout << obj->GetName() <<
"/" << obj->GetTitle() <<
" - " << obj->ClassName() << std::endl;
1116 TIter iter(functions);
1117 TObject* item =
nullptr;
1118 while((item = iter.Next()) !=
nullptr) {
1119 if(item->IsA() == TF1::Class() || item->IsA() == TGauss::Class()) {
1120 double centroid = 0.;
1121 if(item->IsA() == TF1::Class()) {
1122 centroid =
static_cast<TF1*
>(item)->GetParameter(1);
1124 centroid =
static_cast<TGauss*
>(item)->Centroid();
1127 for(
auto point : map) {
1136 if(item->IsA() == TF1::Class()) {
1137 static_cast<TF1*
>(item)->SetLineColor(kGray);
1151 std::cout <<
DCYAN << __PRETTY_FUNCTION__ <<
": index " << index <<
", channel " << channel << std::endl;
1152 for(
size_t i = 0; i <
fPeaks.size() && i <
fFits.size(); ++i) {
1153 std::cout << i <<
": " <<
fPeaks[i]->Centroid() <<
" +- " <<
fPeaks[i]->CentroidErr() <<
" - " <<
fFits[i]->GetFitFunction()->GetParameter(
"centroid_0") << std::endl;
1157 if(index >=
fPeaks.size()) {
1158 std::cerr <<
"Trying to replace peak at index " << index <<
" but there are only " <<
fPeaks.size() <<
" peaks!" << std::endl;
1166 double low = channel - range;
1167 double high = channel + range;
1168 if(
fPeaks.at(index)->Centroid() < channel) {
1169 low = (
fPeaks.at(index)->Centroid() + channel) / 2.;
1171 high = (
fPeaks.at(index)->Centroid() + channel) / 2.;
1175 auto* peak =
new TGauss(channel);
1183 if(peak->Area() > 0) {
1184 if(
Good(peak, low, high)) {
1186 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;
1187 std::cout <<
"Deleting " << index <<
". peak " <<
fPeaks.at(index) << std::flush;
1189 peak->SetLineColor(
fPeaks.at(index)->GetLineColor());
1193 std::cout <<
" and setting it to " <<
fPeaks.at(index) << std::endl;
1196 std::cout <<
"Deleting " << index <<
". fit " <<
fFits.at(index) << std::flush;
1198 pf->GetFitFunction()->SetLineColor(
fFits.at(index)->GetFitFunction()->GetLineColor());
1199 delete fFits.at(index);
1202 std::cout <<
" and setting it to " <<
fFits.at(index) << std::endl;
1205 fData->SetPoint(index, peak->Centroid(),
fData->GetPointY(index));
1206 fData->SetPointError(index, peak->CentroidErr(),
fData->GetErrorY(index));
1207 fFwhm->SetPoint(index, peak->Centroid(), peak->FWHM());
1208 fFwhm->SetPointError(index, peak->CentroidErr(), peak->FWHMErr());
1210 std::cout <<
"Fitted peak " << low <<
" - " << high <<
" -> centroid " << peak->Centroid() <<
", area " << peak->Area() << std::endl;
1214 std::cout <<
"We're ignoring bad fits, and this one has position " << peak->Centroid() <<
" +- " << peak->CentroidErr() <<
", area " << peak->Area() <<
" +- " << peak->AreaErr() << std::endl;
1218 std::cout <<
"Ignoring peak at " << peak->Centroid() <<
" with negative area " << peak->Area() << std::endl;
1225 std::cout <<
DCYAN << __PRETTY_FUNCTION__ <<
": oldPoint " << oldPoint << std::endl;
1231 auto* erasedFit =
fFits.at(oldPoint);
1234 fData->RemovePoint(oldPoint);
1249 for(
size_t i = 0; i <
fPeaks.size() && i <
fFits.size(); ++i) {
1252 fPeaks[i]->SetLineColor(kRed + 2);
1253 fFits[i]->GetFitFunction()->SetLineColor(kRed);
1256 fPeaks[i]->SetLineColor(kBlue + 2);
1257 fFits[i]->GetFitFunction()->SetLineColor(kBlue);
1262 for(
size_t i = 0; i <
fBadFits.size(); ++i) {
1265 fBadFits[i]->GetFitFunction()->SetLineColor(kGray);
1268 fBadFits[i]->GetFitFunction()->SetLineColor(kGray + 2);
1278 gVirtualX->Update();
1287 std::cout <<
" is null";
1289 std::cout << std::endl;
1291 std::cout <<
"Data " <<
fData;
1292 if(
fData !=
nullptr) {
1293 std::cout <<
" = " <<
fData->GetName() <<
"/" <<
fData->GetTitle();
1295 std::cout <<
" is null";
1297 std::cout << std::endl;
1299 std::cout <<
"Fwhm " <<
fFwhm;
1300 if(
fFwhm !=
nullptr) {
1301 std::cout <<
" = " <<
fFwhm->GetName() <<
"/" <<
fFwhm->GetTitle();
1303 std::cout <<
" is null";
1305 std::cout << std::endl;
1307 std::cout <<
fFits.size() <<
" good fits:";
1308 for(
size_t i = 0; i <
fFits.size(); ++i) {
1309 std::cout <<
" " << std::setw(2) << i <<
" - " << std::setw(8) <<
fFits.at(i)->GetFitFunction()->GetParameter(
"centroid_0");
1311 std::cout << std::endl;
1313 std::cout <<
fBadFits.size() <<
" bad fits:";
1314 for(
size_t i = 0; i <
fBadFits.size(); ++i) {
1315 std::cout <<
" " << std::setw(2) << i <<
" - " << std::setw(8) <<
fBadFits.at(i)->GetFitFunction()->GetParameter(
"centroid_0");
1317 std::cout << std::endl;
1319 std::cout <<
fPeaks.size() <<
" peaks:";
1320 for(
size_t i = 0; i <
fPeaks.size(); ++i) {
1321 std::cout <<
" " << std::setw(2) << i <<
" - " << std::setw(8) <<
fPeaks.at(i)->Centroid();
1323 std::cout << std::endl;
1328 std::cout <<
"TSourceTab " <<
fSourceName <<
" projection canvas:" << std::endl;
1337 std::cout <<
"TSourceTab frame:" << std::endl;
1339 std::cout <<
"TSourceTab canvas:" << std::endl;
1341 std::cout <<
"TSourceTab status bar:" << std::endl;
1346TChannelTab::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)
1347 : 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))
1350 std::cout <<
DYELLOW <<
"========================================" << std::endl;
1351 std::cout << __PRETTY_FUNCTION__ << std::endl
1352 <<
" name = " <<
fName <<
", fData = " <<
fData << std::endl;
1353 std::cout <<
"========================================" << std::endl;
1359 std::cout <<
DYELLOW <<
"----------------------------------------" << std::endl;
1360 std::cout << __PRETTY_FUNCTION__ << std::endl
1361 <<
" channel " <<
fName <<
" done" << std::endl;
1362 std::cout <<
"----------------------------------------" << std::endl;
1397 for(
size_t source = 0; source <
fNuclei.size(); ++source) {
1402 if(*iter ==
nullptr) {
1409 fChannelFrame->AddFrame(
fSourceTab,
new TGLayoutHints(kLHintsLeft | kLHintsTop | kLHintsExpandX | kLHintsExpandY, 2, 2, 2, 2));
1416 std::array<int, 3> parts = {25, 35, 40};
1422 fFwhmFrame->AddFrame(
fFwhmCanvas,
new TGLayoutHints(kLHintsTop | kLHintsExpandX | kLHintsExpandY, 2, 2, 2, 2));
1428 fInitFrame->AddFrame(
fInitCanvas,
new TGLayoutHints(kLHintsTop | kLHintsExpandX | kLHintsExpandY, 2, 2, 2, 2));
1430 fChannelFrame->AddFrame(
fCanvasTab,
new TGLayoutHints(kLHintsRight | kLHintsTop | kLHintsExpandX | kLHintsExpandY, 2, 2, 2, 2));
1443 fLegend =
new TLegend(0.8, 0.3, 0.95, 0.3 +
static_cast<double>(
fNuclei.size()) * 0.05);
1446 fResidualPad =
new TPad(Form(
"res_%s",
fName.c_str()), Form(
"residual for %s",
fName.c_str()), 0.0, 0., 0.2, 1.);
1472 std::cout <<
DYELLOW <<
"Creating source tab " << source <<
", using fSourceCalibration " <<
fSourceCalibration << std::endl;
1474 TGCompositeFrame* tmpTab =
nullptr;
1491 std::cout <<
DYELLOW <<
"Skipping projection of source " << source <<
" = " <<
fProjections[source]->GetName() <<
", only " <<
fProjections[source]->GetEntries() <<
" entries" << std::endl;
1495 std::cout << __PRETTY_FUNCTION__ <<
" source " << source <<
" done" << std::endl;
1502 fSourceTab->Connect(
"Selected(Int_t)",
"TChannelTab",
this,
"SelectedTab(Int_t)");
1504 source->MakeConnections();
1506 fCalibrationCanvas->GetCanvas()->Connect(
"ProcessedEvent(Int_t,Int_t,Int_t,TObject*)",
"TChannelTab",
this,
"CalibrationStatus(Int_t,Int_t,Int_t,TObject*)");
1507 fCalibrationCanvas->Connect(
"ProcessedEvent(Event_t*)",
"TChannelTab",
this,
"SelectCanvas(Event_t*)");
1508 if(
fData !=
nullptr) {
1510 std::cout <<
DYELLOW << __PRETTY_FUNCTION__ <<
": connecting fData " <<
fData <<
":" << std::endl;
1513 fData->Connect(
"RemovePoint(Int_t, Int_t)",
"TChannelTab",
this,
"RemovePoint(Int_t, Int_t)");
1515 std::cerr <<
DRED <<
"Failed to create connections for the data graph fData since it hasn't been created yet!" << std::endl;
1522 fSourceTab->Disconnect(
"Selected(Int_t)",
this,
"SelectedTab(Int_t)");
1524 source->Disconnect();
1526 fCalibrationCanvas->GetCanvas()->Disconnect(
"ProcessedEvent(Int_t,Int_t,Int_t,TObject*)",
this,
"CalibrationStatus(Int_t,Int_t,Int_t,TObject*)");
1527 fData->Disconnect(
"RemovePoint(Int_t, Int_t)",
this,
"RemovePoint(Int_t, Int_t)");
1556 if(event->fType == kEnterNotify) {
1558 std::cout <<
"Entered channel tab => changing gPad from " << gPad->GetName();
1562 std::cout <<
" to " << gPad->GetName() << std::endl;
1570 std::cout <<
DCYAN << __PRETTY_FUNCTION__ <<
": oldGraph " << oldGraph <<
", oldPoint " << oldPoint << std::endl;
1572 if(0 <= oldGraph && oldGraph <
static_cast<int>(
fSources.size())) {
1574 return fSources[oldGraph]->RemovePoint(oldPoint);
1576 std::cout <<
"Can't remove negative point " << oldPoint <<
" from graph " << oldGraph << std::endl;
1578 std::cout <<
"Graph the point was removed from was " << oldGraph <<
", but we only have " <<
fSources.size() <<
" source tabs?" << std::endl;
1597 if(event == kKeyPress) {
1601 if(canvas ==
nullptr) {
1605 auto* pad = canvas->GetSelectedPad();
1606 if(pad ==
nullptr) {
1614 fChannelStatusBar->SetText(Form(
"x = %f, y = %f", pad->AbsPixeltoX(px), pad->AbsPixeltoY(py)), 1);
1622 if(
fData ==
nullptr) {
1628 fData->SetName(Form(
"data%s",
fName.c_str()));
1630 std::cout <<
"set name of fData using " <<
fName.c_str() <<
": " <<
fData->GetName() << std::endl;
1631 std::cout <<
"fData " <<
fData <<
": " << (
fData !=
nullptr ?
fData->
GetN() : -2) <<
" data points after creation" << std::endl;
1632 std::cout <<
"Looping over " <<
fNuclei.size() <<
" sources, fSources.size() = " <<
fSources.size() << std::endl;
1634 for(
size_t source = 0; source <
fNuclei.size() && source <
fSources.size(); ++source) {
1644 std::cout <<
"fData " <<
fData <<
": " << (
fData !=
nullptr ?
fData->
GetN() : -1) <<
" data points after adding " <<
fNuclei.size() <<
" graphs" << std::endl;
1653 if(
fFwhm ==
nullptr) {
1659 fFwhm->SetName(Form(
"fwhm%s",
fName.c_str()));
1661 std::cout <<
"set name of fFwhm using " <<
fName.c_str() <<
": " <<
fFwhm->GetName() << std::endl;
1662 std::cout <<
"fFwhm " <<
fFwhm <<
": " << (
fFwhm !=
nullptr ?
fFwhm->
GetN() : -2) <<
" data points after creation" << std::endl;
1663 std::cout <<
"Looping over " <<
fNuclei.size() <<
" sources, fSources.size() = " <<
fSources.size() << std::endl;
1665 for(
size_t source = 0; source <
fNuclei.size() && source <
fSources.size(); ++source) {
1666 if(
fSources[source]->Fwhm() !=
nullptr &&
fSources[source]->Fwhm()->GetN() > 0) {
1675 std::cout <<
"fFwhm " <<
fFwhm <<
": " << (
fFwhm !=
nullptr ?
fFwhm->
GetN() : -1) <<
" data points after adding " <<
fNuclei.size() <<
" graphs" << std::endl;
1691 TF1* calibration =
new TF1(
"fitfunction",
::Polynomial, 0., 10000., degree + 2);
1692 calibration->FixParameter(0, degree);
1695 if(
fData !=
nullptr) {
1696 std::cout <<
fData->
GetN() <<
" data points being fit, ";
1700 calibration->GetRange(min, max);
1701 std::cout <<
"range " << min <<
" - " << max << std::endl;
1704 TString text = Form(
"%.6f + %.6f*x", calibration->GetParameter(1), calibration->GetParameter(2));
1705 for(
int i = 2; i <= degree; ++i) {
1706 text.Append(Form(
" + %.6f*x^%d", calibration->GetParameter(i + 1), i));
1726 fChi2Label =
new TPaveText(left, bottom, right, top);
1735 fChi2Label->AddText(Form(
"#chi^{2}/NDF = %f", calibration->GetChisquare() / calibration->GetNDF()));
1739 std::cout <<
"fChi2Label set to:" << std::endl;
1741 std::cout <<
"Text size " <<
fChi2Label->GetTextSize() << std::endl;
1744 fInfoLabel =
new TPaveText(0, 0.95, 1., 1.,
"NDCNB");
1769 calibration->GetRange(min, max);
1770 std::cout <<
DYELLOW <<
"calibration has range " << min <<
" - " << max;
1773 std::cout <<
", fit function has range " << min <<
" - " << max;
1775 std::cout << std::endl;
1790 if(
fData ==
nullptr) {
1791 std::cout <<
"No longer have a data for channel " <<
Name() <<
"?" << std::endl;
1796 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;
1801 std::cout <<
"Recursively removed all data points for channel " <<
Name() << std::endl;
1809 if(std::abs(*maxElement) < maxResidual) {
1831 std::stringstream str;
1832 str << std::hex <<
fName;
1837 if(calibration ==
nullptr) {
1838 std::cout <<
"Failed to find calibration in fData" << std::endl;
1842 std::vector<Float_t> parameters;
1843 for(
int i = 0; i <= calibration->GetParameter(0); ++i) {
1844 parameters.push_back(
static_cast<Float_t
>(calibration->GetParameter(i + 1)));
1847 if(channel ==
nullptr) {
1848 std::cerr <<
"Failed to get channel for address " <<
hex(address, 4) << std::endl;
1858 for(
int i = 0; i <
fData->
GetN(); ++i) {
1872 std::cout <<
DYELLOW <<
"Rough calibration in source tab:" << std::endl;
1875 source->InitialCalibration(force);
1884 std::cout <<
"Cloned data " <<
fData->GetName() <<
" to " <<
fInit->GetName() <<
":" << std::endl;
1887 auto* oldPad = gPad;
1899 fCalLabel =
new TPaveText(left, bottom, right, top);
1906 std::stringstream str;
1910 str <<
"Unknown fit function with " <<
fInit->
FitFunction()->GetNpar() <<
" parameters";
1913 std::cout <<
"Created label text \"" << str.str() <<
"\"" << std::endl;
1928 for(
int tab = 0; tab <
fSourceTab->GetNumberOfTabs(); ++tab) {
1929 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;
1943 std::cout <<
DYELLOW <<
"Finding calibrated peaks in all source tabs" << std::endl;
1947 std::cout <<
DYELLOW <<
"Finding calibrated peaks in source tab " << source->SourceName() << std::endl;
1954 std::cout <<
DYELLOW <<
"Done finding calibrated peaks in all source tabs" << std::endl;
1973 fData->Write(Form(
"calGraph_%s",
fName.c_str()), TObject::kOverwrite);
1974 fFwhm->Write(Form(
"fwhm_%s",
fName.c_str()), TObject::kOverwrite);
1982 TH1* hist1 =
nullptr;
1983 for(
const auto&& obj : *(gPad->GetListOfPrimitives())) {
1984 if(obj->InheritsFrom(TGraph::Class())) {
1985 hist1 =
static_cast<TGraph*
>(obj)->GetHistogram();
1989 if(hist1 ==
nullptr) {
1990 std::cout <<
"ZoomX - Failed to find histogram for pad " << gPad->GetName() << std::endl;
1996 std::string padName = gPad->GetName();
1997 std::string baseName = padName.substr(0, 3);
1998 std::string channelName = padName.substr(4);
2001 std::string newName;
2002 if(baseName ==
"cal") {
2003 newName =
"res_" + channelName;
2004 }
else if(baseName ==
"res") {
2005 newName =
"cal_" + channelName;
2007 std::cout <<
"Unknown combination of pad " << gPad->GetName() <<
" and histogram " << hist1->GetName() << std::endl;
2010 auto* newObj = gPad->GetCanvas()->FindObject(newName.c_str());
2011 if(newObj ==
nullptr) {
2012 std::cout <<
"Failed to find " << newName << std::endl;
2016 if(newObj->IsA() != TPad::Class()) {
2017 std::cout << newObj <<
" = " << newObj->GetName() <<
", " << newObj->GetTitle() <<
" is a " << newObj->ClassName() <<
" not a TPad" << std::endl;
2020 auto* pad2 =
static_cast<TPad*
>(newObj);
2021 if(pad2 ==
nullptr) {
2022 std::cout <<
"Failed to find partner pad " << newName << std::endl;
2026 TH1* hist2 =
nullptr;
2027 for(
const auto&& obj : *(pad2->GetListOfPrimitives())) {
2028 if(obj->InheritsFrom(TGraph::Class())) {
2029 hist2 =
static_cast<TGraph*
>(obj)->GetHistogram();
2033 if(hist2 ==
nullptr) {
2034 std::cout <<
"ZoomX - Failed to find histogram for partner pad " << newName << std::endl;
2039 TAxis* axis1 = hist1->GetXaxis();
2040 Int_t binmin = axis1->GetFirst();
2041 Int_t binmax = axis1->GetLast();
2042 Double_t xmin = axis1->GetBinLowEdge(binmin);
2043 Double_t xmax = axis1->GetBinLowEdge(binmax);
2044 TAxis* axis2 = hist2->GetXaxis();
2045 Int_t newmin = axis2->FindBin(xmin);
2046 Int_t newmax = axis2->FindBin(xmax);
2047 axis2->SetRange(newmin, newmax);
2056 TH1* hist1 =
nullptr;
2057 for(
const auto&& obj : *(gPad->GetListOfPrimitives())) {
2058 if(obj->InheritsFrom(TGraph::Class())) {
2059 hist1 =
static_cast<TGraph*
>(obj)->GetHistogram();
2063 if(hist1 ==
nullptr) {
2064 std::cout <<
"ZoomY - Failed to find histogram for pad " << gPad->GetName() << std::endl;
2070 std::string padName = gPad->GetName();
2071 std::string baseName = padName.substr(0, 3);
2072 std::string channelName = padName.substr(4);
2075 std::string newName;
2076 if(baseName ==
"cal") {
2077 newName =
"res_" + channelName;
2078 }
else if(baseName ==
"res") {
2079 newName =
"cal_" + channelName;
2081 std::cout <<
"Unknown combination of pad " << gPad->GetName() <<
" and histogram " << hist1->GetName() << std::endl;
2084 auto* newObj = gPad->GetCanvas()->FindObject(newName.c_str());
2085 if(newObj ==
nullptr) {
2086 std::cout <<
"Failed to find " << newName << std::endl;
2090 if(newObj->IsA() != TPad::Class()) {
2091 std::cout << newObj <<
" = " << newObj->GetName() <<
", " << newObj->GetTitle() <<
" is a " << newObj->ClassName() <<
" not a TPad" << std::endl;
2094 auto* pad2 =
static_cast<TPad*
>(newObj);
2095 if(pad2 ==
nullptr) {
2096 std::cout <<
"Failed to find partner pad " << newName << std::endl;
2100 TH1* hist2 =
nullptr;
2101 for(
const auto&& obj : *(pad2->GetListOfPrimitives())) {
2102 if(obj->InheritsFrom(TGraph::Class())) {
2103 hist2 =
static_cast<TGraph*
>(obj)->GetHistogram();
2107 if(hist2 ==
nullptr) {
2108 std::cout <<
"ZoomY - Failed to find histogram for partner pad " << newName << std::endl;
2113 hist2->SetMinimum(hist1->GetMinimum());
2114 hist2->SetMaximum(hist1->GetMaximum());
2122 std::cout <<
"TChannelTab " <<
Name() <<
" calibration canvas:" << std::endl;
2127 std::cout <<
"TChannelTab fwhm canvas:" << std::endl;
2129 for(
auto* obj : *(
fFwhmCanvas->GetCanvas()->GetListOfPrimitives())) {
2133 sourceTab->PrintCanvases();
2139 std::cout <<
"TChannelTab frame:" << std::endl;
2141 std::cout <<
"TChannelTab canvas:" << std::endl;
2143 std::cout <<
"TChannelTab status bar:" << std::endl;
2146 sourceTab->PrintLayout();
2169 : TGMainFrame(nullptr, 2 * fPanelWidth, fPanelHeight + 2 * fStatusbarHeight), fDefaultSigma(sigma), fDefaultThreshold(threshold), fDefaultDegree(degree)
2171 TH1::AddDirectory(
false);
2174 va_start(args, count);
2175 for(
int i = 0; i < count; ++i) {
2176 fMatrices.push_back(va_arg(args, TH2*));
2178 std::cout <<
"Error, got nullptr as matrix input?" << std::endl;
2184 std::cout <<
DGREEN << __PRETTY_FUNCTION__ <<
": verbose level " <<
fVerboseLevel << std::endl
2185 <<
"using " << count <<
"/" <<
fMatrices.size() <<
" matrices:" << std::endl;
2187 std::cout <<
mat << std::flush <<
" = " <<
mat->GetName() << std::endl;
2192 gErrorIgnoreLevel = kError;
2193 gPrintViaErrorHandler =
true;
2197 std::cout <<
"Starting redirect to " <<
fLogFile << std::endl;
2203 std::map<int, int> channelToIndex;
2204 for(
int bin = 1; bin <=
fMatrices[0]->GetNbinsX(); ++bin) {
2217 for(
size_t i = 1; i <
fMatrices.size(); ++i) {
2219 for(
int bin = 1; bin <=
fMatrices[i]->GetNbinsX(); ++bin) {
2222 if(channelToIndex.find(bin) == channelToIndex.end() || tmpBins != channelToIndex[bin]) {
2223 std::ostringstream error;
2224 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;
2225 throw std::invalid_argument(error.str());
2227 if(strcmp(
fMatrices[0]->GetXaxis()->GetBinLabel(bin),
fMatrices[i]->GetXaxis()->GetBinLabel(bin)) != 0) {
2228 std::ostringstream error;
2229 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;
2230 throw std::invalid_argument(error.str());
2234 if(channelToIndex.find(bin) != channelToIndex.end()) {
2235 std::ostringstream error;
2236 error <<
"Mismatch in " << i <<
". matrix (" <<
fMatrices[i]->GetName() <<
"), bin " << bin <<
" is empty, but should be " << channelToIndex[bin] <<
". filled bin" << std::endl;
2237 throw std::invalid_argument(error.str());
2245 fOutput =
new TFile(
"TSourceCalibration.root",
"recreate");
2247 throw std::runtime_error(
"Unable to open output file \"TSourceCalibration.root\"!");
2255 SetWindowName(
"SourceCalibration");
2261 Resize(GetDefaultSize());
2281 auto* layoutManager =
new TGTableLayout(
this,
fMatrices.size() + 1, 2,
true, 5);
2283 SetLayoutManager(layoutManager);
2295#if __cplusplus >= 201703L
2298 if(std::getenv(
"GRSISYS") ==
nullptr) {
2299 throw std::runtime_error(
"Failed to get environment variable $GRSISYS");
2301 std::string path(std::getenv(
"GRSISYS"));
2302 path +=
"/libraries/TAnalysis/SourceData/";
2303 for(
const auto& file : std::filesystem::directory_iterator(path)) {
2304 if(file.is_regular_file() && file.path().extension().compare(
".sou") == 0) {
2305 fSourceBox.back()->AddEntry(file.path().stem().c_str(), index);
2307 if(std::strstr(
fMatrices[i]->GetName(), file.path().stem().c_str()) !=
nullptr) {
2312 std::cout <<
"matrix name " <<
fMatrices[i]->GetName() <<
" not matching " << file.path().stem().c_str() << std::endl;
2320 if(std::strstr(
fMatrices[i]->GetName(),
"22Na") !=
nullptr) {
2326 if(std::strstr(
fMatrices[i]->GetName(),
"56Co") !=
nullptr) {
2332 if(std::strstr(
fMatrices[i]->GetName(),
"60Co") !=
nullptr) {
2338 if(std::strstr(
fMatrices[i]->GetName(),
"133Ba") !=
nullptr) {
2344 if(std::strstr(
fMatrices[i]->GetName(),
"152Eu") !=
nullptr) {
2350 if(std::strstr(
fMatrices[i]->GetName(),
"241Am") !=
nullptr) {
2359 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; }
2360 AddFrame(
fMatrixNames.back(),
new TGTableLayoutHints(0, 1, i, i + 1, kLHintsRight | kLHintsCenterY));
2361 AddFrame(
fSourceBox.back(),
new TGTableLayoutHints(1, 2, i, i + 1, kLHintsLeft | kLHintsCenterY));
2368 AddFrame(
fStartButton,
new TGTableLayoutHints(0, 2, i, i + 1, kLHintsCenterX | kLHintsCenterY));
2378 box->Connect(
"Selected(Int_t, Int_t)",
"TSourceCalibration",
this,
"SetSource(Int_t, Int_t)");
2382 fStartButton->Connect(
"Clicked()",
"TSourceCalibration",
this,
"Start()");
2389 box->Disconnect(
"Selected(Int_t, Int_t)",
this,
"SetSource(Int_t, Int_t)");
2392 fStartButton->Disconnect(
"Clicked()",
this,
"Start()");
2398 RemoveFrame(element);
2422 auto* nucleus =
new TNucleus(
fSourceBox[index]->GetListBox()->GetEntry(entryId)->GetTitle());
2423 TIter iter(nucleus->GetTransitionList());
2425 while(
auto* transition =
static_cast<TTransition*
>(iter.Next())) {
2426 fSourceEnergy[index].push_back(std::make_tuple(transition->GetEnergy(), transition->GetEnergyUncertainty(), transition->GetIntensity(), transition->GetIntensityUncertainty()));
2438 if(channelTab ==
nullptr) {
continue; }
2439 channelTab->UpdateChannel();
2443 std::cout <<
"Closing window" << std::endl;
2445 std::cout <<
"all done" << std::endl;
2455 TTimer::SingleShot(
fWaitMs,
"TSourceCalibration",
this,
"HandleTimer()");
2463 for(
size_t i = 0; i <
fSource.size(); ++i) {
2465 std::cerr <<
"Source " << i <<
" not set!" << std::endl;
2470 for(
size_t i = 0; i <
fSource.size(); ++i) {
2471 for(
size_t j = i + 1; j <
fSource.size(); ++j) {
2473 std::cerr <<
"Duplicate sources: " << i <<
" - " <<
fSource[i]->GetName() <<
" and " << j <<
" - " <<
fSource[j]->GetName() << std::endl;
2484 SetLayoutManager(
new TGVerticalLayout(
this));
2490 fProgressBar->ShowPosition(
true,
false,
"Creating source tabs: %.0f");
2492 AddFrame(
fProgressBar,
new TGLayoutHints(kLHintsCenterX | kLHintsCenterY | kLHintsExpandX | kLHintsExpandY, 0, 0, 0, 0));
2523 SetLayoutManager(
new TGVerticalLayout(
this));
2529 std::vector<GH1D*> projections(
fMatrices.size());
2532 projections[index] =
new GH1D(matrix->ProjectionY(Form(
"%s_%s",
fSource[index]->GetName(), matrix->GetXaxis()->GetBinLabel(bin)), bin, bin));
2535 auto* frame =
fTab->AddTab(
fMatrices[0]->GetXaxis()->GetBinLabel(bin));
2568 AddFrame(
fTab,
new TGLayoutHints(kLHintsTop | kLHintsExpandX | kLHintsExpandY, 0, 0, 0, 0));
2640 AddFrame(
fBottomFrame,
new TGLayoutHints(kLHintsBottom | kLHintsExpandX, 2, 2, 2, 2));
2645 fProgressBar->ShowPosition(
true,
false,
"Finding peaks for tab #%.0f");
2647 if(channelTab !=
nullptr) {
2649 for(
int i = 0; i < 20; ++i) { std::cout << std::endl; }
2650 for(
int i = 0; i < 5; ++i) {
2651 std::cout <<
"================================================================================" << std::endl;
2653 for(
int i = 0; i < 20; ++i) { std::cout << std::endl; }
2655 channelTab->Initialize(
true);
2656 channelTab->FindAllCalibratedPeaks();
2657 channelTab->Calibrate();
2660 channelTab->PrintCanvases();
2671 fNavigationGroup->Connect(
"Clicked(Int_t)",
"TSourceCalibration",
this,
"Navigate(Int_t)");
2672 fFittingGroup->Connect(
"Clicked(Int_t)",
"TSourceCalibration",
this,
"Fitting(Int_t)");
2673 fTab->Connect(
"Selected(Int_t)",
"TSourceCalibration",
this,
"SelectedTab(Int_t)");
2676 if(channelTab !=
nullptr) {
2677 channelTab->MakeConnections();
2686 fFittingGroup->Disconnect(
"Clicked(Int_t)",
this,
"Fitting(Int_t)");
2687 fTab->Disconnect(
"Selected(Int_t)",
this,
"SelectedTab(Int_t)");
2689 if(channelTab !=
nullptr) {
2690 channelTab->Disconnect();
2700 int currentChannelId =
fTab->GetCurrent();
2702 int nofTabs =
fTab->GetNumberOfTabs();
2703 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; }
2707 fTab->SetTab(currentChannelId - 1);
2712 if(currentChannelId < nofTabs - 1) {
2713 fTab->SetTab(currentChannelId + 1);
2715 fTab->SetTab(currentChannelId - 1);
2718 fTab->RemoveTab(currentChannelId);
2730 fTab->SetTab(currentChannelId + 1);
2744 int currentChannelId =
fTab->GetCurrent();
2746 int nofTabs =
fTab->GetNumberOfTabs();
2747 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; }
2776 if(
id < 0) {
return; }
2783 if(
id >=
fTab->GetNumberOfTabs() - 1) {
2792 std::cout <<
"Failed to get fChannelTab[" <<
fActiveBins[id] - 1 <<
" = fActiveBins[" <<
id <<
"]-1]" <<
RESET_COLOR << std::endl;
2796 std::cout <<
"Failed to get fChannelTab[" <<
fActiveBins[id] - 1 <<
" = fActiveBins[" <<
id <<
"]-1]->SelectedSourceTab()" <<
RESET_COLOR << std::endl;
2800 std::cout <<
"Failed to get fChannelTab[" <<
fActiveBins[id] - 1 <<
" = fActiveBins[" <<
id <<
"]-1]->SelectedSourceTab()->ProjectionCanvas()" <<
RESET_COLOR << std::endl;
2804 std::cout <<
"Failed to get fChannelTab[" <<
fActiveBins[id] - 1 <<
" = fActiveBins[" <<
id <<
"]-1]->SelectedSourceTab()->ProjectionCanvas()->GetCanvas()" <<
RESET_COLOR << std::endl;
2818 int nofTabs =
fTab->GetNumberOfTabs();
2820 int maxChannel = nofTabs - 1;
2821 if(channelId >= 0) {
2822 minChannel = channelId;
2823 maxChannel = channelId;
2828 for(
int currentChannelId = maxChannel; currentChannelId >= minChannel; --currentChannelId) {
2830 if(
fVerboseLevel >
EVerbosity::kLoops) { std::cout << __PRETTY_FUNCTION__ <<
": currentChannelId " << currentChannelId <<
", actualChannelId " << actualChannelId <<
", fChannelTab.size() " <<
fChannelTab.size() <<
", fActualChannelId.size() " <<
fActualChannelId.size() <<
", nofTabs " << nofTabs << std::endl; }
2832 if(minChannel == maxChannel) {
2833 if(currentChannelId < nofTabs) {
2834 fTab->SetTab(currentChannelId + 1);
2837 fTab->SetTab(currentChannelId - 1);
2843 fTab->RemoveTab(currentChannelId);
2854 TTimer::SingleShot(
fWaitMs,
"TSourceCalibration",
this,
"HandleTimer()");
2863 auto* window =
CreateProgressbar(
"Finding current source peaks in channel #%.0f");
2872 window->CloseWindow();
2878 std::cout << __PRETTY_FUNCTION__ <<
": fChannelTab[" <<
fActiveBins[
fTab->GetCurrent()] <<
" = fActiveBins[" <<
fTab->GetCurrent() <<
"]] is a nullptr (fApplyToAll is " << (
fApplyToAll->IsDown() ?
"down" :
"up") <<
")!" << std::endl;
2890 std::cout << __PRETTY_FUNCTION__ <<
": fChannelTab[" <<
fActiveBins[
fTab->GetCurrent()] <<
" = fActiveBins[" <<
fTab->GetCurrent() <<
"]] is a nullptr!" << std::endl;
2905 std::cout << __PRETTY_FUNCTION__ <<
": fChannelTab[" << bin <<
"] is a nullptr!" << std::endl;
2909 window->CloseWindow();
2926 window->CloseWindow();
2931 std::cout << __PRETTY_FUNCTION__ <<
": fChannelTab[" <<
fActiveBins[
fTab->GetCurrent()] <<
" = fActiveBins[" <<
fTab->GetCurrent() <<
"]] is a nullptr (fApplyToAll is " << (
fApplyToAll->IsDown() ?
"down" :
"up") <<
")!" << std::endl;
2940 auto* window =
CreateProgressbar(
"Recursively removing peaks for channel #%.0f");
2949 window->CloseWindow();
2955 std::cout << __PRETTY_FUNCTION__ <<
": fChannelTab[" <<
fActiveBins[
fTab->GetCurrent()] <<
" = fActiveBins[" <<
fTab->GetCurrent() <<
"]] is a nullptr (fApplyToAll is " << (
fApplyToAll->IsDown() ?
"down" :
"up") <<
")!" << std::endl;
2963 std::ostringstream fileName;
2965 fileName << source->GetName();
2980 window->AddFrame(
fProgressBar,
new TGLayoutHints(kLHintsCenterX | kLHintsCenterY | kLHintsExpandX | kLHintsExpandY, 0, 0, 0, 0));
2981 window->CenterOnParent();
2982 window->MapSubwindows();
2983 window->MapWindow();
2984 window->Resize(window->GetDefaultSize());
2997 if(
fTab !=
nullptr) {
fTab->Print(); }
2998 std::cout <<
"TSourceCalibration all " <<
fChannelTab.size() <<
" channel tabs:" << std::endl;
3000 if(channelTab !=
nullptr) { channelTab->PrintLayout(); }
3009 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
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
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.
TGLabel * fThresholdLabel
static int fMaxIterations
Maximum iterations over combinations in Match and SmartMatch.
TGTextButton * fFindAllPeaksButton
TGHProgressBar * fProgressBar
void PrintCanvases() const
TGHButtonGroup * fNavigationGroup
TGNumberEntry * fThresholdEntry
void SetSource(Int_t windowId, Int_t entryId)
static int StatusbarHeight()
std::vector< int > fActiveBins
TGTextButton * fDiscardButton
std::vector< TNucleus * > fSource
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
double fDefaultThreshold
The default threshold used for the peak finding algorithm, can be changed later. Co-56 source needs a...
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)