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))
494 for(
auto* fit :
fFits) {
502 for(
auto* peak :
fPeaks) {
530 std::array<int, 3> parts = {35, 50, 15};
544 fProjectionCanvas->GetCanvas()->Connect(
"ProcessedEvent(Int_t,Int_t,Int_t,TObject*)",
"TSourceTab",
this,
"ProjectionStatus(Int_t,Int_t,Int_t,TObject*)");
545 fProjectionCanvas->Connect(
"ProcessedEvent(Event_t*)",
"TSourceTab",
this,
"ProjectionStatus(Event_t*)");
551 fProjectionCanvas->Disconnect(
"ProcessedEvent(Event_t*)",
this,
"ProjectionStatus(Event_t*)");
552 fProjectionCanvas->GetCanvas()->Disconnect(
"ProcessedEvent(Int_t,Int_t,Int_t,TObject*)",
this,
"ProjectionStatus(Int_t,Int_t,Int_t,TObject*)");
570 if(event->fType == kEnterNotify) {
572 std::cout <<
"Entered source tab => changing gPad from " << gPad->GetName();
576 std::cout <<
" to " << gPad->GetName() << std::endl;
596 Status(selected->GetName(), 0);
597 Status(selected->GetObjectInfo(px, py), 1);
604 std::cout <<
fPeaks.size() <<
" peaks:";
605 for(
auto* peak :
fPeaks) {
606 std::cout <<
" " << peak->Centroid();
608 std::cout << std::endl;
610 auto* polym =
static_cast<TPolyMarker*
>(
fProjection->GetListOfFunctions()->FindObject(
"TPolyMarker"));
611 if(polym ==
nullptr) {
612 std::cerr <<
"No peaks defined yet?" << std::endl;
621 if(peak->Area() > 0) {
626 std::cout <<
"Ignoring peak at " << peak->Centroid() <<
" with negative area " << peak->Area() << std::endl;
631 std::sort(
fPeaks.begin(),
fPeaks.end(), [](
const TGauss* a,
const TGauss* b) { return a->Centroid() < b->Centroid(); });
637 Status(Form(
"%d/%d",
static_cast<int>(
fData->GetN()),
static_cast<int>(
fPeaks.size())), 2);
692 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;
708 if(obj->InheritsFrom(TRegion::Class())) {
709 auto* region =
static_cast<TRegion*
>(obj);
712 fRegions.emplace_back(std::min(region->GetX1(), region->GetX2()), std::max(region->GetX1(), region->GetX2()));
714 std::cout << obj->GetName() <<
" is not a TRegion but a " << obj->ClassName() << std::endl;
727 TList* functions =
fProjection->GetListOfFunctions();
729 std::cout <<
"Updating functions for histogram " <<
fProjection->GetName() <<
" by deleting " << functions->GetEntries() <<
" functions:" << std::endl;
730 for(
auto* obj : *functions) {
731 std::cout << obj <<
": " << obj->GetName() <<
"/" << obj->GetTitle() <<
" - " << obj->ClassName();
732 if(obj->IsA() == TF1::Class()) {
733 std::cout <<
" line color " <<
static_cast<TF1*
>(obj)->GetLineColor();
735 std::cout <<
" not a TF1";
737 std::cout << std::endl;
742 TObject* fit =
nullptr;
743 while((fit = functions->FindObject(
"gauss_total")) !=
nullptr) {
744 functions->Remove(fit);
747 for(
auto* obj :
fFits) {
748 functions->Add(obj->GetFitFunction()->Clone(
"gauss_total"));
752 functions->Add(obj->GetFitFunction()->Clone(
"gauss_total"));
755 std::cout <<
"And adding " << functions->GetEntries() <<
" functions instead:" << std::endl;
756 for(
auto* obj : *functions) {
757 std::cout << obj <<
": " << obj->GetName() <<
"/" << obj->GetTitle() <<
" - " << obj->ClassName();
758 if(obj->IsA() == TF1::Class()) {
759 std::cout <<
" line color " <<
static_cast<TF1*
>(obj)->GetLineColor();
761 std::cout <<
" not a TF1";
763 std::cout << std::endl;
766 if(!
fFits.empty() &&
fFits.front()->NumberOfPeaks() > 0 &&
fFits.back()->NumberOfPeaks() > 0) {
790 std::cout << __PRETTY_FUNCTION__ <<
": # peaks " <<
fPeaks.size() << std::endl;
798 TList* functions =
fProjection->GetListOfFunctions();
799 std::cout << functions->GetEntries() <<
" functions in projection " <<
fProjection->GetName() <<
" before clearing" << std::endl;
800 for(
auto* obj : *functions) {
801 std::cout << obj->GetName() <<
"/" << obj->GetTitle() <<
" - " << obj->ClassName() << std::endl;
807 std::vector<double> peakPos;
812 nofPeaks = spectrum.GetNPeaks();
813 peakPos.insert(peakPos.end(), spectrum.GetPositionX(), spectrum.GetPositionX() + nofPeaks);
816 fProjection->GetXaxis()->SetRangeUser(region.first, region.second);
818 int tmpNofPeaks = spectrum.GetNPeaks();
819 peakPos.insert(peakPos.end(), spectrum.GetPositionX(), spectrum.GetPositionX() + tmpNofPeaks);
820 nofPeaks += spectrum.GetNPeaks();
831 Status(Form(
"%d/%d",
static_cast<int>(
fData->GetN()), nofPeaks), 2);
841 if(calibration ==
nullptr) {
842 std::cerr << __PRETTY_FUNCTION__ <<
": provided calibration is nullptr, this function can only be called after an initial calibration has been made!" << std::endl;
855 std::cout <<
"calibration has " << calibration->GetNpar() <<
" parameters (";
856 for(
int i = 0; i < calibration->GetNpar(); ++i) {
860 std::cout << i <<
": " << calibration->GetParameter(i);
862 std::cout <<
"), if linear offset is " << calibration->Eval(0) <<
" and gain is " << calibration->Eval(1) - calibration->Eval(0) << std::endl;
863 TList* functions =
fProjection->GetListOfFunctions();
864 std::cout << functions->GetEntries() <<
" functions in projection " <<
fProjection->GetName() <<
" before clearing" << std::endl;
865 for(
auto* obj : *functions) {
866 std::cout << obj->GetName() <<
"/" << obj->GetTitle() <<
" - " << obj->ClassName() << std::endl;
871 std::map<TGauss*, std::tuple<double, double, double, double>> map;
875 std::vector<std::pair<std::tuple<double, double, double, double>,
double>> channelPos;
879 std::cout <<
"Skipping peak at " << std::get<0>(tuple) <<
" keV with intensity " << std::get<2>(tuple) <<
" below required minimum intensity " <<
TSourceCalibration::MinIntensity() << std::endl;
883 channelPos.emplace_back(tuple, calibration->GetX(std::get<0>(tuple)));
885 std::cout <<
"Set channel position for " << channelPos.size() - 1 <<
". peak to " << channelPos.back().second <<
" channels = " << std::get<0>(channelPos.back().first) <<
" keV" << std::endl;
889 for(
size_t i = 0; i < channelPos.size(); ++i) {
895 if(channelPos[i].second - lowRange < channelPos[i - 1].second + highRange) {
897 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;
899 lowRange = std::max(lowRange / 2., (channelPos[i].second - channelPos[i - 1].second) / 2.);
902 if(i + 1 < channelPos.size()) {
903 if(channelPos[i].second + highRange > channelPos[i + 1].second - lowRange) {
905 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;
907 highRange = std::min(highRange / 2., (channelPos[i + 1].second - channelPos[i].second) / 2.);
911 std::cout <<
"Trying to fit peak " << channelPos[i].second <<
" in range " << channelPos[i].second - lowRange <<
" - " << channelPos[i].second + highRange << std::endl;
914 auto* pf =
new TPeakFitter(channelPos[i].second - lowRange, channelPos[i].second + highRange);
915 auto* peak =
new TGauss(channelPos[i].second);
923 if(peak->Area() > 0) {
925 if(
Good(peak, channelPos[i].second - lowRange, channelPos[i].second + highRange)) {
928 map[peak] = channelPos[i].first;
930 std::cout <<
"Fitted peak " << channelPos[i].second - lowRange <<
" - " << channelPos[i].second + highRange <<
" -> centroid " << peak->Centroid() <<
", area " << peak->Area() << std::endl;
935 std::cout <<
"We're ignoring bad fits, and this one has position " << peak->Centroid() <<
" +- " << peak->CentroidErr() <<
", area " << peak->Area() <<
" +- " << peak->AreaErr() << std::endl;
939 std::cout <<
"Ignoring peak at " << peak->Centroid() <<
" with negative area " << peak->Area() << std::endl;
946 std::sort(
fFits.begin(),
fFits.end(), [](
const TPeakFitter* a,
const TPeakFitter* b) { return a->GetFitFunction()->GetParameter(
"centroid_0") < b->GetFitFunction()->GetParameter(
"centroid_0"); });
947 std::sort(
fBadFits.begin(),
fBadFits.end(), [](
const TPeakFitter* a,
const TPeakFitter* b) { return a->GetFitFunction()->GetParameter(
"centroid_0") < b->GetFitFunction()->GetParameter(
"centroid_0"); });
948 std::sort(
fPeaks.begin(),
fPeaks.end(), [](
const TGauss* a,
const TGauss* b) { return a->Centroid() < b->Centroid(); });
957 std::cout << __PRETTY_FUNCTION__ <<
": found " <<
fData->GetN() <<
" peaks";
958 Double_t* x =
fData->GetX();
959 Double_t* y =
fData->GetY();
960 for(
int i = 0; i <
fData->GetN(); ++i) {
961 std::cout <<
"; " << x[i] <<
" - " << y[i];
963 std::cout << std::endl;
970 std::cout <<
DCYAN <<
"Adding map with " << map.size() <<
" data points, fData = " <<
fData << std::endl;
972 if(
fData ==
nullptr) {
973 fData =
new TGraphErrors(map.size());
975 fData->Set(map.size());
977 fData->SetLineColor(2);
978 fData->SetMarkerColor(2);
980 for(
auto iter = map.begin(); iter != map.end();) {
982 auto peakPos = iter->first;
983 auto energy = std::get<0>(iter->second);
984 fData->SetPoint(i, peakPos, energy);
986 std::cout <<
"Using peak with position " << peakPos <<
", energy " << energy << std::endl;
992 std::cout <<
"Accepted " << map.size() <<
" peaks" << std::endl;
1000 std::cout <<
DCYAN <<
"Adding map with " << map.size() <<
" data points, fData = " <<
fData << std::endl;
1002 if(
fData ==
nullptr) {
1003 fData =
new TGraphErrors(map.size());
1005 fData->Set(map.size());
1007 fData->SetLineColor(2);
1008 fData->SetMarkerColor(2);
1009 if(
fFwhm ==
nullptr) {
1010 fFwhm =
new TGraphErrors(map.size());
1012 fFwhm->Set(map.size());
1014 fFwhm->SetLineColor(4);
1015 fFwhm->SetMarkerColor(4);
1017 for(
auto iter = map.begin(); iter != map.end();) {
1019 auto peakPos = iter->first->Centroid();
1020 auto peakPosErr = iter->first->CentroidErr();
1021 auto peakArea = iter->first->Area();
1022 auto peakAreaErr = iter->first->AreaErr();
1023 auto fwhm = iter->first->FWHM();
1024 auto fwhmErr = iter->first->FWHMErr();
1025 auto energy = std::get<0>(iter->second);
1026 auto energyErr = std::get<1>(iter->second);
1028 if(!
Good(iter->first)) {
1030 std::cout <<
"Dropping peak with position " << peakPos <<
" +- " << peakPosErr <<
", area " << peakArea <<
" +- " << peakAreaErr <<
", energy " << energy << std::endl;
1032 iter = map.erase(iter);
1034 std::cout <<
"Erasing peak returned iterator " << std::distance(map.begin(), iter) << std::endl;
1037 fData->SetPoint(i, peakPos, energy);
1038 fData->SetPointError(i, peakPosErr, energyErr);
1039 fFwhm->SetPoint(i, peakPos, fwhm);
1040 fFwhm->SetPointError(i, peakPosErr, fwhmErr);
1042 std::cout <<
"Using peak with position " << peakPos <<
" +- " << peakPosErr <<
", area " << peakArea <<
" +- " << peakAreaErr <<
", energy " << energy << std::endl;
1049 std::cout <<
"Accepted " << map.size() <<
" peaks" << std::endl;
1052 fData->Set(map.size());
1053 fFwhm->Set(map.size());
1057 TList* functions =
fProjection->GetListOfFunctions();
1059 std::cout << functions->GetEntries() <<
" functions in projection " <<
fProjection->GetName() << std::endl;
1060 for(
auto* obj : *functions) {
1061 std::cout << obj->GetName() <<
"/" << obj->GetTitle() <<
" - " << obj->ClassName() << std::endl;
1064 auto* polym =
static_cast<TPolyMarker*
>(functions->FindObject(
"TPolyMarker"));
1065 if(polym !=
nullptr) {
1066 double* oldX = polym->GetX();
1067 double* oldY = polym->GetY();
1068 int size = polym->GetN();
1069 std::vector<double> newX;
1070 std::vector<double> newY;
1071 std::vector<double> unusedX;
1072 std::vector<double> unusedY;
1073 for(i = 0; i < size; ++i) {
1075 for(
auto point : map) {
1077 newX.push_back(oldX[i]);
1078 newY.push_back(oldY[i]);
1084 unusedX.push_back(oldX[i]);
1085 unusedY.push_back(oldY[i]);
1088 polym->SetPolyMarker(newX.size(), newX.data(), newY.data());
1089 auto* unusedMarkers =
new TPolyMarker(unusedX.size(), unusedX.data(), unusedY.data());
1090 unusedMarkers->SetMarkerStyle(23);
1091 unusedMarkers->SetMarkerColor(16);
1092 functions->Add(unusedMarkers);
1094 std::cout <<
fProjection->GetTitle() <<
": " << size <<
" peaks founds total, " << polym->GetN() <<
" used, and " << unusedMarkers->GetN() <<
" unused" << std::endl;
1096 std::cout <<
"Used: ";
1097 for(
size_t m = 0; m < newX.size(); ++m) { std::cout << newX[m] <<
" - " << newY[m] <<
";"; }
1098 std::cout << std::endl;
1099 std::cout <<
"Unused: ";
1100 for(
size_t m = 0; m < unusedX.size(); ++m) { std::cout << unusedX[m] <<
" - " << unusedY[m] <<
";"; }
1101 std::cout << std::endl;
1104 std::cout << functions->GetEntries() <<
" functions in projection " <<
fProjection->GetTitle() << std::endl;
1105 for(
auto* obj : *functions) {
1106 std::cout << obj->GetName() <<
"/" << obj->GetTitle() <<
" - " << obj->ClassName() << std::endl;
1113 TIter iter(functions);
1114 TObject* item =
nullptr;
1115 while((item = iter.Next()) !=
nullptr) {
1116 if(item->IsA() == TF1::Class() || item->IsA() == TGauss::Class()) {
1117 double centroid = 0.;
1118 if(item->IsA() == TF1::Class()) {
1119 centroid =
static_cast<TF1*
>(item)->GetParameter(1);
1121 centroid =
static_cast<TGauss*
>(item)->Centroid();
1124 for(
auto point : map) {
1133 if(item->IsA() == TF1::Class()) {
1134 static_cast<TF1*
>(item)->SetLineColor(kGray);
1148 std::cout <<
DCYAN << __PRETTY_FUNCTION__ <<
": index " << index <<
", channel " << channel << std::endl;
1149 for(
size_t i = 0; i <
fPeaks.size() && i <
fFits.size(); ++i) {
1150 std::cout << i <<
": " <<
fPeaks[i]->Centroid() <<
" +- " <<
fPeaks[i]->CentroidErr() <<
" - " <<
fFits[i]->GetFitFunction()->GetParameter(
"centroid_0") << std::endl;
1154 if(index >=
fPeaks.size()) {
1155 std::cerr <<
"Trying to replace peak at index " << index <<
" but there are only " <<
fPeaks.size() <<
" peaks!" << std::endl;
1163 double low = channel - range;
1164 double high = channel + range;
1165 if(
fPeaks.at(index)->Centroid() < channel) {
1166 low = (
fPeaks.at(index)->Centroid() + channel) / 2.;
1168 high = (
fPeaks.at(index)->Centroid() + channel) / 2.;
1172 auto* peak =
new TGauss(channel);
1180 if(peak->Area() > 0) {
1181 if(
Good(peak, low, high)) {
1183 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;
1184 std::cout <<
"Deleting " << index <<
". peak " <<
fPeaks.at(index) << std::flush;
1186 peak->SetLineColor(
fPeaks.at(index)->GetLineColor());
1190 std::cout <<
" and setting it to " <<
fPeaks.at(index) << std::endl;
1193 std::cout <<
"Deleting " << index <<
". fit " <<
fFits.at(index) << std::flush;
1195 pf->GetFitFunction()->SetLineColor(
fFits.at(index)->GetFitFunction()->GetLineColor());
1196 delete fFits.at(index);
1199 std::cout <<
" and setting it to " <<
fFits.at(index) << std::endl;
1202 fData->SetPoint(index, peak->Centroid(),
fData->GetPointY(index));
1203 fData->SetPointError(index, peak->CentroidErr(),
fData->GetErrorY(index));
1204 fFwhm->SetPoint(index, peak->Centroid(), peak->FWHM());
1205 fFwhm->SetPointError(index, peak->CentroidErr(), peak->FWHMErr());
1207 std::cout <<
"Fitted peak " << low <<
" - " << high <<
" -> centroid " << peak->Centroid() <<
", area " << peak->Area() << std::endl;
1211 std::cout <<
"We're ignoring bad fits, and this one has position " << peak->Centroid() <<
" +- " << peak->CentroidErr() <<
", area " << peak->Area() <<
" +- " << peak->AreaErr() << std::endl;
1215 std::cout <<
"Ignoring peak at " << peak->Centroid() <<
" with negative area " << peak->Area() << std::endl;
1222 std::cout <<
DCYAN << __PRETTY_FUNCTION__ <<
": oldPoint " << oldPoint << std::endl;
1228 auto* erasedFit =
fFits.at(oldPoint);
1231 fData->RemovePoint(oldPoint);
1246 for(
size_t i = 0; i <
fPeaks.size() && i <
fFits.size(); ++i) {
1249 fPeaks[i]->SetLineColor(kRed + 2);
1250 fFits[i]->GetFitFunction()->SetLineColor(kRed);
1253 fPeaks[i]->SetLineColor(kBlue + 2);
1254 fFits[i]->GetFitFunction()->SetLineColor(kBlue);
1259 for(
size_t i = 0; i <
fBadFits.size(); ++i) {
1262 fBadFits[i]->GetFitFunction()->SetLineColor(kGray);
1265 fBadFits[i]->GetFitFunction()->SetLineColor(kGray + 2);
1275 gVirtualX->Update();
1284 std::cout <<
" is null";
1286 std::cout << std::endl;
1288 std::cout <<
"Data " <<
fData;
1289 if(
fData !=
nullptr) {
1290 std::cout <<
" = " <<
fData->GetName() <<
"/" <<
fData->GetTitle();
1292 std::cout <<
" is null";
1294 std::cout << std::endl;
1296 std::cout <<
"Fwhm " <<
fFwhm;
1297 if(
fFwhm !=
nullptr) {
1298 std::cout <<
" = " <<
fFwhm->GetName() <<
"/" <<
fFwhm->GetTitle();
1300 std::cout <<
" is null";
1302 std::cout << std::endl;
1304 std::cout <<
fFits.size() <<
" good fits:";
1305 for(
size_t i = 0; i <
fFits.size(); ++i) {
1306 std::cout <<
" " << std::setw(2) << i <<
" - " << std::setw(8) <<
fFits.at(i)->GetFitFunction()->GetParameter(
"centroid_0");
1308 std::cout << std::endl;
1310 std::cout <<
fBadFits.size() <<
" bad fits:";
1311 for(
size_t i = 0; i <
fBadFits.size(); ++i) {
1312 std::cout <<
" " << std::setw(2) << i <<
" - " << std::setw(8) <<
fBadFits.at(i)->GetFitFunction()->GetParameter(
"centroid_0");
1314 std::cout << std::endl;
1316 std::cout <<
fPeaks.size() <<
" peaks:";
1317 for(
size_t i = 0; i <
fPeaks.size(); ++i) {
1318 std::cout <<
" " << std::setw(2) << i <<
" - " << std::setw(8) <<
fPeaks.at(i)->Centroid();
1320 std::cout << std::endl;
1325 std::cout <<
"TSourceTab " <<
fSourceName <<
" projection canvas:" << std::endl;
1334 std::cout <<
"TSourceTab frame:" << std::endl;
1336 std::cout <<
"TSourceTab canvas:" << std::endl;
1338 std::cout <<
"TSourceTab status bar:" << std::endl;
1343TChannelTab::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)
1344 : 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))
1347 std::cout <<
DYELLOW <<
"========================================" << std::endl;
1348 std::cout << __PRETTY_FUNCTION__ << std::endl
1349 <<
" name = " <<
fName <<
", fData = " <<
fData << std::endl;
1350 std::cout <<
"========================================" << std::endl;
1356 std::cout <<
DYELLOW <<
"----------------------------------------" << std::endl;
1357 std::cout << __PRETTY_FUNCTION__ << std::endl
1358 <<
" channel " <<
fName <<
" done" << std::endl;
1359 std::cout <<
"----------------------------------------" << std::endl;
1394 for(
size_t source = 0; source <
fNuclei.size(); ++source) {
1399 if(*iter ==
nullptr) {
1406 fChannelFrame->AddFrame(
fSourceTab,
new TGLayoutHints(kLHintsLeft | kLHintsTop | kLHintsExpandX | kLHintsExpandY, 2, 2, 2, 2));
1413 std::array<int, 3> parts = {25, 35, 40};
1419 fFwhmFrame->AddFrame(
fFwhmCanvas,
new TGLayoutHints(kLHintsTop | kLHintsExpandX | kLHintsExpandY, 2, 2, 2, 2));
1425 fInitFrame->AddFrame(
fInitCanvas,
new TGLayoutHints(kLHintsTop | kLHintsExpandX | kLHintsExpandY, 2, 2, 2, 2));
1427 fChannelFrame->AddFrame(
fCanvasTab,
new TGLayoutHints(kLHintsRight | kLHintsTop | kLHintsExpandX | kLHintsExpandY, 2, 2, 2, 2));
1440 fLegend =
new TLegend(0.8, 0.3, 0.95, 0.3 +
static_cast<double>(
fNuclei.size()) * 0.05);
1443 fResidualPad =
new TPad(Form(
"res_%s",
fName.c_str()), Form(
"residual for %s",
fName.c_str()), 0.0, 0., 0.2, 1.);
1469 std::cout <<
DYELLOW <<
"Creating source tab " << source <<
", using fSourceCalibration " <<
fSourceCalibration << std::endl;
1471 TGCompositeFrame* tmpTab =
nullptr;
1488 std::cout <<
DYELLOW <<
"Skipping projection of source " << source <<
" = " <<
fProjections[source]->GetName() <<
", only " <<
fProjections[source]->GetEntries() <<
" entries" << std::endl;
1492 std::cout << __PRETTY_FUNCTION__ <<
" source " << source <<
" done" << std::endl;
1499 fSourceTab->Connect(
"Selected(Int_t)",
"TChannelTab",
this,
"SelectedTab(Int_t)");
1501 source->MakeConnections();
1503 fCalibrationCanvas->GetCanvas()->Connect(
"ProcessedEvent(Int_t,Int_t,Int_t,TObject*)",
"TChannelTab",
this,
"CalibrationStatus(Int_t,Int_t,Int_t,TObject*)");
1504 fCalibrationCanvas->Connect(
"ProcessedEvent(Event_t*)",
"TChannelTab",
this,
"SelectCanvas(Event_t*)");
1505 if(
fData !=
nullptr) {
1507 std::cout <<
DYELLOW << __PRETTY_FUNCTION__ <<
": connecting fData " <<
fData <<
":" << std::endl;
1510 fData->Connect(
"RemovePoint(Int_t, Int_t)",
"TChannelTab",
this,
"RemovePoint(Int_t, Int_t)");
1512 std::cerr <<
DRED <<
"Failed to create connections for the data graph fData since it hasn't been created yet!" << std::endl;
1519 fSourceTab->Disconnect(
"Selected(Int_t)",
this,
"SelectedTab(Int_t)");
1521 source->Disconnect();
1523 fCalibrationCanvas->GetCanvas()->Disconnect(
"ProcessedEvent(Int_t,Int_t,Int_t,TObject*)",
this,
"CalibrationStatus(Int_t,Int_t,Int_t,TObject*)");
1524 fData->Disconnect(
"RemovePoint(Int_t, Int_t)",
this,
"RemovePoint(Int_t, Int_t)");
1553 if(event->fType == kEnterNotify) {
1555 std::cout <<
"Entered channel tab => changing gPad from " << gPad->GetName();
1559 std::cout <<
" to " << gPad->GetName() << std::endl;
1567 std::cout <<
DCYAN << __PRETTY_FUNCTION__ <<
": oldGraph " << oldGraph <<
", oldPoint " << oldPoint << std::endl;
1569 if(0 <= oldGraph && oldGraph <
static_cast<int>(
fSources.size())) {
1571 fSources[oldGraph]->RemovePoint(oldPoint);
1574 std::cout <<
"Can't remove negative point " << oldPoint <<
" from graph " << oldGraph << std::endl;
1576 std::cout <<
"Graph the point was removed from was " << oldGraph <<
", but we only have " <<
fSources.size() <<
" source tabs?" << std::endl;
1595 if(event == kKeyPress) {
1599 if(canvas ==
nullptr) {
1603 auto* pad = canvas->GetSelectedPad();
1604 if(pad ==
nullptr) {
1612 fChannelStatusBar->SetText(Form(
"x = %f, y = %f", pad->AbsPixeltoX(px), pad->AbsPixeltoY(py)), 1);
1620 if(
fData ==
nullptr) {
1626 fData->SetName(Form(
"data%s",
fName.c_str()));
1628 std::cout <<
"set name of fData using " <<
fName.c_str() <<
": " <<
fData->GetName() << std::endl;
1629 std::cout <<
"fData " <<
fData <<
": " << (
fData !=
nullptr ?
fData->
GetN() : -2) <<
" data points after creation" << std::endl;
1630 std::cout <<
"Looping over " <<
fNuclei.size() <<
" sources, fSources.size() = " <<
fSources.size() << std::endl;
1632 for(
size_t source = 0; source <
fNuclei.size() && source <
fSources.size(); ++source) {
1642 std::cout <<
"fData " <<
fData <<
": " << (
fData !=
nullptr ?
fData->
GetN() : -1) <<
" data points after adding " <<
fNuclei.size() <<
" graphs" << std::endl;
1651 if(
fFwhm ==
nullptr) {
1657 fFwhm->SetName(Form(
"fwhm%s",
fName.c_str()));
1659 std::cout <<
"set name of fFwhm using " <<
fName.c_str() <<
": " <<
fFwhm->GetName() << std::endl;
1660 std::cout <<
"fFwhm " <<
fFwhm <<
": " << (
fFwhm !=
nullptr ?
fFwhm->
GetN() : -2) <<
" data points after creation" << std::endl;
1661 std::cout <<
"Looping over " <<
fNuclei.size() <<
" sources, fSources.size() = " <<
fSources.size() << std::endl;
1663 for(
size_t source = 0; source <
fNuclei.size() && source <
fSources.size(); ++source) {
1664 if(
fSources[source]->Fwhm() !=
nullptr &&
fSources[source]->Fwhm()->GetN() > 0) {
1673 std::cout <<
"fFwhm " <<
fFwhm <<
": " << (
fFwhm !=
nullptr ?
fFwhm->
GetN() : -1) <<
" data points after adding " <<
fNuclei.size() <<
" graphs" << std::endl;
1689 TF1* calibration =
new TF1(
"fitfunction",
::Polynomial, 0., 10000., degree + 2);
1690 calibration->FixParameter(0, degree);
1693 if(
fData !=
nullptr) {
1694 std::cout <<
fData->
GetN() <<
" data points being fit, ";
1698 calibration->GetRange(min, max);
1699 std::cout <<
"range " << min <<
" - " << max << std::endl;
1702 TString text = Form(
"%.6f + %.6f*x", calibration->GetParameter(1), calibration->GetParameter(2));
1703 for(
int i = 2; i <= degree; ++i) {
1704 text.Append(Form(
" + %.6f*x^%d", calibration->GetParameter(i + 1), i));
1724 fChi2Label =
new TPaveText(left, bottom, right, top);
1733 fChi2Label->AddText(Form(
"#chi^{2}/NDF = %f", calibration->GetChisquare() / calibration->GetNDF()));
1737 std::cout <<
"fChi2Label set to:" << std::endl;
1739 std::cout <<
"Text size " <<
fChi2Label->GetTextSize() << std::endl;
1742 fInfoLabel =
new TPaveText(0, 0.95, 1., 1.,
"NDCNB");
1767 calibration->GetRange(min, max);
1768 std::cout <<
DYELLOW <<
"calibration has range " << min <<
" - " << max;
1771 std::cout <<
", fit function has range " << min <<
" - " << max;
1773 std::cout << std::endl;
1788 if(
fData ==
nullptr) {
1789 std::cout <<
"No longer have a data for channel " <<
Name() <<
"?" << std::endl;
1794 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;
1799 std::cout <<
"Recursively removed all data points for channel " <<
Name() << std::endl;
1807 if(std::abs(*maxElement) < maxResidual) {
1829 std::stringstream str;
1830 str << std::hex <<
fName;
1835 if(calibration ==
nullptr) {
1836 std::cout <<
"Failed to find calibration in fData" << std::endl;
1840 std::vector<Float_t> parameters;
1841 for(
int i = 0; i <= calibration->GetParameter(0); ++i) {
1842 parameters.push_back(
static_cast<Float_t
>(calibration->GetParameter(i + 1)));
1845 if(channel ==
nullptr) {
1846 std::cerr <<
"Failed to get channel for address " <<
hex(address, 4) << std::endl;
1856 for(
int i = 0; i <
fData->
GetN(); ++i) {
1870 std::cout <<
DYELLOW <<
"Rough calibration in source tab:" << std::endl;
1873 source->InitialCalibration(force);
1882 std::cout <<
"Cloned data " <<
fData->GetName() <<
" to " <<
fInit->GetName() <<
":" << std::endl;
1885 auto* oldPad = gPad;
1897 fCalLabel =
new TPaveText(left, bottom, right, top);
1904 std::stringstream str;
1908 str <<
"Unknown fit function with " <<
fInit->
FitFunction()->GetNpar() <<
" parameters";
1911 std::cout <<
"Created label text \"" << str.str() <<
"\"" << std::endl;
1926 for(
int tab = 0; tab <
fSourceTab->GetNumberOfTabs(); ++tab) {
1927 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;
1941 std::cout <<
DYELLOW <<
"Finding calibrated peaks in all source tabs" << std::endl;
1945 std::cout <<
DYELLOW <<
"Finding calibrated peaks in source tab " << source->SourceName() << std::endl;
1952 std::cout <<
DYELLOW <<
"Done finding calibrated peaks in all source tabs" << std::endl;
1971 fData->Write(Form(
"calGraph_%s",
fName.c_str()), TObject::kOverwrite);
1972 fFwhm->Write(Form(
"fwhm_%s",
fName.c_str()), TObject::kOverwrite);
1980 TH1* hist1 =
nullptr;
1981 for(
const auto&& obj : *(gPad->GetListOfPrimitives())) {
1982 if(obj->InheritsFrom(TGraph::Class())) {
1983 hist1 =
static_cast<TGraph*
>(obj)->GetHistogram();
1987 if(hist1 ==
nullptr) {
1988 std::cout <<
"ZoomX - Failed to find histogram for pad " << gPad->GetName() << std::endl;
1994 std::string padName = gPad->GetName();
1995 std::string baseName = padName.substr(0, 3);
1996 std::string channelName = padName.substr(4);
1999 std::string newName;
2000 if(baseName ==
"cal") {
2001 newName =
"res_" + channelName;
2002 }
else if(baseName ==
"res") {
2003 newName =
"cal_" + channelName;
2005 std::cout <<
"Unknown combination of pad " << gPad->GetName() <<
" and histogram " << hist1->GetName() << std::endl;
2008 auto* newObj = gPad->GetCanvas()->FindObject(newName.c_str());
2009 if(newObj ==
nullptr) {
2010 std::cout <<
"Failed to find " << newName << std::endl;
2014 if(newObj->IsA() != TPad::Class()) {
2015 std::cout << newObj <<
" = " << newObj->GetName() <<
", " << newObj->GetTitle() <<
" is a " << newObj->ClassName() <<
" not a TPad" << std::endl;
2018 auto* pad2 =
static_cast<TPad*
>(newObj);
2019 if(pad2 ==
nullptr) {
2020 std::cout <<
"Failed to find partner pad " << newName << std::endl;
2024 TH1* hist2 =
nullptr;
2025 for(
const auto&& obj : *(pad2->GetListOfPrimitives())) {
2026 if(obj->InheritsFrom(TGraph::Class())) {
2027 hist2 =
static_cast<TGraph*
>(obj)->GetHistogram();
2031 if(hist2 ==
nullptr) {
2032 std::cout <<
"ZoomX - Failed to find histogram for partner pad " << newName << std::endl;
2037 TAxis* axis1 = hist1->GetXaxis();
2038 Int_t binmin = axis1->GetFirst();
2039 Int_t binmax = axis1->GetLast();
2040 Double_t xmin = axis1->GetBinLowEdge(binmin);
2041 Double_t xmax = axis1->GetBinLowEdge(binmax);
2042 TAxis* axis2 = hist2->GetXaxis();
2043 Int_t newmin = axis2->FindBin(xmin);
2044 Int_t newmax = axis2->FindBin(xmax);
2045 axis2->SetRange(newmin, newmax);
2054 TH1* hist1 =
nullptr;
2055 for(
const auto&& obj : *(gPad->GetListOfPrimitives())) {
2056 if(obj->InheritsFrom(TGraph::Class())) {
2057 hist1 =
static_cast<TGraph*
>(obj)->GetHistogram();
2061 if(hist1 ==
nullptr) {
2062 std::cout <<
"ZoomY - Failed to find histogram for pad " << gPad->GetName() << std::endl;
2068 std::string padName = gPad->GetName();
2069 std::string baseName = padName.substr(0, 3);
2070 std::string channelName = padName.substr(4);
2073 std::string newName;
2074 if(baseName ==
"cal") {
2075 newName =
"res_" + channelName;
2076 }
else if(baseName ==
"res") {
2077 newName =
"cal_" + channelName;
2079 std::cout <<
"Unknown combination of pad " << gPad->GetName() <<
" and histogram " << hist1->GetName() << std::endl;
2082 auto* newObj = gPad->GetCanvas()->FindObject(newName.c_str());
2083 if(newObj ==
nullptr) {
2084 std::cout <<
"Failed to find " << newName << std::endl;
2088 if(newObj->IsA() != TPad::Class()) {
2089 std::cout << newObj <<
" = " << newObj->GetName() <<
", " << newObj->GetTitle() <<
" is a " << newObj->ClassName() <<
" not a TPad" << std::endl;
2092 auto* pad2 =
static_cast<TPad*
>(newObj);
2093 if(pad2 ==
nullptr) {
2094 std::cout <<
"Failed to find partner pad " << newName << std::endl;
2098 TH1* hist2 =
nullptr;
2099 for(
const auto&& obj : *(pad2->GetListOfPrimitives())) {
2100 if(obj->InheritsFrom(TGraph::Class())) {
2101 hist2 =
static_cast<TGraph*
>(obj)->GetHistogram();
2102 if(obj->IsA() == TCalibrationGraphSet::Class()) {
2108 if(hist2 ==
nullptr) {
2109 std::cout <<
"ZoomY - Failed to find histogram for partner pad " << newName << std::endl;
2114 hist2->SetMinimum(hist1->GetMinimum());
2115 hist2->SetMaximum(hist1->GetMaximum());
2123 std::cout <<
"TChannelTab " <<
Name() <<
" calibration canvas:" << std::endl;
2128 std::cout <<
"TChannelTab fwhm canvas:" << std::endl;
2130 for(
auto* obj : *(
fFwhmCanvas->GetCanvas()->GetListOfPrimitives())) {
2134 sourceTab->PrintCanvases();
2140 std::cout <<
"TChannelTab frame:" << std::endl;
2142 std::cout <<
"TChannelTab canvas:" << std::endl;
2144 std::cout <<
"TChannelTab status bar:" << std::endl;
2147 sourceTab->PrintLayout();
2170 : TGMainFrame(nullptr, 2 * fPanelWidth, fPanelHeight + 2 * fStatusbarHeight), fDefaultSigma(sigma), fDefaultThreshold(threshold), fDefaultDegree(degree)
2172 TH1::AddDirectory(
false);
2175 va_start(args, count);
2176 for(
int i = 0; i < count; ++i) {
2177 fMatrices.push_back(va_arg(args, TH2*));
2179 std::cout <<
"Error, got nullptr as matrix input?" << std::endl;
2185 std::cout <<
DGREEN << __PRETTY_FUNCTION__ <<
": verbose level " <<
static_cast<std::underlying_type_t<EVerbosity>
>(
fVerboseLevel) << std::endl
2186 <<
"using " << count <<
"/" <<
fMatrices.size() <<
" matrices:" << std::endl;
2188 std::cout <<
mat << std::flush <<
" = " <<
mat->GetName() << std::endl;
2193 gErrorIgnoreLevel = kError;
2194 gPrintViaErrorHandler =
true;
2198 std::cout <<
"Starting redirect to " <<
fLogFile << std::endl;
2204 std::map<int, int> channelToIndex;
2205 for(
int bin = 1; bin <=
fMatrices[0]->GetNbinsX(); ++bin) {
2218 for(
size_t i = 1; i <
fMatrices.size(); ++i) {
2220 for(
int bin = 1; bin <=
fMatrices[i]->GetNbinsX(); ++bin) {
2223 if(channelToIndex.find(bin) == channelToIndex.end() || tmpBins != channelToIndex[bin]) {
2224 std::ostringstream error;
2225 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;
2226 throw std::invalid_argument(error.str());
2228 if(strcmp(
fMatrices[0]->GetXaxis()->GetBinLabel(bin),
fMatrices[i]->GetXaxis()->GetBinLabel(bin)) != 0) {
2229 std::ostringstream error;
2230 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;
2231 throw std::invalid_argument(error.str());
2235 if(channelToIndex.find(bin) != channelToIndex.end()) {
2236 std::ostringstream error;
2237 error <<
"Mismatch in " << i <<
". matrix (" <<
fMatrices[i]->GetName() <<
"), bin " << bin <<
" is empty, but should be " << channelToIndex[bin] <<
". filled bin" << std::endl;
2238 throw std::invalid_argument(error.str());
2246 fOutput =
new TFile(
"TSourceCalibration.root",
"recreate");
2248 throw std::runtime_error(
"Unable to open output file \"TSourceCalibration.root\"!");
2256 SetWindowName(
"SourceCalibration");
2262 Resize(GetDefaultSize());
2282 auto* layoutManager =
new TGTableLayout(
this,
fMatrices.size() + 1, 2,
true, 5);
2284 SetLayoutManager(layoutManager);
2299 std::string name =
fMatrices[i]->GetName();
2300 std::transform(name.begin(), name.end(), name.begin(), ::tolower);
2302#if __cplusplus >= 201703L
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].emplace_back(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
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
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)