9#if __cplusplus >= 201703L
14#include "TGTableLayout.h"
16#include "TLinearFitter.h"
19#include "TPolyMarker.h"
29std::map<GPeak*, std::tuple<double, double, double, double>>
Match(std::vector<GPeak*> peaks, std::vector<std::tuple<double, double, double, double>> sources,
TSourceTab* sourceTab)
36 std::map<GPeak*, std::tuple<double, double, double, double>> result;
37 std::sort(peaks.begin(), peaks.end());
38 std::sort(sources.begin(), sources.end());
40 auto maxSize = peaks.size();
41 if(sources.size() > maxSize) { maxSize = sources.size(); }
46 TLinearFitter fitter(1,
"1 ++ x");
49 std::vector<double> peakValues(peaks.size());
50 for(
size_t i = 0; i < peaks.size(); ++i) { peakValues[i] = peaks[i]->Centroid(); }
51 std::vector<double> sourceValues(sources.size());
52 for(
size_t i = 0; i < sources.size(); ++i) { sourceValues[i] = std::get<0>(sources[i]); }
53 std::map<double, double> tmpMap;
55 for(
size_t num_data_points = peakValues.size(); num_data_points > 0; num_data_points--) {
57 double best_chi2 = DBL_MAX;
59 for(
auto peak_values :
combinations(peakValues, num_data_points)) {
61 peak_values.push_back(0);
62 for(
auto source_values :
combinations(sourceValues, num_data_points)) {
63 source_values.push_back(0);
65 if(peakValues.size() > 3) {
66 double pratio = peak_values.front() / peak_values.at(peak_values.size() - 2);
67 double sratio = source_values.front() / source_values.at(source_values.size() - 2);
69 if(std::abs(pratio - sratio) > 0.02) {
77 fitter.AssignData(source_values.size(), 1, peak_values.data(), source_values.data());
80 if(fitter.GetChisquare() < best_chi2) {
82 for(
size_t i = 0; i < num_data_points; i++) {
83 tmpMap[peak_values[i]] = source_values[i];
85 best_chi2 = fitter.GetChisquare();
88 sourceTab->
Status(Form(
"%zu/%zu - %zu - %d", num_data_points, peakValues.size(), maxSize, iteration), 1);
94 if(tmpMap.size() > 2) {
95 std::vector<double> peak_values;
96 std::vector<double> source_values;
97 for(
auto& item : tmpMap) {
98 peak_values.push_back(item.first);
99 source_values.push_back(item.second);
102 for(
size_t skipped_point = 0; skipped_point < source_values.size(); skipped_point++) {
103 std::swap(peak_values[skipped_point], peak_values.back());
104 std::swap(source_values[skipped_point], source_values.back());
106 fitter.ClearPoints();
107 fitter.AssignData(source_values.size() - 1, 1, peak_values.data(), source_values.data());
110 if(std::abs(fitter.GetParameter(0)) > 10) {
112 std::cout << fitter.GetParameter(0) <<
" too big, clearing map with " << tmpMap.size() <<
" points: ";
113 for(
auto iter : tmpMap) { std::cout << iter.first <<
" - " << iter.second <<
"; "; }
114 std::cout << std::endl;
120 std::swap(peak_values[skipped_point], peak_values.back());
121 std::swap(source_values[skipped_point], source_values.back());
126 if(!tmpMap.empty()) {
127 for(
auto iter : tmpMap) {
128 result[*(std::find_if(peaks.begin(), peaks.end(), [&iter](
auto& item) { return iter.first == item->Centroid(); }))] =
129 *(std::find_if(sources.begin(), sources.end(), [&iter](
auto& item) { return iter.second == std::get<0>(item); }));
135 std::cout <<
"Matched " << num_data_points <<
" data points from " << peaks.size() <<
" peaks with " << sources.size() <<
" source energies" << std::endl;
136 std::cout <<
"Returning map with " << result.size() <<
" points: ";
137 for(
auto iter : result) { std::cout << iter.first->Centroid() <<
" - " << std::get<0>(iter.second) <<
"; "; }
138 std::cout << std::endl;
142 sourceTab->
Status(Form(
"%zu/%zu - %zu", num_data_points, peakValues.size(), maxSize), 1);
148std::map<GPeak*, std::tuple<double, double, double, double>>
SmartMatch(std::vector<GPeak*> peaks, std::vector<std::tuple<double, double, double, double>> sources,
TSourceTab* sourceTab)
155 for(
size_t i = 0; i < peaks.size() || i < sources.size(); ++i) {
156 std::cout << i <<
".: " << std::setw(8);
157 if(i < peaks.size()) {
158 std::cout << peaks[i]->Centroid();
162 std::cout <<
" - " << std::setw(8);
163 if(i < sources.size()) {
164 std::cout << std::get<0>(sources[i]);
168 std::cout << std::endl;
172 std::map<GPeak*, std::tuple<double, double, double, double>> result;
173 std::sort(peaks.begin(), peaks.end(), [](
const GPeak* a,
const GPeak* b) { return a->Centroid() < b->Centroid(); });
174 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); });
176 auto maxSize = peaks.size();
177 if(sources.size() > maxSize) { maxSize = sources.size(); }
182 TLinearFitter fitter(1,
"1 ++ x");
185 std::vector<double> peakValues(peaks.size());
186 for(
size_t i = 0; i < peaks.size(); ++i) { peakValues[i] = peaks[i]->Centroid(); }
187 std::vector<double> sourceValues(sources.size());
188 std::map<double, double> tmpMap;
190 for(
size_t num_data_points = std::min(peakValues.size(), sourceValues.size()); num_data_points > 0; num_data_points--) {
192 double best_chi2 = DBL_MAX;
194 for(
auto peak_values :
combinations(peakValues, num_data_points)) {
196 peak_values.push_back(0);
200 sourceValues.resize(num_data_points);
201 for(
size_t i = 0; i < sourceValues.size(); ++i) { sourceValues[i] = std::get<0>(sources[i]); }
202 std::sort(sourceValues.begin(), sourceValues.end());
203 sourceValues.push_back(0);
206 for(
size_t i = 0; i < peak_values.size(); ++i) {
207 std::cout << i <<
".: " << std::setw(8) << peak_values[i] <<
" - " << std::setw(8) << sourceValues[i] << std::endl;
210 if(peakValues.size() > 3) {
211 double pratio = peak_values.front() / peak_values.at(peak_values.size() - 2);
212 double sratio = sourceValues.front() / sourceValues.at(sourceValues.size() - 2);
214 if(std::abs(pratio - sratio) > 0.02) {
220 fitter.ClearPoints();
221 fitter.AssignData(sourceValues.size(), 1, peak_values.data(), sourceValues.data());
224 if(fitter.GetChisquare() < best_chi2) {
226 for(
size_t i = 0; i < num_data_points; i++) {
227 tmpMap[peak_values[i]] = sourceValues[i];
229 best_chi2 = fitter.GetChisquare();
231 sourceTab->
Status(Form(
"%zu/%zu - %zu - %d", num_data_points, peakValues.size(), maxSize, iteration), 1);
237 if(tmpMap.size() > 2) {
238 std::vector<double> peak_values;
239 std::vector<double> source_values;
240 for(
auto& item : tmpMap) {
241 peak_values.push_back(item.first);
242 source_values.push_back(item.second);
245 for(
size_t skipped_point = 0; skipped_point < source_values.size(); skipped_point++) {
246 std::swap(peak_values[skipped_point], peak_values.back());
247 std::swap(source_values[skipped_point], source_values.back());
249 fitter.ClearPoints();
250 fitter.AssignData(source_values.size() - 1, 1, peak_values.data(), source_values.data());
253 if(std::abs(fitter.GetParameter(0)) > 10) {
255 std::cout << fitter.GetParameter(0) <<
" too big an offset, clearing map with " << tmpMap.size() <<
" points: ";
256 for(
auto iter : tmpMap) { std::cout << iter.first <<
" - " << iter.second <<
"; "; }
257 std::cout << std::endl;
263 std::swap(peak_values[skipped_point], peak_values.back());
264 std::swap(source_values[skipped_point], source_values.back());
269 if(!tmpMap.empty()) {
273 for(
auto iter : tmpMap) {
274 result[*(std::find_if(peaks.begin(), peaks.end(), [&iter](
auto& item) { return iter.first == item->Centroid(); }))] =
275 *(std::find_if(sources.begin(), sources.end(), [&iter](
auto& item) { return iter.second == std::get<0>(item); }));
278 std::cout <<
"Smart matched " << num_data_points <<
" data points from " << peaks.size() <<
" peaks with " << sources.size() <<
" source energies" << std::endl;
279 std::cout <<
"Returning map with " << result.size() <<
" points: ";
280 for(
auto iter : result) { std::cout << iter.first->Centroid() <<
" - " << std::get<0>(iter.second) <<
"; "; }
281 std::cout << std::endl;
285 sourceTab->
Status(Form(
"%zu/%zu - %zu", num_data_points, peakValues.size(), maxSize), 1);
293 double result = par[1];
294 for(
int i = 1; i <= par[0]; ++i) {
295 result += par[i + 1] * TMath::Power(x[0], i);
302 return (matrix->Integral(bin, bin, 1, matrix->GetNbinsY()) > 1000);
306TSourceTab::TSourceTab(
TChannelTab* parent, TGCompositeFrame* frame,
GH1D* projection,
const double& sigma,
const double& threshold,
const double& peakRatio, std::vector<std::tuple<double, double, double, double>> sourceEnergy)
307 : fParent(parent), fSourceFrame(frame), fProjection(projection), fSigma(sigma), fThreshold(threshold), fPeakRatio(peakRatio), fSourceEnergy(std::move(sourceEnergy))
332 for(
auto* peak :
fPeaks) {
348 std::array<int, 3> parts = {35, 50, 15};
356 fProjectionCanvas->Connect(
"ProcessedEvent(Event_t*)",
"TSourceTab",
this,
"ProjectionStatus(Event_t*)");
357 fProjectionCanvas->GetCanvas()->Connect(
"ProcessedEvent(Int_t,Int_t,Int_t,TObject*)",
"TSourceTab",
this,
"ProjectionStatus(Int_t,Int_t,Int_t,TObject*)");
362 fProjectionCanvas->Disconnect(
"ProcessedEvent(Event_t*)",
this,
"ProjectionStatus(Event_t*)");
363 fProjectionCanvas->GetCanvas()->Disconnect(
"ProcessedEvent(Int_t,Int_t,Int_t,TObject*)",
this,
"ProjectionStatus(Int_t,Int_t,Int_t,TObject*)");
376 std::cout << __PRETTY_FUNCTION__ <<
": code " <<
event->fCode <<
", count " <<
event->fCount <<
", state " <<
event->fState <<
", type " <<
event->fType << std::endl;
377 if(event->fType == kClientMessage) {
378 std::cout <<
"Client message: " <<
event->fUser[0] <<
", " <<
event->fUser[1] <<
", " <<
event->fUser[2] << std::endl;
381 if(event->fType == kEnterNotify) {
383 std::cout <<
"Entered source tab => changing gPad from " << gPad->GetName();
387 std::cout <<
" to " << gPad->GetName() << std::endl;
407 Status(selected->GetName(), 0);
408 Status(selected->GetObjectInfo(px, py), 1);
414 auto* polym =
static_cast<TPolyMarker*
>(
fProjection->GetListOfFunctions()->FindObject(
"TPolyMarker"));
415 if(polym ==
nullptr) {
416 std::cerr <<
"No peaks defined yet?" << std::endl;
420 double range = 4 *
fSigma;
426 if(peak->
Area() > 0) {
430 std::cout <<
"Ignoring peak at " << peak->
Centroid() <<
" with negative area " << peak->
Area() << std::endl;
445 Status(Form(
"%d/%d",
static_cast<int>(
fData->GetN()),
static_cast<int>(
fPeaks.size())), 2);
486 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;
502 if(obj->InheritsFrom(TRegion::Class())) {
503 auto* region =
static_cast<TRegion*
>(obj);
506 fRegions.emplace_back(std::min(region->GetX1(), region->GetX2()), std::max(region->GetX1(), region->GetX2()));
508 std::cout << obj->GetName() <<
" is not a TRegion but a " << obj->ClassName() << std::endl;
513void TSourceTab::FindPeaks(
const double& sigma,
const double& threshold,
const double& peakRatio,
const bool& force,
const bool& fast)
526 std::cout << __PRETTY_FUNCTION__ <<
": # peaks " <<
fPeaks.size() <<
", sigma (" << sigma <<
"/" <<
fSigma <<
"), or threshold (" << threshold <<
"/" <<
fThreshold <<
") have changed?" << std::endl;
534 TList* functions =
fProjection->GetListOfFunctions();
535 std::cout << functions->GetEntries() <<
" functions in projection " <<
fProjection->GetName() <<
" before clearing" << std::endl;
536 for(
auto* obj : *functions) {
537 std::cout << obj->GetName() <<
"/" << obj->GetTitle() <<
" - " << obj->ClassName() << std::endl;
543 std::vector<double> peakPos;
548 nofPeaks = spectrum.GetNPeaks();
554 peakPos.insert(peakPos.end(), spectrum.GetPositionX(), spectrum.GetPositionX() + nofPeaks);
557 fProjection->GetXaxis()->SetRangeUser(region.first, region.second);
559 int tmpNofPeaks = spectrum.GetNPeaks();
565 peakPos.insert(peakPos.end(), spectrum.GetPositionX(), spectrum.GetPositionX() + tmpNofPeaks);
566 nofPeaks += spectrum.GetNPeaks();
573 for(
int i = 0; i < nofPeaks; i++) {
576 GPeak* peak =
nullptr;
583 if(peak->
Area() > 0) {
586 std::cout <<
"Fitted peak " << peakPos[i] - range <<
" - " << peakPos[i] + range <<
" -> centroid " << peak->
Centroid() <<
", area " << peak->
Area() << std::endl;
589 std::cout <<
"Ignoring peak at " << peak->
Centroid() <<
" with negative area " << peak->
Area() << std::endl;
614 Status(Form(
"%d/%d",
static_cast<int>(
fData->GetN()), nofPeaks), 2);
617 std::cout << __PRETTY_FUNCTION__ <<
": found " <<
fData->GetN() <<
" peaks";
618 Double_t* x =
fData->GetX();
619 Double_t* y =
fData->GetY();
620 for(
int i = 0; i <
fData->GetN(); ++i) {
621 std::cout <<
" - " << x[i] <<
", " << y[i];
623 std::cout << std::endl;
630 std::cout <<
DCYAN <<
"Adding map with " << map.size() <<
" data points, fData = " <<
fData << std::endl;
632 if(
fData ==
nullptr) {
633 fData =
new TGraphErrors(map.size());
635 fData->Set(map.size());
637 fData->SetLineColor(2);
638 fData->SetMarkerColor(2);
639 if(
fFwhm ==
nullptr) {
640 fFwhm =
new TGraphErrors(map.size());
642 fFwhm->Set(map.size());
644 fFwhm->SetLineColor(4);
645 fFwhm->SetMarkerColor(4);
647 for(
auto iter = map.begin(); iter != map.end();) {
649 auto peakPos = iter->first->Centroid();
650 auto peakPosErr = iter->first->CentroidErr();
651 auto peakArea = iter->first->Area();
652 auto peakAreaErr = iter->first->AreaErr();
653 auto fwhm = iter->first->FWHM();
654 auto fwhmErr = iter->first->FWHMErr();
655 auto energy = std::get<0>(iter->second);
656 auto energyErr = std::get<1>(iter->second);
658 if(peakPosErr > 0.1 * peakPos || peakAreaErr > peakArea || std::isnan(peakPosErr) || std::isnan(peakAreaErr)) {
660 std::cout <<
"Dropping peak with position " << peakPos <<
" +- " << peakPosErr <<
", area " << peakArea <<
" +- " << peakAreaErr <<
", energy " << energy << std::endl;
662 iter = map.erase(iter);
664 std::cout <<
"Erasing peak returned iterator " << std::distance(map.begin(), iter) << std::endl;
667 fData->SetPoint(i, peakPos, energy);
668 fData->SetPointError(i, peakPosErr, energyErr);
669 fFwhm->SetPoint(i, peakPos, fwhm);
670 fFwhm->SetPointError(i, peakPosErr, fwhmErr);
672 std::cout <<
"Using peak with position " << peakPos <<
" +- " << peakPosErr <<
", area " << peakArea <<
" +- " << peakAreaErr <<
", energy " << energy << std::endl;
679 std::cout <<
"Accepted " << map.size() <<
" peaks" << std::endl;
682 fData->Set(map.size());
683 fFwhm->Set(map.size());
685 TList* functions =
fProjection->GetListOfFunctions();
687 std::cout << functions->GetEntries() <<
" functions in projection " <<
fProjection->GetTitle() << std::endl;
688 for(
auto* obj : *functions) {
689 std::cout << obj->GetName() <<
"/" << obj->GetTitle() <<
" - " << obj->ClassName() << std::endl;
692 auto* polym =
static_cast<TPolyMarker*
>(functions->FindObject(
"TPolyMarker"));
693 if(polym !=
nullptr) {
694 double* oldX = polym->GetX();
695 double* oldY = polym->GetY();
696 int size = polym->GetN();
697 std::vector<double> newX;
698 std::vector<double> newY;
699 std::vector<double> unusedX;
700 std::vector<double> unusedY;
701 for(i = 0; i < size; ++i) {
703 for(
auto point : map) {
704 if(TMath::Abs(oldX[i] - point.first->Centroid()) <
fSigma) {
705 newX.push_back(oldX[i]);
706 newY.push_back(oldY[i]);
712 unusedX.push_back(oldX[i]);
713 unusedY.push_back(oldY[i]);
716 polym->SetPolyMarker(newX.size(), newX.data(), newY.data());
717 auto* unusedMarkers =
new TPolyMarker(unusedX.size(), unusedX.data(), unusedY.data());
718 unusedMarkers->SetMarkerStyle(23);
719 unusedMarkers->SetMarkerColor(16);
720 functions->Add(unusedMarkers);
722 std::cout <<
fProjection->GetTitle() <<
": " << size <<
" peaks founds total, " << polym->GetN() <<
" used, and " << unusedMarkers->GetN() <<
" unused" << std::endl;
724 std::cout <<
"Used: ";
725 for(
size_t m = 0; m < newX.size(); ++m) { std::cout << newX[m] <<
" - " << newY[m] <<
";"; }
726 std::cout << std::endl;
727 std::cout <<
"Unused: ";
728 for(
size_t m = 0; m < unusedX.size(); ++m) { std::cout << unusedX[m] <<
" - " << unusedY[m] <<
";"; }
729 std::cout << std::endl;
732 std::cout << functions->GetEntries() <<
" functions in projection " <<
fProjection->GetTitle() << std::endl;
733 for(
auto* obj : *functions) {
734 std::cout << obj->GetName() <<
"/" << obj->GetTitle() <<
" - " << obj->ClassName() << std::endl;
741 TIter iter(functions);
742 TObject* item =
nullptr;
743 while((item = iter.Next()) !=
nullptr) {
744 if(item->IsA() == TF1::Class() || item->IsA() == GPeak::Class()) {
745 double centroid = 0.;
746 if(item->IsA() == TF1::Class()) {
747 centroid =
static_cast<TF1*
>(item)->GetParameter(1);
749 centroid =
static_cast<GPeak*
>(item)->Centroid();
752 for(
auto point : map) {
753 if(TMath::Abs(centroid - point.first->Centroid()) <
fSigma) {
760 functions->Remove(item);
769 std::cout <<
DCYAN << __PRETTY_FUNCTION__ <<
": px " << px <<
", py " << py << std::endl;
773 for(
auto it =
fPeaks.begin(); it !=
fPeaks.end(); ++it) {
774 if(TMath::Abs((*it)->Centroid() - px) <
fSigma) {
776 std::cout <<
DCYAN <<
"Erasing peak " << TMath::Abs((*it)->Centroid() - px) <<
" < " <<
fSigma << std::endl;
784 for(
auto* item : *(
fProjection->GetListOfFunctions())) {
785 if(item->IsA() == TF1::Class() || item->IsA() == GPeak::Class()) {
786 double centroid = 0.;
787 if(item->IsA() == TF1::Class()) {
788 centroid =
static_cast<TF1*
>(item)->GetParameter(1);
790 centroid =
static_cast<GPeak*
>(item)->Centroid();
792 if(TMath::Abs(centroid - px) <
fSigma) {
794 std::cout <<
DCYAN <<
"Removing function " << TMath::Abs(centroid - px) <<
" < " <<
fSigma << std::endl;
802 if(item->IsA() == TPolyMarker::Class()) { item->Print(); }
832 std::cout <<
DCYAN << __PRETTY_FUNCTION__ <<
": px " << px <<
", py " << py << std::endl;
847 std::cout <<
"TSourceTab frame:" << std::endl;
849 std::cout <<
"TSourceTab canvas:" << std::endl;
851 std::cout <<
"TSourceTab status bar:" << std::endl;
856TChannelTab::TChannelTab(
TSourceCalibration* parent, std::vector<TNucleus*> nuclei, std::vector<GH1D*> projections, std::string name, TGCompositeFrame* frame,
double sigma,
double threshold,
int degree, std::vector<std::vector<std::tuple<double, double, double, double>>> sourceEnergies, TGHProgressBar* progressBar)
857 : 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), fParent(parent), fNuclei(std::move(nuclei)), fProjections(std::move(projections)), fName(std::move(name)), fSigma(sigma), fThreshold(threshold), fDegree(degree), fSourceEnergies(std::move(sourceEnergies))
860 std::cout <<
DYELLOW <<
"========================================" << std::endl;
861 std::cout << __PRETTY_FUNCTION__ << std::endl
862 <<
" name = " <<
fName <<
", fData = " <<
fData << std::endl;
863 std::cout <<
"========================================" << std::endl;
870 for(
size_t source = 0; source <
fNuclei.size(); ++source) {
871 CreateSourceTab(source);
875 if(*iter == nullptr) {
876 fSources.erase(iter--);
880 fChannelFrame->AddFrame(fSourceTab,
new TGLayoutHints(kLHintsLeft | kLHintsTop | kLHintsExpandX | kLHintsExpandY, 2, 2, 2, 2));
882 fCalibrationFrame = fCanvasTab->AddTab(
"Calibration");
883 fCalibrationFrame->SetLayoutManager(
new TGVerticalLayout(fCalibrationFrame));
885 fCalibrationFrame->AddFrame(fCalibrationCanvas,
new TGLayoutHints(kLHintsTop | kLHintsExpandX | kLHintsExpandY, 2, 2, 2, 2));
887 std::array<int, 3> parts = {25, 35, 40};
888 fChannelStatusBar->SetParts(parts.data(), parts.size());
889 fCalibrationFrame->AddFrame(fChannelStatusBar,
new TGLayoutHints(kLHintsBottom | kLHintsExpandX, 2, 2, 2, 2));
890 fFwhmFrame = fCanvasTab->AddTab(
"FWHM");
891 fFwhmFrame->SetLayoutManager(
new TGVerticalLayout(fFwhmFrame));
893 fFwhmFrame->AddFrame(fFwhmCanvas,
new TGLayoutHints(kLHintsTop | kLHintsExpandX | kLHintsExpandY, 2, 2, 2, 2));
895 fChannelFrame->AddFrame(fCanvasTab,
new TGLayoutHints(kLHintsRight | kLHintsTop | kLHintsExpandX | kLHintsExpandY, 2, 2, 2, 2));
899 fCalibrationCanvas->GetCanvas()->cd();
900 fCalibrationPad =
new TPad(Form(
"cal_%s", fName.c_str()), Form(
"calibration for %s", fName.c_str()), 0.2, 0., 1., 1.);
901 fCalibrationPad->SetNumber(1);
902 fCalibrationPad->Draw();
903 fCalibrationPad->AddExec(
"zoom",
"TChannelTab::ZoomY()");
905 fLegend =
new TLegend(0.8, 0.3, 0.95, 0.3 +
static_cast<double>(fNuclei.size()) * 0.05);
907 fCalibrationCanvas->GetCanvas()->cd();
908 fResidualPad =
new TPad(Form(
"res_%s", fName.c_str()), Form(
"residual for %s", fName.c_str()), 0.0, 0., 0.2, 1.);
909 fResidualPad->SetNumber(2);
910 fResidualPad->Draw();
911 fResidualPad->AddExec(
"zoom",
"TChannelTab::ZoomY()");
916 fFwhmCanvas->GetCanvas()->cd();
917 fFwhm->DrawCalibration(
"*");
921 std::cout <<
DYELLOW <<
"----------------------------------------" << std::endl;
922 std::cout << __PRETTY_FUNCTION__ << std::endl
923 <<
" channel " << fName <<
" done" << std::endl;
924 std::cout <<
"----------------------------------------" << std::endl;
953 std::cout <<
DYELLOW <<
"Creating source tab " << source <<
", using fParent " <<
fParent << std::flush;
957 std::cout << std::endl;
965 std::cout <<
DYELLOW <<
"Skipping projection of source " << source <<
" = " <<
fProjections[source]->GetName() <<
", only " <<
fProjections[source]->GetEntries() <<
" entries" << std::endl;
969 std::cout << __PRETTY_FUNCTION__ <<
" source " << source <<
" done" << std::endl;
975 fSourceTab->Connect(
"Selected(Int_t)",
"TChannelTab",
this,
"SelectedTab(Int_t)");
976 fCalibrationCanvas->GetCanvas()->Connect(
"ProcessedEvent(Int_t,Int_t,Int_t,TObject*)",
"TChannelTab",
this,
"CalibrationStatus(Int_t,Int_t,Int_t,TObject*)");
977 fCalibrationCanvas->Connect(
"ProcessedEvent(Event_t*)",
"TChannelTab",
this,
"SelectCanvas(Event_t*)");
979 source->MakeConnections();
980 fData->Connect(
"RemovePoint(const Int_t&, const Int_t&)",
"TSourceTab", source,
"RemovePoint(const Int_t&, const Int_t&)");
981 fData->Connect(
"RemoveResidualPoint(const Int_t&, const Int_t&)",
"TSourceTab", source,
"RemoveResidualPoint(const Int_t&, const Int_t&)");
987 fSourceTab->Disconnect(
"Selected(Int_t)",
this,
"SelectedTab(Int_t)");
988 fCalibrationCanvas->GetCanvas()->Disconnect(
"ProcessedEvent(Int_t,Int_t,Int_t,TObject*)",
this,
"CalibrationStatus(Int_t,Int_t,Int_t,TObject*)");
990 source->Disconnect();
991 fData->Disconnect(
"RemovePoint(const Int_t&, const Int_t&)", source,
"RemovePoint(const Int_t&, const Int_t&)");
992 fData->Disconnect(
"RemoveResidualPoint(const Int_t&, const Int_t&)", source,
"RemoveResidualPoint(const Int_t&, const Int_t&)");
1022 if(event->fType == kEnterNotify) {
1024 std::cout <<
"Entered channel tab => changing gPad from " << gPad->GetName();
1028 std::cout <<
" to " << gPad->GetName() << std::endl;
1049 if(event == kKeyPress) {
1053 if(canvas ==
nullptr) {
1057 auto* pad = canvas->GetSelectedPad();
1058 if(pad ==
nullptr) {
1066 fChannelStatusBar->SetText(Form(
"x = %f, y = %f", pad->AbsPixeltoX(px), pad->AbsPixeltoY(py)), 1);
1074 if(
fData ==
nullptr) {
1080 fData->SetName(Form(
"data%s",
fName.c_str()));
1082 std::cout <<
"set name of fData using " <<
fName.c_str() <<
": " <<
fData->GetName() << std::endl;
1083 std::cout <<
"fData " <<
fData <<
": " << (
fData !=
nullptr ?
fData->
GetN() : -2) <<
" data points after creation" << std::endl;
1084 std::cout <<
"Looping over " <<
fNuclei.size() <<
" sources, fSources.size() = " <<
fSources.size() << std::endl;
1086 for(
size_t source = 0; source <
fNuclei.size() && source <
fSources.size(); ++source) {
1096 std::cout <<
"fData " <<
fData <<
": " << (
fData !=
nullptr ?
fData->
GetN() : -1) <<
" data points after adding " <<
fNuclei.size() <<
" graphs" << std::endl;
1105 if(
fFwhm ==
nullptr) {
1111 fFwhm->SetName(Form(
"fwhm%s",
fName.c_str()));
1113 std::cout <<
"set name of fFwhm using " <<
fName.c_str() <<
": " <<
fFwhm->GetName() << std::endl;
1114 std::cout <<
"fFwhm " <<
fFwhm <<
": " << (
fFwhm !=
nullptr ?
fFwhm->
GetN() : -2) <<
" data points after creation" << std::endl;
1115 std::cout <<
"Looping over " <<
fNuclei.size() <<
" sources, fSources.size() = " <<
fSources.size() << std::endl;
1117 for(
size_t source = 0; source <
fNuclei.size() && source <
fSources.size(); ++source) {
1118 if(
fSources[source]->Fwhm()->GetN() > 0) {
1127 std::cout <<
"fFwhm " <<
fFwhm <<
": " << (
fFwhm !=
nullptr ?
fFwhm->
GetN() : -1) <<
" data points after adding " <<
fNuclei.size() <<
" graphs" << std::endl;
1134 if(degree !=
fDegree || force) {
1138 std::cout <<
"forced calibration" << std::endl;
1140 std::cout <<
"changed degree of polynomial: " << degree <<
" != " <<
fDegree << std::endl;
1146 std::cout << degree <<
" == " <<
fDegree <<
" and not forcing (" << force <<
"): not fitting channel " <<
fName << std::endl;
1154 calibration->FixParameter(0,
fDegree);
1157 TString text = Form(
"%.6f + %.6f*x", calibration->GetParameter(1), calibration->GetParameter(2));
1158 for(
int i = 2; i <=
fDegree; ++i) {
1159 text.Append(Form(
" + %.6f*x^%d", calibration->GetParameter(i + 1), i));
1179 fChi2Label =
new TPaveText(left, bottom, right, top);
1187 fChi2Label->AddText(Form(
"#chi^{2}/NDF = %f", calibration->GetChisquare() / calibration->GetNDF()));
1191 std::cout <<
"fChi2Label set to:" << std::endl;
1193 std::cout <<
"Text size " <<
fChi2Label->GetTextSize() << std::endl;
1210 std::stringstream str;
1211 str << std::hex <<
fName;
1216 if(calibration ==
nullptr) {
1217 std::cout <<
"Failed to find calibration in fData" << std::endl;
1221 std::vector<Float_t> parameters;
1222 for(
int i = 0; i <= calibration->GetParameter(0); ++i) {
1223 parameters.push_back(
static_cast<Float_t
>(calibration->GetParameter(i + 1)));
1226 if(channel ==
nullptr) {
1227 std::cerr <<
"Failed to get channel for address " <<
hex(address, 4) << std::endl;
1237 for(
int i = 0; i <
fData->
GetN(); ++i) {
1246void TChannelTab::FindPeaks(
const double& sigma,
const double& threshold,
const double& peakRatio,
const bool& force,
const bool& fast)
1251 for(
int tab = 0; tab <
fSourceTab->GetNumberOfTabs(); ++tab) {
1252 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;
1265 fData->Write(Form(
"calGraph_%s",
fName.c_str()), TObject::kOverwrite);
1266 fFwhm->Write(Form(
"fwhm_%s",
fName.c_str()), TObject::kOverwrite);
1274 TH1* hist1 =
nullptr;
1275 for(
const auto&& obj : *(gPad->GetListOfPrimitives())) {
1276 if(obj->InheritsFrom(TGraph::Class())) {
1277 hist1 =
static_cast<TGraph*
>(obj)->GetHistogram();
1281 if(hist1 ==
nullptr) {
1282 std::cout <<
"ZoomX - Failed to find histogram for pad " << gPad->GetName() << std::endl;
1288 std::string padName = gPad->GetName();
1289 std::string baseName = padName.substr(0, 3);
1290 std::string channelName = padName.substr(4);
1293 std::string newName;
1294 if(baseName ==
"cal") {
1295 newName =
"res_" + channelName;
1296 }
else if(baseName ==
"res") {
1297 newName =
"cal_" + channelName;
1299 std::cout <<
"Unknown combination of pad " << gPad->GetName() <<
" and histogram " << hist1->GetName() << std::endl;
1302 auto* newObj = gPad->GetCanvas()->FindObject(newName.c_str());
1303 if(newObj ==
nullptr) {
1304 std::cout <<
"Failed to find " << newName << std::endl;
1308 if(newObj->IsA() != TPad::Class()) {
1309 std::cout << newObj <<
" = " << newObj->GetName() <<
", " << newObj->GetTitle() <<
" is a " << newObj->ClassName() <<
" not a TPad" << std::endl;
1312 auto* pad2 =
static_cast<TPad*
>(newObj);
1313 if(pad2 ==
nullptr) {
1314 std::cout <<
"Failed to find partner pad " << newName << std::endl;
1318 TH1* hist2 =
nullptr;
1319 for(
const auto&& obj : *(pad2->GetListOfPrimitives())) {
1320 if(obj->InheritsFrom(TGraph::Class())) {
1321 hist2 =
static_cast<TGraph*
>(obj)->GetHistogram();
1325 if(hist2 ==
nullptr) {
1326 std::cout <<
"ZoomX - Failed to find histogram for partner pad " << newName << std::endl;
1331 TAxis* axis1 = hist1->GetXaxis();
1332 Int_t binmin = axis1->GetFirst();
1333 Int_t binmax = axis1->GetLast();
1334 Double_t xmin = axis1->GetBinLowEdge(binmin);
1335 Double_t xmax = axis1->GetBinLowEdge(binmax);
1336 TAxis* axis2 = hist2->GetXaxis();
1337 Int_t newmin = axis2->FindBin(xmin);
1338 Int_t newmax = axis2->FindBin(xmax);
1339 axis2->SetRange(newmin, newmax);
1348 TH1* hist1 =
nullptr;
1349 for(
const auto&& obj : *(gPad->GetListOfPrimitives())) {
1350 if(obj->InheritsFrom(TGraph::Class())) {
1351 hist1 =
static_cast<TGraph*
>(obj)->GetHistogram();
1355 if(hist1 ==
nullptr) {
1356 std::cout <<
"ZoomY - Failed to find histogram for pad " << gPad->GetName() << std::endl;
1362 std::string padName = gPad->GetName();
1363 std::string baseName = padName.substr(0, 3);
1364 std::string channelName = padName.substr(4);
1367 std::string newName;
1368 if(baseName ==
"cal") {
1369 newName =
"res_" + channelName;
1370 }
else if(baseName ==
"res") {
1371 newName =
"cal_" + channelName;
1373 std::cout <<
"Unknown combination of pad " << gPad->GetName() <<
" and histogram " << hist1->GetName() << std::endl;
1376 auto* newObj = gPad->GetCanvas()->FindObject(newName.c_str());
1377 if(newObj ==
nullptr) {
1378 std::cout <<
"Failed to find " << newName << std::endl;
1382 if(newObj->IsA() != TPad::Class()) {
1383 std::cout << newObj <<
" = " << newObj->GetName() <<
", " << newObj->GetTitle() <<
" is a " << newObj->ClassName() <<
" not a TPad" << std::endl;
1386 auto* pad2 =
static_cast<TPad*
>(newObj);
1387 if(pad2 ==
nullptr) {
1388 std::cout <<
"Failed to find partner pad " << newName << std::endl;
1392 TH1* hist2 =
nullptr;
1393 for(
const auto&& obj : *(pad2->GetListOfPrimitives())) {
1394 if(obj->InheritsFrom(TGraph::Class())) {
1395 hist2 =
static_cast<TGraph*
>(obj)->GetHistogram();
1399 if(hist2 ==
nullptr) {
1400 std::cout <<
"ZoomY - Failed to find histogram for partner pad " << newName << std::endl;
1405 hist2->SetMinimum(hist1->GetMinimum());
1406 hist2->SetMaximum(hist1->GetMaximum());
1414 std::cout <<
"TChannelTab frame:" << std::endl;
1416 std::cout <<
"TChannelTab canvas:" << std::endl;
1418 std::cout <<
"TChannelTab status bar:" << std::endl;
1421 sourceTab->PrintLayout();
1437 : TGMainFrame(nullptr, 2 * fPanelWidth, fPanelHeight + 2 * fStatusbarHeight), fDefaultSigma(sigma), fDefaultThreshold(threshold), fDefaultDegree(degree), fDefaultPeakRatio(peakRatio)
1439 TH1::AddDirectory(
false);
1442 va_start(args, count);
1443 for(
int i = 0; i < count; ++i) {
1444 fMatrices.push_back(va_arg(args, TH2*));
1446 std::cout <<
"Error, got nullptr as matrix input?" << std::endl;
1452 std::cout <<
DGREEN << __PRETTY_FUNCTION__ <<
": verbose level " <<
fVerboseLevel << std::endl
1453 <<
"using " << count <<
"/" <<
fMatrices.size() <<
" matrices:" << std::endl;
1455 std::cout <<
mat << std::flush <<
" = " <<
mat->GetName() << std::endl;
1460 gErrorIgnoreLevel = kError;
1461 gPrintViaErrorHandler =
true;
1466 std::map<int, int> channelToIndex;
1467 for(
int bin = 1; bin <=
fMatrices[0]->GetNbinsX(); ++bin) {
1480 for(
size_t i = 1; i <
fMatrices.size(); ++i) {
1482 for(
int bin = 1; bin <=
fMatrices[i]->GetNbinsX(); ++bin) {
1485 if(channelToIndex.find(bin) == channelToIndex.end() || tmpBins != channelToIndex[bin]) {
1486 std::ostringstream error;
1487 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;
1488 throw std::invalid_argument(error.str());
1490 if(strcmp(
fMatrices[0]->GetXaxis()->GetBinLabel(bin),
fMatrices[i]->GetXaxis()->GetBinLabel(bin)) != 0) {
1491 std::ostringstream error;
1492 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;
1493 throw std::invalid_argument(error.str());
1497 if(channelToIndex.find(bin) != channelToIndex.end()) {
1498 std::ostringstream error;
1499 error <<
"Mismatch in " << i <<
". matrix (" <<
fMatrices[i]->GetName() <<
"), bin " << bin <<
" is empty, but should be " << channelToIndex[bin] <<
". filled bin" << std::endl;
1500 throw std::invalid_argument(error.str());
1508 fOutput =
new TFile(
"TSourceCalibration.root",
"recreate");
1510 throw std::runtime_error(
"Unable to open output file \"TSourceCalibration.root\"!");
1523 SetWindowName(
"SourceCalibration");
1529 Resize(GetDefaultSize());
1549 auto* layoutManager =
new TGTableLayout(
this,
fMatrices.size() + 1, 2,
true, 5);
1551 SetLayoutManager(layoutManager);
1563#if __cplusplus >= 201703L
1566 if(std::getenv(
"GRSISYS") ==
nullptr) {
1567 throw std::runtime_error(
"Failed to get environment variable $GRSISYS");
1569 std::string path(std::getenv(
"GRSISYS"));
1570 path +=
"/libraries/TAnalysis/SourceData/";
1571 for(
const auto& file : std::filesystem::directory_iterator(path)) {
1572 if(file.is_regular_file() && file.path().extension().compare(
".sou") == 0) {
1573 fSourceBox.back()->AddEntry(file.path().stem().c_str(), index);
1575 if(std::strstr(
fMatrices[i]->GetName(), file.path().stem().c_str()) !=
nullptr) {
1580 std::cout <<
"matrix name " <<
fMatrices[i]->GetName() <<
" not matching " << file.path().stem().c_str() << std::endl;
1588 if(std::strstr(
fMatrices[i]->GetName(),
"22Na") !=
nullptr) {
1594 if(std::strstr(
fMatrices[i]->GetName(),
"56Co") !=
nullptr) {
1600 if(std::strstr(
fMatrices[i]->GetName(),
"60Co") !=
nullptr) {
1606 if(std::strstr(
fMatrices[i]->GetName(),
"133Ba") !=
nullptr) {
1612 if(std::strstr(
fMatrices[i]->GetName(),
"152Eu") !=
nullptr) {
1618 if(std::strstr(
fMatrices[i]->GetName(),
"241Am") !=
nullptr) {
1627 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; }
1628 AddFrame(
fMatrixNames.back(),
new TGTableLayoutHints(0, 1, i, i + 1, kLHintsRight | kLHintsCenterY));
1629 AddFrame(
fSourceBox.back(),
new TGTableLayoutHints(1, 2, i, i + 1, kLHintsLeft | kLHintsCenterY));
1636 AddFrame(
fStartButton,
new TGTableLayoutHints(0, 2, i, i + 1, kLHintsCenterX | kLHintsCenterY));
1646 box->Connect(
"Selected(Int_t, Int_t)",
"TSourceCalibration",
this,
"SetSource(Int_t, Int_t)");
1650 fStartButton->Connect(
"Clicked()",
"TSourceCalibration",
this,
"Start()");
1657 box->Disconnect(
"Selected(Int_t, Int_t)",
this,
"SetSource(Int_t, Int_t)");
1660 fStartButton->Disconnect(
"Clicked()",
this,
"Start()");
1666 RemoveFrame(element);
1690 auto* nucleus =
new TNucleus(
fSourceBox[index]->GetListBox()->GetEntry(entryId)->GetTitle());
1691 TIter iter(nucleus->GetTransitionList());
1693 while(
auto* transition =
static_cast<TTransition*
>(iter.Next())) {
1694 fSourceEnergy[index].push_back(std::make_tuple(transition->GetEnergy(), transition->GetEnergyUncertainty(), transition->GetIntensity(), transition->GetIntensityUncertainty()));
1706 if(channelTab ==
nullptr) {
continue; }
1707 channelTab->UpdateChannel();
1711 std::cout <<
"Closing window" << std::endl;
1713 std::cout <<
"all done" << std::endl;
1723 TTimer::SingleShot(
fWaitMs,
"TSourceCalibration",
this,
"HandleTimer()");
1731 for(
size_t i = 0; i <
fSource.size(); ++i) {
1733 std::cerr <<
"Source " << i <<
" not set!" << std::endl;
1738 for(
size_t i = 0; i <
fSource.size(); ++i) {
1739 for(
size_t j = i + 1; j <
fSource.size(); ++j) {
1741 std::cerr <<
"Duplicate sources: " << i <<
" - " <<
fSource[i]->GetName() <<
" and " << j <<
" - " <<
fSource[j]->GetName() << std::endl;
1752 SetLayoutManager(
new TGVerticalLayout(
this));
1759 AddFrame(
fProgressBar,
new TGLayoutHints(kLHintsCenterX | kLHintsCenterY | kLHintsExpandX | kLHintsExpandY, 0, 0, 0, 0));
1790 SetLayoutManager(
new TGVerticalLayout(
this));
1796 std::vector<GH1D*> projections(
fMatrices.size());
1799 projections[index] =
new GH1D(matrix->ProjectionY(Form(
"%s_%s",
fSource[index]->GetName(), matrix->GetXaxis()->GetBinLabel(bin)), bin, bin));
1811 AddFrame(
fTab,
new TGLayoutHints(kLHintsTop | kLHintsExpandX | kLHintsExpandY, 0, 0, 0, 0));
1867 AddFrame(
fBottomFrame,
new TGLayoutHints(kLHintsBottom | kLHintsExpandX, 2, 2, 2, 2));
1877 fNavigationGroup->Connect(
"Clicked(Int_t)",
"TSourceCalibration",
this,
"Navigate(Int_t)");
1878 fTab->Connect(
"Selected(Int_t)",
"TSourceCalibration",
this,
"SelectedTab(Int_t)");
1881 if(sourceTab !=
nullptr) {
1882 sourceTab->MakeConnections();
1891 fTab->Disconnect(
"Selected(Int_t)",
this,
"SelectedTab(Int_t)");
1893 if(sourceTab !=
nullptr) {
1894 sourceTab->Disconnect();
1904 int currentChannelId =
fTab->GetCurrent();
1906 int nofTabs =
fTab->GetNumberOfTabs();
1907 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; }
1911 fTab->SetTab(currentChannelId - 1);
1925 if(currentChannelId < nofTabs - 1) {
1926 fTab->SetTab(currentChannelId + 1);
1928 fTab->SetTab(currentChannelId - 1);
1931 fTab->RemoveTab(currentChannelId);
1941 fTab->SetTab(currentChannelId + 1);
1955 if(
id < 0) {
return; }
1962 if(
id ==
fTab->GetNumberOfTabs() - 1) {
1971 std::cout <<
"Failed to get fChannelTab[" <<
fActiveBins[id] - 1 <<
" = fActiveBins[" <<
id <<
"]-1]" <<
RESET_COLOR << std::endl;
1975 std::cout <<
"Failed to get fChannelTab[" <<
fActiveBins[id] - 1 <<
" = fActiveBins[" <<
id <<
"]-1]->SelectedSourceTab()" <<
RESET_COLOR << std::endl;
1979 std::cout <<
"Failed to get fChannelTab[" <<
fActiveBins[id] - 1 <<
" = fActiveBins[" <<
id <<
"]-1]->SelectedSourceTab()->ProjectionCanvas()" <<
RESET_COLOR << std::endl;
1983 std::cout <<
"Failed to get fChannelTab[" <<
fActiveBins[id] - 1 <<
" = fActiveBins[" <<
id <<
"]-1]->SelectedSourceTab()->ProjectionCanvas()->GetCanvas()" <<
RESET_COLOR << std::endl;
1997 int nofTabs =
fTab->GetNumberOfTabs();
1999 int maxChannel = nofTabs - 1;
2000 if(channelId >= 0) {
2001 minChannel = channelId;
2002 maxChannel = channelId;
2007 for(
int currentChannelId = maxChannel; currentChannelId >= minChannel; --currentChannelId) {
2009 if(
fVerboseLevel >
EVerbosity::kLoops) { std::cout << __PRETTY_FUNCTION__ <<
": currentChannelId " << currentChannelId <<
", actualChannelId " << actualChannelId <<
", fChannelTab.size() " <<
fChannelTab.size() <<
", fActualChannelId.size() " <<
fActualChannelId.size() << std::endl; }
2010 if(minChannel == maxChannel) {
2011 if(currentChannelId < maxChannel) {
2012 fTab->SetTab(currentChannelId + 1);
2014 fTab->SetTab(currentChannelId - 1);
2018 fTab->RemoveTab(currentChannelId);
2029 TTimer::SingleShot(
fWaitMs,
"TSourceCalibration",
this,
"HandleTimer()");
2041 std::cout << __PRETTY_FUNCTION__ <<
": fChannelTab[" <<
fActiveBins[
fTab->GetCurrent()] <<
" = fActiveBins[" <<
fTab->GetCurrent() <<
"]] is a nullptr!" << std::endl;
2053 std::cout << __PRETTY_FUNCTION__ <<
": fChannelTab[" <<
fActiveBins[
fTab->GetCurrent()] <<
" = fActiveBins[" <<
fTab->GetCurrent() <<
"]] is a nullptr!" << std::endl;
2064 std::cout << __PRETTY_FUNCTION__ <<
": fChannelTab[" <<
fActiveBins[
fTab->GetCurrent()] <<
" = fActiveBins[" <<
fTab->GetCurrent() <<
"]] is a nullptr!" << std::endl;
2072 std::ostringstream fileName;
2074 fileName << source->GetName();
2090 if(
fTab !=
nullptr) {
fTab->Print(); }
2091 std::cout <<
"TSourceCalibration all channel tabs:" << std::endl;
2093 if(channelTab !=
nullptr) { channelTab->PrintLayout(); }
GPeak * PhotoPeakFit(TH1 *, double, double, Option_t *opt="")
std::string hex(T val, int width=-1)
bool FilledBin(TH2 *matrix, const int &bin)
std::map< GPeak *, std::tuple< double, double, double, double > > Match(std::vector< GPeak * > peaks, std::vector< std::tuple< double, double, double, double > > sources, TSourceTab *sourceTab)
double Polynomial(double *x, double *par)
std::map< GPeak *, std::tuple< double, double, double, double > > SmartMatch(std::vector< GPeak * > peaks, std::vector< std::tuple< double, double, double, double > > sources, TSourceTab *sourceTab)
bool FilledBin(TH2 *matrix, const int &bin)
std::map< GPeak *, std::tuple< double, double, double, double > > Match(std::vector< GPeak * > peaks, std::vector< std::tuple< double, double, double, double > > sources, TSourceTab *sourceTab)
double Polynomial(double *x, double *par)
std::map< GPeak *, std::tuple< double, double, double, double > > SmartMatch(std::vector< GPeak * > peaks, std::vector< std::tuple< double, double, double, double > > sources, TSourceTab *sourceTab)
void Print(Option_t *opt="") const override
void Clear(Option_t *opt="") override
void Draw(Option_t *opt="") override
Double_t Centroid() const
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)
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
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()
std::vector< GH1D * > fProjections
vector of all projections
double fThreshold
the threshold (relative to the largest peak) used in the peak finder
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
TChannelTab(TSourceCalibration *parent, std::vector< TNucleus * > nuclei, std::vector< GH1D * > projections, std::string name, TGCompositeFrame *frame, double sigma, double threshold, int degree, std::vector< std::vector< std::tuple< double, double, double, double > > > sourceEnergies, TGHProgressBar *progressBar)
TGTab * fSourceTab
tab for sources
void SelectCanvas(Event_t *event)
void Write(TFile *output)
void CalibrationStatus(Int_t event, Int_t px, Int_t py, TObject *selected)
TGCompositeFrame * fCalibrationFrame
frame of tab with calibration
TSourceCalibration * fParent
the parent of this tab
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
TRootEmbeddedCanvas * fFwhmCanvas
int fActiveSourceTab
id of the currently active source tab
std::string fName
name of this tab
void FindPeaks(const double &sigma, const double &threshold, const double &peakRatio, const bool &force=false, const bool &fast=true)
int fDegree
degree of polynomial function used to calibrate
std::vector< TNucleus * > fNuclei
the source nucleus
void SelectedTab(Int_t id)
TGStatusBar * fChannelStatusBar
TGTab * fCanvasTab
tab for canvases (calibration with residuals, and FWHM)
double fSigma
the sigma used in the peak finder
TGHProgressBar * fProgressBar
TRootEmbeddedCanvas * fCalibrationCanvas
TCalibrationGraphSet * fData
combined data from all sources
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
static std::string LogFile()
static int fStatusbarHeight
Height of status bar (also extra height needed for tabs)
TGVerticalFrame * fRightFrame
static std::string fLogFile
name of log file, if empty no log file is written
TGNumberEntry * fPeakRatioEntry
TGCheckButton * fWriteNonlinearities
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 * fCalibrateButton
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 * fFindPeaksFastButton
double fDefaultPeakRatio
The default ratio between found peaks and peaks in the source (per region).
TGHProgressBar * fProgressBar
TGHButtonGroup * fNavigationGroup
TGNumberEntry * fThresholdEntry
void SetSource(Int_t windowId, Int_t entryId)
TGTextButton * fFindPeaksButton
static int StatusbarHeight()
std::vector< int > fActiveBins
TGTextButton * fDiscardButton
std::vector< TNucleus * > fSource
bool WriteNonlinearities()
std::vector< const char * > fChannelLabel
std::vector< TChannelTab * > fChannelTab
TGTextButton * fAcceptButton
TSourceCalibration(double sigma, double threshold, int degree, double peakRatio, int count...)
static int fPanelWidth
Width of one panel.
static int fPanelHeight
Height of one panel.
std::vector< TH2 * > fMatrices
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)
std::vector< TGComboBox * > fSourceBox
TGLabel * fPeakRatioLabel
std::vector< int > fActualChannelId
int fNofBins
Number of filled bins in first matrix.
TGNumberEntry * fDegreeEntry
void MakeSecondConnections()
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 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...
TGTextButton * fNextButton
TGVerticalFrame * fLeftFrame
static EVerbosity fVerboseLevel
Changes verbosity from 0 (quiet) to 4 (very verbose)
TGHorizontalFrame * fBottomFrame
void BuildSecondInterface()
void RemovePoint(Int_t px, Int_t py)
std::vector< GPeak * > fPeaks
void Status(const char *status, int position)
TRootEmbeddedCanvas * fProjectionCanvas
TSourceTab(TChannelTab *parent, TGCompositeFrame *frame, GH1D *projection, const double &sigma, const double &threshold, const double &peakRatio, std::vector< std::tuple< double, double, double, double > > sourceEnergy)
void FindPeaks(const double &sigma, const double &threshold, const double &peakRatio, const bool &force=false, const bool &fast=true)
std::vector< std::pair< double, double > > fRegions
void Add(std::map< GPeak *, std::tuple< double, double, double, double > > map)
void ProjectionStatus(Event_t *event)
TGCompositeFrame * fSourceFrame
void RemoveResidualPoint(Int_t px, Int_t py)
std::vector< std::tuple< double, double, double, double > > fSourceEnergy
TGStatusBar * fSourceStatusBar