musrfit 1.10.0
PFourierCanvas.cpp
Go to the documentation of this file.
1/***************************************************************************
2
3 PFourierCanvas.cpp
4
5 Author: Andreas Suter
6 e-mail: andreas.suter@psi.ch
7
8***************************************************************************/
9
10/***************************************************************************
11 * Copyright (C) 2007-2026 by Andreas Suter *
12 * andreas.suter@psi.ch *
13 * *
14 * This program is free software; you can redistribute it and/or modify *
15 * it under the terms of the GNU General Public License as published by *
16 * the Free Software Foundation; either version 2 of the License, or *
17 * (at your option) any later version. *
18 * *
19 * This program is distributed in the hope that it will be useful, *
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
22 * GNU General Public License for more details. *
23 * *
24 * You should have received a copy of the GNU General Public License *
25 * along with this program; if not, write to the *
26 * Free Software Foundation, Inc., *
27 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
28 ***************************************************************************/
29
30#include <iostream>
31#include <fstream>
32
33#include <TColor.h>
34#include <TRandom.h>
35#include <TROOT.h>
36#include <TDatime.h>
37#include <TMath.h>
38#include <TGFileDialog.h>
39
40#include "PFourierCanvas.h"
41
42#define YINFO 0.2
43#define YTITLE 0.95
44
45static const Char_t *gFiletypes[] = { "Data files", "*.dat",
46 "All files", "*",
47 nullptr, nullptr };
48
50
51//---------------------------------------------------------------------------
69{
70 fTimeout = 0;
71
72 fBatchMode = false;
73 fValid = false;
74 fAveragedView = false;
77 fInitialXRange[0] = 0.0;
78 fInitialXRange[1] = 0.0;
79
80 fTitle = TString("");
81 fXaxisTitle = TString("");
82
84
85 fImp = nullptr;
86 fBar = nullptr;
87 fPopupMain = nullptr;
88}
89
90//---------------------------------------------------------------------------
126PFourierCanvas::PFourierCanvas(std::vector<PFourier*> &fourier, PIntVector dataSetTag, const Char_t* title,
127 const Bool_t showAverage, const Bool_t showAveragePerDataSet,
128 const Int_t fourierPlotOpt, Double_t fourierXrange[], Double_t phase,
129 Int_t wtopx, Int_t wtopy, Int_t ww, Int_t wh,
130 const Bool_t batch) :
131 fBatchMode(batch), fAveragedView(showAverage), fAveragedViewPerDataSet(showAveragePerDataSet),
132 fDataSetTag(dataSetTag), fCurrentPlotView(fourierPlotOpt), fTitle(title), fFourier(fourier),
133 fCurrentFourierPhase(phase)
134{
135 fInitialXRange[0] = fourierXrange[0];
136 fInitialXRange[1] = fourierXrange[1];
137
138 fTimeout = 0;
139
140 fValid = false;
141
142 // generate fMarkerList and fColorList, since they are not provided
143 TRandom rand;
144 Int_t style, color;
145 for (UInt_t i=0; i<fourier.size(); i++) {
146 rand.SetSeed(i);
147 style = 20+static_cast<Int_t>(rand.Integer(10));
148 fMarkerList.push_back(style);
149 color = TColor::GetColor(static_cast<Int_t>(rand.Integer(255)), static_cast<Int_t>(rand.Integer(255)), static_cast<Int_t>(rand.Integer(255)));
150 fColorList.push_back(color);
151 }
152
153 CreateXaxisTitle();
154 CreateStyle();
155 InitFourierDataSets();
156 InitFourierCanvas(fTitle, wtopx, wtopy, ww, wh);
157
158 gStyle->SetHistMinimumZero(kTRUE); // needed to enforce proper bar option handling
159}
160
161//---------------------------------------------------------------------------
203PFourierCanvas::PFourierCanvas(std::vector<PFourier*> &fourier, PIntVector dataSetTag, const Char_t* title,
204 const Bool_t showAverage, const Bool_t showAveragePerDataSet,
205 const Int_t fourierPlotOpt, Double_t fourierXrange[], Double_t phase,
206 Int_t wtopx, Int_t wtopy, Int_t ww, Int_t wh,
207 const PIntVector markerList, const PIntVector colorList, const Bool_t batch) :
208 fBatchMode(batch), fAveragedView(showAverage), fAveragedViewPerDataSet(showAveragePerDataSet),
209 fDataSetTag(dataSetTag), fCurrentPlotView(fourierPlotOpt), fTitle(title), fFourier(fourier),
210 fCurrentFourierPhase(phase), fMarkerList(markerList), fColorList(colorList)
211{
212 fInitialXRange[0] = fourierXrange[0];
213 fInitialXRange[1] = fourierXrange[1];
214
215 fTimeout = 0;
216
217 fValid = false;
218
219 // generate fMarkerList and fColorList, since they are not provided
220 TRandom rand;
221 Int_t style, color;
222 for (UInt_t i=static_cast<UInt_t>(fMarkerList.size()); i<fourier.size(); i++) {
223 rand.SetSeed(i);
224 style = 20+static_cast<Int_t>(rand.Integer(10));
225 fMarkerList.push_back(style);
226 }
227 for (UInt_t i=static_cast<UInt_t>(fColorList.size()); i<fourier.size(); i++) {
228 rand.SetSeed(i);
229 color = TColor::GetColor(static_cast<Int_t>(rand.Integer(255)), static_cast<Int_t>(rand.Integer(255)), static_cast<Int_t>(rand.Integer(255)));
230 fColorList.push_back(color);
231 }
232
233 CreateXaxisTitle();
234 CreateStyle();
235 InitFourierDataSets();
236 InitFourierCanvas(fTitle, wtopx, wtopy, ww, wh);
237
238 gStyle->SetHistMinimumZero(kTRUE); // needed to enforce proper bar option handling
239}
240
241//--------------------------------------------------------------------------
242// Done (SIGNAL)
243//--------------------------------------------------------------------------
266{
267 Emit("Done(Int_t)", status);
268}
269
270//--------------------------------------------------------------------------
271// HandleCmdKey (SLOT)
272//--------------------------------------------------------------------------
306void PFourierCanvas::HandleCmdKey(Int_t event, Int_t x, Int_t y, TObject *selected)
307{
308 if (event != kKeyPress)
309 return;
310
311 if (fBatchMode)
312 return;
313
314 if (x == 'q') { // quit
315 Done(0);
316 } else if (x == 'u') { // unzoom
318 PlotAverage();
319 else
320 PlotFourier();
321 } else if (x == 'a') { // toggle between average view and single histo view
322 // toggle average view flag
324 // unset average per data set view flag
326 // update menu
327 if (fAveragedView) {
328 fPopupMain->CheckEntry(P_MENU_ID_AVERAGE);
331 PlotAverage();
332 } else {
333 fPopupMain->UnCheckEntry(P_MENU_ID_AVERAGE);
336 PlotFourier();
337 }
338 } else if (x == 'd') { // toggle between average view per data set and single histo view
339 // toggle average per data set view flag
341 // unset average view flag
342 fAveragedView = false;
343 // update menu
346 fPopupMain->UnCheckEntry(P_MENU_ID_AVERAGE);
348 PlotAverage();
349 } else {
351 fPopupMain->UnCheckEntry(P_MENU_ID_AVERAGE);
353 PlotFourier();
354 }
355 } else if (x == 'c') {
356 Int_t state = fFourierPad->GetCrosshair();
357 if (state == 0) {
358 fMainCanvas->ToggleEventStatus();
359 fFourierPad->SetCrosshair(2);
360 } else {
361 fMainCanvas->ToggleEventStatus();
362 fFourierPad->SetCrosshair(0);
363 }
364 fMainCanvas->Update();
365 } else if (x == '+') { // increment phase (Fourier real/imag)
367 } else if (x == '-') { // decrement phase (Fourier real/imag)
369 }
370}
371
372//--------------------------------------------------------------------------
373// HandleMenuPopup (SLOT)
374//--------------------------------------------------------------------------
405{
406 if (fBatchMode)
407 return;
408
410 // uncheck fourier popup items
411 fPopupFourier->UnCheckEntries();
414 if (!fAveragedView) {
415 PlotFourier();
416 } else {
418 PlotAverage();
419 }
420 } else if (id == P_MENU_ID_FOURIER+P_MENU_ID_FOURIER_IMAG) {
421 fPopupFourier->UnCheckEntries();
424 if (!fAveragedView) {
425 PlotFourier();
426 } else {
428 PlotAverage();
429 }
431 fPopupFourier->UnCheckEntries();
434 if (!fAveragedView) {
435 PlotFourier();
436 } else {
438 PlotAverage();
439 }
440 } else if (id == P_MENU_ID_FOURIER+P_MENU_ID_FOURIER_PWR) {
441 fPopupFourier->UnCheckEntries();
444 if (!fAveragedView) {
445 PlotFourier();
446 } else {
448 PlotAverage();
449 }
451 fPopupFourier->UnCheckEntries();
454 if (!fAveragedView) {
455 PlotFourier();
456 } else {
458 PlotAverage();
459 }
461 fPopupFourier->UnCheckEntries();
464 if (!fAveragedView) {
465 PlotFourier();
466 } else {
468 PlotAverage();
469 }
474 } else if (id == P_MENU_ID_AVERAGE) {
475 // toggle average view flag
477 // unset average per data set view flag
479 // update menu
480 if (fAveragedView) {
481 fPopupMain->CheckEntry(P_MENU_ID_AVERAGE);
484 PlotAverage();
485 } else {
486 fPopupMain->UnCheckEntry(P_MENU_ID_AVERAGE);
489 PlotFourier();
490 }
491 } else if (id == P_MENU_ID_AVERAGE_PER_DATA_SET) {
492 // toggle average per data set view flag
494 // unset average view flag
495 fAveragedView = false;
496 // update menu
499 fPopupMain->UnCheckEntry(P_MENU_ID_AVERAGE);
501 PlotAverage();
502 } else {
504 fPopupMain->UnCheckEntry(P_MENU_ID_AVERAGE);
506 PlotFourier();
507 }
508 } else if (id == P_MENU_ID_EXPORT_DATA) {
509 static TString dir(".");
510 TGFileInfo fi;
511 fi.fFileTypes = gFiletypes;
512 fi.fIniDir = StrDup(dir);
513 fi.fOverwrite = true;
514 new TGFileDialog(nullptr, fImp, kFDSave, &fi);
515 if (fi.fFilename && strlen(fi.fFilename)) {
516 ExportData(fi.fFilename);
517 }
518 }
519}
520
521//--------------------------------------------------------------------------
522// LastCanvasClosed (SLOT)
523//--------------------------------------------------------------------------
529{
530 if (gROOT->GetListOfCanvases()->IsEmpty()) {
531 Done(0);
532 }
533}
534
535//--------------------------------------------------------------------------
536// UpdateFourierPad (public)
537//--------------------------------------------------------------------------
542{
543 if (!fValid)
544 return;
545
547 PlotAverage();
548 else
549 PlotFourier();
550
551 fFourierPad->Draw();
552 fMainCanvas->cd();
553 fMainCanvas->Update();
554}
555
556//--------------------------------------------------------------------------
557// UpdateInfoPad (public)
558//--------------------------------------------------------------------------
563{
564 if (!fValid)
565 return;
566
567 // write header line
568 TDatime dt;
569 Char_t dtStr[128];
570 strncpy(dtStr, dt.AsSQLString(), sizeof(dtStr));
571 TString str("musrFT: ");
572 str += dtStr;
573 fInfoPad->SetHeader(str);
574
575 Char_t title[1024];
576 for (UInt_t i=0; i<fFourier.size(); i++) {
577 strncpy(title, fFourier[i]->GetDataTitle(), sizeof(title));
578 // add entry
579 fInfoPad->AddEntry(fFourierHistos[i].dataFourierRe, title, "p");
580 }
581
582 fInfoPad->Draw();
583 fMainCanvas->cd();
584 fMainCanvas->Update();
585}
586
587//--------------------------------------------------------------------------
588// SetTimeout (public)
589//--------------------------------------------------------------------------
613{
615
616 if (fTimeout <= 0)
617 return;
618
619 fTimeoutTimer.reset(new TTimer());
620
621 fTimeoutTimer->Connect("Timeout()", "PFourierCanvas", this, "Done()");
622
623 fTimeoutTimer->Start(1000*fTimeout, kTRUE);
624}
625
626//--------------------------------------------------------------------------
627// SaveGraphicsAndQuit
628//--------------------------------------------------------------------------
657void PFourierCanvas::SaveGraphicsAndQuit(const Char_t *fileName)
658{
659 std::cout << std::endl << ">> SaveGraphicsAndQuit: will dump the canvas into a graphics output file: " << fileName << " ..." << std::endl;
660
661 fMainCanvas->SaveAs(fileName);
662
663 Done(0);
664}
665
666//--------------------------------------------------------------------------
667// ExportData
668//--------------------------------------------------------------------------
709void PFourierCanvas::ExportData(const Char_t *pathFileName)
710{
711 TString pfn("");
712
713 if (pathFileName) { // path file name provided
714 pfn = TString(pathFileName);
715 } else { // path file name NOT provided, generate a default path file name
716 std::cerr << std::endl << ">> PFourierCanvas::ExportData **ERROR** NO path file name provided. Will do nothing." << std::endl;
717 return;
718 }
719
720 TString xAxis(""), yAxis("");
721 Int_t xMinBin, xMaxBin;
722 if (fAveragedView) {
723 switch (fCurrentPlotView) {
725 xAxis = fFourierHistos[0].dataFourierRe->GetXaxis()->GetTitle();
726 yAxis = TString("<Real>");
727 xMinBin = fFourierHistos[0].dataFourierRe->GetXaxis()->GetFirst();
728 xMaxBin = fFourierHistos[0].dataFourierRe->GetXaxis()->GetLast();
729 break;
731 xAxis = fFourierHistos[0].dataFourierIm->GetXaxis()->GetTitle();
732 yAxis = TString("<Imag>");
733 xMinBin = fFourierHistos[0].dataFourierIm->GetXaxis()->GetFirst();
734 xMaxBin = fFourierHistos[0].dataFourierIm->GetXaxis()->GetLast();
735 break;
737 xAxis = fFourierHistos[0].dataFourierPwr->GetXaxis()->GetTitle();
738 yAxis = TString("<Power>");
739 xMinBin = fFourierHistos[0].dataFourierPwr->GetXaxis()->GetFirst();
740 xMaxBin = fFourierHistos[0].dataFourierPwr->GetXaxis()->GetLast();
741 break;
743 xAxis = fFourierHistos[0].dataFourierPhase->GetXaxis()->GetTitle();
744 yAxis = TString("<Phase>");
745 xMinBin = fFourierHistos[0].dataFourierPhase->GetXaxis()->GetFirst();
746 xMaxBin = fFourierHistos[0].dataFourierPhase->GetXaxis()->GetLast();
747 break;
749 xAxis = fFourierHistos[0].dataFourierPhaseOptReal->GetXaxis()->GetTitle();
750 yAxis = TString("<Phase>");
751 xMinBin = fFourierHistos[0].dataFourierPhaseOptReal->GetXaxis()->GetFirst();
752 xMaxBin = fFourierHistos[0].dataFourierPhaseOptReal->GetXaxis()->GetLast();
753 break;
754 default:
755 xAxis = TString("??");
756 yAxis = TString("??");
757 xMinBin = 0;
758 xMaxBin = 0;
759 break;
760 }
761 } else {
762 switch (fCurrentPlotView) {
764 xAxis = fFourierHistos[0].dataFourierRe->GetXaxis()->GetTitle();
765 yAxis = TString("Real");
766 xMinBin = fFourierHistos[0].dataFourierRe->GetXaxis()->GetFirst();
767 xMaxBin = fFourierHistos[0].dataFourierRe->GetXaxis()->GetLast();
768 break;
770 xAxis = fFourierHistos[0].dataFourierIm->GetXaxis()->GetTitle();
771 yAxis = TString("Imag");
772 xMinBin = fFourierHistos[0].dataFourierIm->GetXaxis()->GetFirst();
773 xMaxBin = fFourierHistos[0].dataFourierIm->GetXaxis()->GetLast();
774 break;
776 xAxis = fFourierHistos[0].dataFourierRe->GetXaxis()->GetTitle();
777 yAxis = TString("Real+Imag");
778 xMinBin = fFourierHistos[0].dataFourierRe->GetXaxis()->GetFirst();
779 xMaxBin = fFourierHistos[0].dataFourierRe->GetXaxis()->GetLast();
780 break;
782 xAxis = fFourierHistos[0].dataFourierPwr->GetXaxis()->GetTitle();
783 yAxis = TString("Power");
784 xMinBin = fFourierHistos[0].dataFourierPwr->GetXaxis()->GetFirst();
785 xMaxBin = fFourierHistos[0].dataFourierPwr->GetXaxis()->GetLast();
786 break;
788 xAxis = fFourierHistos[0].dataFourierPhase->GetXaxis()->GetTitle();
789 yAxis = TString("Phase");
790 xMinBin = fFourierHistos[0].dataFourierPhase->GetXaxis()->GetFirst();
791 xMaxBin = fFourierHistos[0].dataFourierPhase->GetXaxis()->GetLast();
792 break;
794 xAxis = fFourierHistos[0].dataFourierPhaseOptReal->GetXaxis()->GetTitle();
795 yAxis = TString("Phase");
796 xMinBin = fFourierHistos[0].dataFourierPhaseOptReal->GetXaxis()->GetFirst();
797 xMaxBin = fFourierHistos[0].dataFourierPhaseOptReal->GetXaxis()->GetLast();
798 break;
799 default:
800 xAxis = TString("??");
801 yAxis = TString("??");
802 xMinBin = 0;
803 xMaxBin = 0;
804 break;
805 }
806 }
807
808 // write data to file
809 std::ofstream fout(pfn.Data(), std::ofstream::out);
810
811 if (fAveragedView) {
812 // write header
813 fout << "% " << pfn << std::endl;
814 fout << "% averaged data of:" << std::endl;
815 for (UInt_t i=0; i<fFourierHistos.size(); i++) {
816 fout << "% " << fFourierHistos[i].dataFourierRe->GetTitle() << std::endl;
817 }
818 fout << "%------------" << std::endl;
819 fout << "% " << xAxis << ", " << yAxis << std::endl;
820 for (Int_t i=xMinBin; i<xMaxBin; i++) {
821 switch (fCurrentPlotView) {
823 fout << fFourierAverage[0].dataFourierRe->GetBinCenter(i) << ", " << fFourierAverage[0].dataFourierRe->GetBinContent(i) << std::endl;
824 break;
826 fout << fFourierAverage[0].dataFourierIm->GetBinCenter(i) << ", " << fFourierAverage[0].dataFourierIm->GetBinContent(i) << std::endl;
827 break;
829 fout << fFourierAverage[0].dataFourierPwr->GetBinCenter(i) << ", " << fFourierAverage[0].dataFourierPwr->GetBinContent(i) << std::endl;
830 break;
832 fout << fFourierAverage[0].dataFourierPhase->GetBinCenter(i) << ", " << fFourierAverage[0].dataFourierPhase->GetBinContent(i) << std::endl;
833 break;
835 fout << fFourierAverage[0].dataFourierPhaseOptReal->GetBinCenter(i) << ", " << fFourierAverage[0].dataFourierPhaseOptReal->GetBinContent(i) << std::endl;
836 break;
837 default:
838 break;
839 }
840 }
841 } else {
842 // write header
843 fout << "% " << pfn << std::endl;
844 fout << "% data of:" << std::endl;
845 for (UInt_t i=0; i<fFourierHistos.size(); i++) {
846 fout << "% " << fFourierHistos[i].dataFourierRe->GetTitle() << std::endl;
847 }
848 fout << "%------------" << std::endl;
849 fout << "% ";
850 for (UInt_t i=0; i<fFourierHistos.size()-1; i++) {
851 fout << xAxis << i << ", " << yAxis << i << ", ";
852 }
853 fout << xAxis << fFourierHistos.size()-1 << ", " << yAxis << fFourierHistos.size()-1 << std::endl;
854
855 // write data
856 for (Int_t i=xMinBin; i<xMaxBin; i++) {
857 for (UInt_t j=0; j<fFourierHistos.size()-1; j++) {
858 switch (fCurrentPlotView) {
860 fout << fFourierHistos[j].dataFourierRe->GetBinCenter(i) << ", " << fFourierHistos[j].dataFourierRe->GetBinContent(i) << ", ";
861 break;
863 fout << fFourierHistos[j].dataFourierIm->GetBinCenter(i) << ", " << fFourierHistos[j].dataFourierIm->GetBinContent(i) << ", ";
864 break;
866 break;
868 fout << fFourierHistos[j].dataFourierPwr->GetBinCenter(i) << ", " << fFourierHistos[j].dataFourierPwr->GetBinContent(i) << ", ";
869 break;
871 fout << fFourierHistos[j].dataFourierPhase->GetBinCenter(i) << ", " << fFourierHistos[j].dataFourierPhase->GetBinContent(i) << ", ";
872 break;
874 fout << fFourierHistos[j].dataFourierPhaseOptReal->GetBinCenter(i) << ", " << fFourierHistos[j].dataFourierPhaseOptReal->GetBinContent(i) << ", ";
875 break;
876 default:
877 break;
878 }
879 }
880 switch (fCurrentPlotView) {
882 fout << fFourierHistos[fFourierHistos.size()-1].dataFourierRe->GetBinCenter(i) << ", " << fFourierHistos[fFourierHistos.size()-1].dataFourierRe->GetBinContent(i) << std::endl;
883 break;
885 fout << fFourierHistos[fFourierHistos.size()-1].dataFourierIm->GetBinCenter(i) << ", " << fFourierHistos[fFourierHistos.size()-1].dataFourierIm->GetBinContent(i) << std::endl;
886 break;
888 break;
890 fout << fFourierHistos[fFourierHistos.size()-1].dataFourierPwr->GetBinCenter(i) << ", " << fFourierHistos[fFourierHistos.size()-1].dataFourierPwr->GetBinContent(i) << std::endl;
891 break;
893 fout << fFourierHistos[fFourierHistos.size()-1].dataFourierPhase->GetBinCenter(i) << ", " << fFourierHistos[fFourierHistos.size()-1].dataFourierPhase->GetBinContent(i) << std::endl;
894 break;
896 fout << fFourierHistos[fFourierHistos.size()-1].dataFourierPhaseOptReal->GetBinCenter(i) << ", " << fFourierHistos[fFourierHistos.size()-1].dataFourierPhaseOptReal->GetBinContent(i) << std::endl;
897 break;
898 default:
899 break;
900 }
901 }
902 }
903
904 fout.close();
905}
906
907//--------------------------------------------------------------------------
908// CreateXaxisTitle (private)
909//--------------------------------------------------------------------------
914{
915 switch (fFourier[0]->GetUnitTag()) {
917 fXaxisTitle = TString("Field (Gauss)");
918 break;
920 fXaxisTitle = TString("Field (Tesla)");
921 break;
923 fXaxisTitle = TString("Frequency (MHz)");
924 break;
926 fXaxisTitle = TString("Angular Frequency (Mc/s)");
927 break;
928 default:
929 fXaxisTitle = TString("??");
930 break;
931 }
932}
933
934//--------------------------------------------------------------------------
935// CreateStyle (private)
936//--------------------------------------------------------------------------
941{
942 TString musrFTStyle("musrFTStyle");
943 fStyle = std::make_unique<TStyle>(musrFTStyle, musrFTStyle);
944 fStyle->SetOptStat(0); // no statistics options
945 fStyle->SetOptTitle(0); // no title
946 fStyle->cd();
947}
948
949//--------------------------------------------------------------------------
950// InitFourierDataSets (private)
951//--------------------------------------------------------------------------
957{
958 // get all the Fourier histos
959 fFourierHistos.resize(fFourier.size());
960 for (UInt_t i=0; i<fFourierHistos.size(); i++) {
961 fFourierHistos[i].dataFourierRe = fFourier[i]->GetRealFourier();
962 fFourierHistos[i].dataFourierIm = fFourier[i]->GetImaginaryFourier();
963 fFourierHistos[i].dataFourierPwr = fFourier[i]->GetPowerFourier();
964 fFourierHistos[i].dataFourierPhase = fFourier[i]->GetPhaseFourier();
966 fFourierHistos[i].dataFourierPhaseOptReal = fFourier[i]->GetPhaseOptRealFourier(fFourierHistos[i].dataFourierRe,
967 fFourierHistos[i].dataFourierIm, fFourierHistos[i].optPhase, 1.0, fInitialXRange[0], fInitialXRange[1]);
968 }
969 }
970
971 // rescale histo to abs(maximum) == 1
972 Double_t max = 0.0, dval = 0.0;
973 Int_t start = fFourierHistos[0].dataFourierRe->FindBin(fInitialXRange[0]);
974 Int_t end = fFourierHistos[0].dataFourierRe->FindBin(fInitialXRange[1]);
975 // real
976 for (UInt_t i=0; i<fFourierHistos.size(); i++) {
977 for (Int_t j=start; j<=end; j++) {
978 dval = fFourierHistos[i].dataFourierRe->GetBinContent(j);
979 if (fabs(dval) > max)
980 max = dval;
981 }
982 }
983 for (UInt_t i=0; i<fFourierHistos.size(); i++) {
984 for (Int_t j=1; j<fFourierHistos[i].dataFourierRe->GetNbinsX(); j++) {
985 fFourierHistos[i].dataFourierRe->SetBinContent(j, fFourierHistos[i].dataFourierRe->GetBinContent(j)/fabs(max));
986 }
987 }
988
989 // imaginary
990 for (UInt_t i=0; i<fFourierHistos.size(); i++) {
991 for (Int_t j=start; j<=end; j++) {
992 dval = fFourierHistos[i].dataFourierIm->GetBinContent(j);
993 if (fabs(dval) > max)
994 max = dval;
995 }
996 }
997 for (UInt_t i=0; i<fFourierHistos.size(); i++) {
998 for (Int_t j=1; j<fFourierHistos[i].dataFourierIm->GetNbinsX(); j++) {
999 fFourierHistos[i].dataFourierIm->SetBinContent(j, fFourierHistos[i].dataFourierIm->GetBinContent(j)/fabs(max));
1000 }
1001 }
1002
1003 // power
1004 max = 0.0;
1005 for (UInt_t i=0; i<fFourierHistos.size(); i++) {
1006 for (Int_t j=start; j<=end; j++) {
1007 dval = fFourierHistos[i].dataFourierPwr->GetBinContent(j);
1008 if (fabs(dval) > max)
1009 max = dval;
1010 }
1011 }
1012 for (UInt_t i=0; i<fFourierHistos.size(); i++) {
1013 for (Int_t j=1; j<fFourierHistos[i].dataFourierPwr->GetNbinsX(); j++) {
1014 fFourierHistos[i].dataFourierPwr->SetBinContent(j, fFourierHistos[i].dataFourierPwr->GetBinContent(j)/fabs(max));
1015 }
1016 }
1017
1018 // phase
1019 max = 0.0;
1020 for (UInt_t i=0; i<fFourierHistos.size(); i++) {
1021 for (Int_t j=start; j<=end; j++) {
1022 dval = fFourierHistos[i].dataFourierPhase->GetBinContent(j);
1023 if (fabs(dval) > max)
1024 max = dval;
1025 }
1026 }
1027 for (UInt_t i=0; i<fFourierHistos.size(); i++) {
1028 for (Int_t j=1; j<fFourierHistos[i].dataFourierPhase->GetNbinsX(); j++) {
1029 fFourierHistos[i].dataFourierPhase->SetBinContent(j, fFourierHistos[i].dataFourierPhase->GetBinContent(j)/fabs(max));
1030 }
1031 }
1032
1034 // phase opt real
1035 for (UInt_t i=0; i<fFourierHistos.size(); i++) {
1036 for (Int_t j=start; j<=end; j++) {
1037 dval = fFourierHistos[i].dataFourierPhaseOptReal->GetBinContent(j);
1038 if (fabs(dval) > max)
1039 max = dval;
1040 }
1041 }
1042 for (UInt_t i=0; i<fFourierHistos.size(); i++) {
1043 for (Int_t j=1; j<fFourierHistos[i].dataFourierPhaseOptReal->GetNbinsX(); j++) {
1044 fFourierHistos[i].dataFourierPhaseOptReal->SetBinContent(j, fFourierHistos[i].dataFourierPhaseOptReal->GetBinContent(j)/fabs(max));
1045 }
1046 }
1047 }
1048
1049 // set the marker and line color
1050 for (UInt_t i=0; i<fFourierHistos.size(); i++) {
1051 fFourierHistos[i].dataFourierRe->SetMarkerColor(fColorList[i]);
1052 fFourierHistos[i].dataFourierRe->SetLineColor(fColorList[i]);
1053 fFourierHistos[i].dataFourierIm->SetMarkerColor(fColorList[i]);
1054 fFourierHistos[i].dataFourierIm->SetLineColor(fColorList[i]);
1055 fFourierHistos[i].dataFourierPwr->SetMarkerColor(fColorList[i]);
1056 fFourierHistos[i].dataFourierPwr->SetLineColor(fColorList[i]);
1057 fFourierHistos[i].dataFourierPhase->SetMarkerColor(fColorList[i]);
1058 fFourierHistos[i].dataFourierPhase->SetLineColor(fColorList[i]);
1060 fFourierHistos[i].dataFourierPhaseOptReal->SetMarkerColor(fColorList[i]);
1061 fFourierHistos[i].dataFourierPhaseOptReal->SetLineColor(fColorList[i]);
1062 }
1063 }
1064
1065 // set the marker symbol and size
1066 for (UInt_t i=0; i<fFourierHistos.size(); i++) {
1067 fFourierHistos[i].dataFourierRe->SetMarkerStyle(fMarkerList[i]);
1068 fFourierHistos[i].dataFourierRe->SetMarkerSize(0.7);
1069 fFourierHistos[i].dataFourierIm->SetMarkerStyle(fMarkerList[i]);
1070 fFourierHistos[i].dataFourierIm->SetMarkerSize(0.7);
1071 fFourierHistos[i].dataFourierPwr->SetMarkerStyle(fMarkerList[i]);
1072 fFourierHistos[i].dataFourierPwr->SetMarkerSize(0.7);
1073 fFourierHistos[i].dataFourierPhase->SetMarkerStyle(fMarkerList[i]);
1074 fFourierHistos[i].dataFourierPhase->SetMarkerSize(0.7);
1076 fFourierHistos[i].dataFourierPhaseOptReal->SetMarkerStyle(fMarkerList[i]);
1077 fFourierHistos[i].dataFourierPhaseOptReal->SetMarkerSize(0.7);
1078 }
1079 }
1080
1081 // initialize average histos
1083}
1084
1085//--------------------------------------------------------------------------
1086// InitFourierCanvas (private)
1087//--------------------------------------------------------------------------
1097void PFourierCanvas::InitFourierCanvas(const Char_t* title, Int_t wtopx, Int_t wtopy, Int_t ww, Int_t wh)
1098{
1099 fImp = nullptr;
1100 fBar = nullptr;
1101 fPopupMain = nullptr;
1102
1103 // invoke canvas
1104 TString canvasName = TString("fMainCanvas");
1105 fMainCanvas = std::make_unique<TCanvas>(canvasName.Data(), title, wtopx, wtopy, ww, wh);
1106
1107 // add canvas menu if not in batch mode
1108 if (!fBatchMode) {
1109 fImp = static_cast<TRootCanvas*>(fMainCanvas->GetCanvasImp());
1110 fBar = fImp->GetMenuBar();
1111 fPopupMain = fBar->AddPopup("MusrFT");
1112
1113 fPopupFourier = std::make_unique<TGPopupMenu>();
1114
1115 fPopupMain->AddPopup("&Fourier", fPopupFourier.get());
1119 fPopupFourier->AddEntry("Show Power", P_MENU_ID_FOURIER+P_MENU_ID_FOURIER_PWR);
1121 fPopupFourier->AddEntry("Show Phase Opt Fourier", P_MENU_ID_FOURIER+P_MENU_ID_FOURIER_PHASE_OPT_REAL);
1122 fPopupFourier->AddSeparator();
1127
1128 switch (fCurrentPlotView) {
1129 case FOURIER_PLOT_REAL:
1131 break;
1132 case FOURIER_PLOT_IMAG:
1134 break;
1137 break;
1138 case FOURIER_PLOT_POWER:
1140 break;
1141 case FOURIER_PLOT_PHASE:
1143 break;
1146 break;
1147 default:
1148 break;
1149 }
1150
1151 fPopupMain->AddEntry("Average", P_MENU_ID_AVERAGE);
1152 if (fAveragedView)
1153 fPopupMain->CheckEntry(P_MENU_ID_AVERAGE);
1154 fPopupMain->AddEntry("Average per Data Set", P_MENU_ID_AVERAGE_PER_DATA_SET);
1157 fPopupMain->AddSeparator();
1158
1159 fPopupMain->AddEntry("Export Data", P_MENU_ID_EXPORT_DATA);
1160 fBar->MapSubwindows();
1161 fBar->Layout();
1162
1163 fPopupMain->Connect("TGPopupMenu", "Activated(Int_t)", "PFourierCanvas", this, "HandleMenuPopup(Int_t)");
1164 }
1165
1166 // divide the canvas into sub pads
1167 // title pad
1168 fTitlePad = std::make_unique<TPaveText>(0.0, YTITLE, 1.0, 1.0, "NDC");
1169
1170 fTitlePad->SetFillColor(TColor::GetColor(255,255,255));
1171 fTitlePad->SetTextAlign(12); // middle, left
1172 fTitlePad->AddText(title);
1173 fTitlePad->Draw();
1174
1175 // fourier pad
1176 fFourierPad = std::make_unique<TPad>("fFourierPad", "fFourierPad", 0.0, YINFO, 1.0, YTITLE);
1177
1178 fFourierPad->SetFillColor(TColor::GetColor(255,255,255));
1179 fFourierPad->Draw();
1180
1181 // info pad
1182 fInfoPad = std::make_unique<TLegend>(0.0, 0.0, 1.0, YINFO, "NDC");
1183
1184 fInfoPad->SetFillColor(TColor::GetColor(255,255,255));
1185 fInfoPad->SetTextAlign(12); // middle, left
1186
1187 fValid = true;
1188
1189 if ((fFourier.size() != fDataSetTag.size()) && fAveragedViewPerDataSet) {
1190 fValid = false;
1191 std::cerr << std::endl << "PFourierCanvas::PFourierCanvas: **PANIC ERROR**: # Fourier != # Data Set Tags." << std::endl;
1192 }
1193
1194 fMainCanvas->cd();
1195
1196 fMainCanvas->Show();
1197
1198 fMainCanvas->Connect("ProcessedEvent(Int_t,Int_t,Int_t,TObject*)", "PFourierCanvas",
1199 this, "HandleCmdKey(Int_t,Int_t,Int_t,TObject*)");
1200}
1201
1202//--------------------------------------------------------------------------
1203// CleanupAverage (private)
1204//--------------------------------------------------------------------------
1209{
1210 for (UInt_t i=0; i<fFourierAverage.size(); i++) {
1211 if (fFourierAverage[i].dataFourierRe != nullptr) {
1212 delete fFourierAverage[i].dataFourierRe;
1213 fFourierAverage[i].dataFourierRe = nullptr;
1214 }
1215 if (fFourierAverage[i].dataFourierIm) {
1216 delete fFourierAverage[i].dataFourierIm;
1217 fFourierAverage[i].dataFourierIm = nullptr;
1218 }
1219 if (fFourierAverage[i].dataFourierPwr) {
1220 delete fFourierAverage[i].dataFourierPwr;
1221 fFourierAverage[i].dataFourierPwr = nullptr;
1222 }
1223 if (fFourierAverage[i].dataFourierPhase) {
1224 delete fFourierAverage[i].dataFourierPhase;
1225 fFourierAverage[i].dataFourierPhase = nullptr;
1226 }
1227 if (fFourierAverage[i].dataFourierPhaseOptReal) {
1228 delete fFourierAverage[i].dataFourierPhaseOptReal;
1229 fFourierAverage[i].dataFourierPhaseOptReal = nullptr;
1230 }
1231 }
1232 fFourierAverage.clear();
1233}
1234
1235//--------------------------------------------------------------------------
1236// HandleAverage (private)
1237//--------------------------------------------------------------------------
1242{
1243 if (fFourierHistos.size() == 0)
1244 return;
1245
1247
1248 TString name("");
1249 Double_t dval=0.0;
1250
1251 Bool_t phaseOptRealPresent = false;
1252 if (fFourierHistos[0].dataFourierPhaseOptReal != nullptr)
1253 phaseOptRealPresent = true;
1254
1255 // check if ALL data shall be averaged
1256 if (fAveragedView) {
1257 fFourierAverage.resize(1);
1258
1259 // create average histograms
1260 name = TString(fFourierHistos[0].dataFourierRe->GetTitle()) + "_avg";
1261 fFourierAverage[0].dataFourierRe = new TH1F(name, name, fFourierHistos[0].dataFourierRe->GetNbinsX(),
1262 fFourierHistos[0].dataFourierRe->GetXaxis()->GetXmin(),
1263 fFourierHistos[0].dataFourierRe->GetXaxis()->GetXmax());
1264
1265 name = TString(fFourierHistos[0].dataFourierIm->GetTitle()) + "_avg";
1266 fFourierAverage[0].dataFourierIm = new TH1F(name, name, fFourierHistos[0].dataFourierIm->GetNbinsX(),
1267 fFourierHistos[0].dataFourierIm->GetXaxis()->GetXmin(),
1268 fFourierHistos[0].dataFourierIm->GetXaxis()->GetXmax());
1269
1270 name = TString(fFourierHistos[0].dataFourierPwr->GetTitle()) + "_avg";
1271 fFourierAverage[0].dataFourierPwr = new TH1F(name, name, fFourierHistos[0].dataFourierPwr->GetNbinsX(),
1272 fFourierHistos[0].dataFourierPwr->GetXaxis()->GetXmin(),
1273 fFourierHistos[0].dataFourierPwr->GetXaxis()->GetXmax());
1274
1275 name = TString(fFourierHistos[0].dataFourierPhase->GetTitle()) + "_avg";
1276 fFourierAverage[0].dataFourierPhase = new TH1F(name, name, fFourierHistos[0].dataFourierPhase->GetNbinsX(),
1277 fFourierHistos[0].dataFourierPhase->GetXaxis()->GetXmin(),
1278 fFourierHistos[0].dataFourierPhase->GetXaxis()->GetXmax());
1279
1280 if (phaseOptRealPresent) {
1281 name = TString(fFourierHistos[0].dataFourierPhaseOptReal->GetTitle()) + "_avg";
1282 fFourierAverage[0].dataFourierPhaseOptReal = new TH1F(name, name, fFourierHistos[0].dataFourierPhaseOptReal->GetNbinsX(),
1283 fFourierHistos[0].dataFourierPhaseOptReal->GetXaxis()->GetXmin(),
1284 fFourierHistos[0].dataFourierPhaseOptReal->GetXaxis()->GetXmax());
1285 }
1286
1287 // real average
1288 for (Int_t j=0; j<fFourierHistos[0].dataFourierRe->GetNbinsX(); j++) {
1289 dval = 0.0;
1290 for (UInt_t i=0; i<fFourierHistos.size(); i++) {
1291 if (j < fFourierHistos[i].dataFourierRe->GetNbinsX())
1292 dval += GetInterpolatedValue(fFourierHistos[i].dataFourierRe, fFourierHistos[0].dataFourierRe->GetBinCenter(j));
1293 }
1294 fFourierAverage[0].dataFourierRe->SetBinContent(j, dval/fFourierHistos.size());
1295 }
1296 // set marker color, line color, maker size, marker type
1297 fFourierAverage[0].dataFourierRe->SetMarkerColor(kBlack);
1298 fFourierAverage[0].dataFourierRe->SetLineColor(kBlack);
1299 fFourierAverage[0].dataFourierRe->SetMarkerSize(0.8);
1300 fFourierAverage[0].dataFourierRe->SetMarkerStyle(22); // closed up triangle
1301
1302 // imaginary average
1303 for (Int_t j=0; j<fFourierHistos[0].dataFourierIm->GetNbinsX(); j++) {
1304 dval = 0.0;
1305 for (UInt_t i=0; i<fFourierHistos.size(); i++) {
1306 if (j < fFourierHistos[i].dataFourierIm->GetNbinsX())
1307 dval += GetInterpolatedValue(fFourierHistos[i].dataFourierIm, fFourierHistos[0].dataFourierIm->GetBinCenter(j));
1308 }
1309 fFourierAverage[0].dataFourierIm->SetBinContent(j, dval/fFourierHistos.size());
1310 }
1311 // set marker color, line color, maker size, marker type
1312 fFourierAverage[0].dataFourierIm->SetMarkerColor(kBlack);
1313 fFourierAverage[0].dataFourierIm->SetLineColor(kBlack);
1314 fFourierAverage[0].dataFourierIm->SetMarkerSize(0.8);
1315 fFourierAverage[0].dataFourierIm->SetMarkerStyle(22); // closed up triangle
1316
1317 // power average
1318 for (Int_t j=0; j<fFourierHistos[0].dataFourierPwr->GetNbinsX(); j++) {
1319 dval = 0.0;
1320 for (UInt_t i=0; i<fFourierHistos.size(); i++) {
1321 if (j < fFourierHistos[i].dataFourierPwr->GetNbinsX())
1322 dval += GetInterpolatedValue(fFourierHistos[i].dataFourierPwr, fFourierHistos[0].dataFourierPwr->GetBinCenter(j));
1323 }
1324 fFourierAverage[0].dataFourierPwr->SetBinContent(j, dval/fFourierHistos.size());
1325 }
1326 // set marker color, line color, maker size, marker type
1327 fFourierAverage[0].dataFourierPwr->SetMarkerColor(kBlack);
1328 fFourierAverage[0].dataFourierPwr->SetLineColor(kBlack);
1329 fFourierAverage[0].dataFourierPwr->SetMarkerSize(0.8);
1330 fFourierAverage[0].dataFourierPwr->SetMarkerStyle(22); // closed up triangle
1331
1332 // phase average
1333 for (Int_t j=0; j<fFourierHistos[0].dataFourierPhase->GetNbinsX(); j++) {
1334 dval = 0.0;
1335 for (UInt_t i=0; i<fFourierHistos.size(); i++) {
1336 if (j < fFourierHistos[i].dataFourierPhase->GetNbinsX())
1337 dval += GetInterpolatedValue(fFourierHistos[i].dataFourierPhase, fFourierHistos[0].dataFourierPhase->GetBinCenter(j));
1338 }
1339 fFourierAverage[0].dataFourierPhase->SetBinContent(j, dval/fFourierHistos.size());
1340 }
1341 // set marker color, line color, maker size, marker type
1342 fFourierAverage[0].dataFourierPhase->SetMarkerColor(kBlack);
1343 fFourierAverage[0].dataFourierPhase->SetLineColor(kBlack);
1344 fFourierAverage[0].dataFourierPhase->SetMarkerSize(0.8);
1345 fFourierAverage[0].dataFourierPhase->SetMarkerStyle(22);
1346
1347 if (phaseOptRealPresent) {
1348 // phase optimised real average
1349 for (Int_t j=0; j<fFourierHistos[0].dataFourierPhaseOptReal->GetNbinsX(); j++) {
1350 dval = 0.0;
1351 for (UInt_t i=0; i<fFourierHistos.size(); i++) {
1352 if (j < fFourierHistos[i].dataFourierPhaseOptReal->GetNbinsX())
1353 dval += GetInterpolatedValue(fFourierHistos[i].dataFourierPhaseOptReal, fFourierHistos[0].dataFourierPhaseOptReal->GetBinCenter(j));
1354 }
1355 fFourierAverage[0].dataFourierPhaseOptReal->SetBinContent(j, dval/fFourierHistos.size());
1356 }
1357 // set marker color, line color, maker size, marker type
1358 fFourierAverage[0].dataFourierPhaseOptReal->SetMarkerColor(kBlack);
1359 fFourierAverage[0].dataFourierPhaseOptReal->SetLineColor(kBlack);
1360 fFourierAverage[0].dataFourierPhaseOptReal->SetMarkerSize(0.8);
1361 fFourierAverage[0].dataFourierPhaseOptReal->SetMarkerStyle(22);
1362 }
1363 }
1364
1365 // check if per data set shall be averaged
1367 // check what size is required
1368 UInt_t count = 1;
1369 Int_t currentTag = fDataSetTag[0];
1370 for (UInt_t i=1; i<fDataSetTag.size(); i++) {
1371 if (fDataSetTag[i] != currentTag) {
1372 currentTag = fDataSetTag[i];
1373 count++;
1374 }
1375 }
1376 fFourierAverage.resize(count);
1377
1378 Int_t start=0, end=0;
1379 for (UInt_t i=0; i<fFourierAverage.size(); i++) {
1380 // get data set range
1381 count = 0;
1382 currentTag = fDataSetTag[0];
1383 start = -1, end = -1;
1384 for (UInt_t j=0; j<fDataSetTag.size(); j++) {
1385 if ((count == i) && (start == -1)) {
1386 if (j > 0)
1387 start = j-1;
1388 else
1389 start = 0;
1390 }
1391 if (currentTag != fDataSetTag[j]) {
1392 if (count == i) {
1393 end = j-1;
1394 break;
1395 }
1396 count++;
1397 currentTag = fDataSetTag[j];
1398 }
1399 }
1400 if (start == -1)
1401 start = fDataSetTag.size()-1;
1402 if (end == -1)
1403 end = fDataSetTag.size()-1;
1404
1405 // create average histograms
1406 name = TString(fFourierHistos[start].dataFourierRe->GetTitle()) + "_avg";
1407 fFourierAverage[i].dataFourierRe = new TH1F(name, name, fFourierHistos[0].dataFourierRe->GetNbinsX(),
1408 fFourierHistos[0].dataFourierRe->GetXaxis()->GetXmin(),
1409 fFourierHistos[0].dataFourierRe->GetXaxis()->GetXmax());
1410
1411 name = TString(fFourierHistos[start].dataFourierIm->GetTitle()) + "_avg";
1412 fFourierAverage[i].dataFourierIm = new TH1F(name, name, fFourierHistos[0].dataFourierIm->GetNbinsX(),
1413 fFourierHistos[0].dataFourierIm->GetXaxis()->GetXmin(),
1414 fFourierHistos[0].dataFourierIm->GetXaxis()->GetXmax());
1415
1416 name = TString(fFourierHistos[start].dataFourierPwr->GetTitle()) + "_avg";
1417 fFourierAverage[i].dataFourierPwr = new TH1F(name, name, fFourierHistos[0].dataFourierPwr->GetNbinsX(),
1418 fFourierHistos[0].dataFourierPwr->GetXaxis()->GetXmin(),
1419 fFourierHistos[0].dataFourierPwr->GetXaxis()->GetXmax());
1420
1421 name = TString(fFourierHistos[start].dataFourierPhase->GetTitle()) + "_avg";
1422 fFourierAverage[i].dataFourierPhase = new TH1F(name, name, fFourierHistos[0].dataFourierPhase->GetNbinsX(),
1423 fFourierHistos[0].dataFourierPhase->GetXaxis()->GetXmin(),
1424 fFourierHistos[0].dataFourierPhase->GetXaxis()->GetXmax());
1425
1426 if (phaseOptRealPresent) {
1427 name = TString(fFourierHistos[start].dataFourierPhaseOptReal->GetTitle()) + "_avg";
1428 fFourierAverage[i].dataFourierPhaseOptReal = new TH1F(name, name, fFourierHistos[0].dataFourierPhaseOptReal->GetNbinsX(),
1429 fFourierHistos[0].dataFourierPhaseOptReal->GetXaxis()->GetXmin(),
1430 fFourierHistos[0].dataFourierPhaseOptReal->GetXaxis()->GetXmax());
1431 }
1432
1433 // real average
1434 for (Int_t j=0; j<fFourierHistos[0].dataFourierRe->GetNbinsX(); j++) {
1435 dval = 0.0;
1436 for (Int_t k=start; k<=end; k++) {
1437 if (j < fFourierHistos[k].dataFourierRe->GetNbinsX())
1438 dval += GetInterpolatedValue(fFourierHistos[k].dataFourierRe, fFourierHistos[0].dataFourierRe->GetBinCenter(j));
1439 }
1440 fFourierAverage[i].dataFourierRe->SetBinContent(j, dval/(end-start+1));
1441 }
1442 // set marker color, line color, maker size, marker type
1443 fFourierAverage[i].dataFourierRe->SetMarkerColor(fColorList[i]);
1444 fFourierAverage[i].dataFourierRe->SetLineColor(fColorList[i]);
1445 fFourierAverage[i].dataFourierRe->SetMarkerSize(0.8);
1446 fFourierAverage[i].dataFourierRe->SetMarkerStyle(22); // closed up triangle
1447
1448 // imaginary average
1449 for (Int_t j=0; j<fFourierHistos[0].dataFourierIm->GetNbinsX(); j++) {
1450 dval = 0.0;
1451 for (Int_t k=start; k<=end; k++) {
1452 if (j < fFourierHistos[k].dataFourierIm->GetNbinsX())
1453 dval += GetInterpolatedValue(fFourierHistos[k].dataFourierIm, fFourierHistos[0].dataFourierIm->GetBinCenter(j));
1454 }
1455 fFourierAverage[i].dataFourierIm->SetBinContent(j, dval/(end-start+1));
1456 }
1457 // set marker color, line color, maker size, marker type
1458 fFourierAverage[i].dataFourierIm->SetMarkerColor(fColorList[i]);
1459 fFourierAverage[i].dataFourierIm->SetLineColor(fColorList[i]);
1460 fFourierAverage[i].dataFourierIm->SetMarkerSize(0.8);
1461 fFourierAverage[i].dataFourierIm->SetMarkerStyle(22); // closed up triangle
1462
1463 // power average
1464 for (Int_t j=0; j<fFourierHistos[0].dataFourierPwr->GetNbinsX(); j++) {
1465 dval = 0.0;
1466 for (Int_t k=start; k<=end; k++) {
1467 if (j < fFourierHistos[k].dataFourierPwr->GetNbinsX())
1468 dval += GetInterpolatedValue(fFourierHistos[k].dataFourierPwr, fFourierHistos[0].dataFourierPwr->GetBinCenter(j));
1469 }
1470 fFourierAverage[i].dataFourierPwr->SetBinContent(j, dval/(end-start+1));
1471 }
1472 // set marker color, line color, maker size, marker type
1473 fFourierAverage[i].dataFourierPwr->SetMarkerColor(fColorList[i]);
1474 fFourierAverage[i].dataFourierPwr->SetLineColor(fColorList[i]);
1475 fFourierAverage[i].dataFourierPwr->SetMarkerSize(0.8);
1476 fFourierAverage[i].dataFourierPwr->SetMarkerStyle(22); // closed up triangle
1477
1478 // phase average
1479 for (Int_t j=0; j<fFourierHistos[0].dataFourierPhase->GetNbinsX(); j++) {
1480 dval = 0.0;
1481 for (Int_t k=start; k<=end; k++) {
1482 if (j < fFourierHistos[k].dataFourierPhase->GetNbinsX())
1483 dval += GetInterpolatedValue(fFourierHistos[k].dataFourierPhase, fFourierHistos[0].dataFourierPhase->GetBinCenter(j));
1484 }
1485 fFourierAverage[i].dataFourierPhase->SetBinContent(j, dval/(end-start+1));
1486 }
1487 // set marker color, line color, maker size, marker type
1488 fFourierAverage[i].dataFourierPhase->SetMarkerColor(fColorList[i]);
1489 fFourierAverage[i].dataFourierPhase->SetLineColor(fColorList[i]);
1490 fFourierAverage[i].dataFourierPhase->SetMarkerSize(0.8);
1491 fFourierAverage[i].dataFourierPhase->SetMarkerStyle(22); // closed up triangle
1492
1493 if (phaseOptRealPresent) {
1494 // phase optimised real average
1495 for (Int_t j=0; j<fFourierHistos[0].dataFourierPhaseOptReal->GetNbinsX(); j++) {
1496 dval = 0.0;
1497 for (Int_t k=start; k<=end; k++) {
1498 if (j < fFourierHistos[k].dataFourierPhaseOptReal->GetNbinsX())
1499 dval += GetInterpolatedValue(fFourierHistos[k].dataFourierPhaseOptReal, fFourierHistos[0].dataFourierPhaseOptReal->GetBinCenter(j));
1500 }
1501 fFourierAverage[i].dataFourierPhaseOptReal->SetBinContent(j, dval/(end-start+1));
1502 }
1503 // set marker color, line color, maker size, marker type
1504 fFourierAverage[i].dataFourierPhaseOptReal->SetMarkerColor(fColorList[i]);
1505 fFourierAverage[i].dataFourierPhaseOptReal->SetLineColor(fColorList[i]);
1506 fFourierAverage[i].dataFourierPhaseOptReal->SetMarkerSize(0.8);
1507 fFourierAverage[i].dataFourierPhaseOptReal->SetMarkerStyle(22); // closed up triangle
1508 }
1509 }
1510 }
1511}
1512
1513//--------------------------------------------------------------------------
1514// CalcPhaseOptReal (private)
1515//--------------------------------------------------------------------------
1520{
1521 Int_t start = fFourierHistos[0].dataFourierRe->FindFixBin(fInitialXRange[0]);
1522 Int_t end = fFourierHistos[0].dataFourierRe->FindFixBin(fInitialXRange[1]);
1523
1524 Double_t dval=0.0, max=0.0;
1525 for (UInt_t i=0; i<fFourierHistos.size(); i++) {
1526 fFourierHistos[i].dataFourierPhaseOptReal = fFourier[i]->GetPhaseOptRealFourier(fFourierHistos[i].dataFourierRe,
1527 fFourierHistos[i].dataFourierIm, fFourierHistos[i].optPhase, 1.0, fInitialXRange[0], fInitialXRange[1]);
1528 // normalize it
1529 max = 0.0;
1530 for (Int_t j=start; j<=end; j++) {
1531 dval = fFourierHistos[i].dataFourierPhaseOptReal->GetBinContent(j);
1532 if (fabs(dval) > max)
1533 max = dval;
1534 }
1535 for (Int_t j=1; j<fFourierHistos[i].dataFourierPhaseOptReal->GetNbinsX(); j++) {
1536 fFourierHistos[i].dataFourierPhaseOptReal->SetBinContent(j, fFourierHistos[i].dataFourierPhaseOptReal->GetBinContent(j)/fabs(max));
1537 }
1538 // set the marker and line color
1539 fFourierHistos[i].dataFourierPhaseOptReal->SetMarkerColor(fColorList[i]);
1540 fFourierHistos[i].dataFourierPhaseOptReal->SetLineColor(fColorList[i]);
1541
1542 // set the marker symbol and size
1543 fFourierHistos[i].dataFourierPhaseOptReal->SetMarkerStyle(fMarkerList[i]);
1544 fFourierHistos[i].dataFourierPhaseOptReal->SetMarkerSize(0.7);
1545 }
1546}
1547
1548//--------------------------------------------------------------------------
1549// PlotFourier (private)
1550//--------------------------------------------------------------------------
1555{
1556 // check if phase opt real Fourier spectra already exists if requested,
1557 // and if not calculate them first
1559 if (fFourierHistos[0].dataFourierPhaseOptReal == nullptr) { // not yet calculated
1561 }
1562 }
1563
1564 fFourierPad->cd();
1565
1566 Double_t xmin=0, xmax=0;
1567 xmin = fInitialXRange[0];
1568 xmax = fInitialXRange[1];
1569
1570 Double_t ymin=0, ymax=0;
1571 switch (fCurrentPlotView) {
1572 case FOURIER_PLOT_REAL:
1573 fFourierHistos[0].dataFourierRe->GetXaxis()->SetRangeUser(xmin, xmax);
1574 ymin = GetMinimum(fFourierHistos[0].dataFourierRe, xmin, xmax);
1575 ymax = GetMaximum(fFourierHistos[0].dataFourierRe, xmin, xmax);
1576 for (UInt_t i=1; i<fFourierHistos.size(); i++) {
1577 if (GetMaximum(fFourierHistos[i].dataFourierRe, xmin, xmax) > ymax)
1578 ymax = GetMaximum(fFourierHistos[i].dataFourierRe, xmin, xmax);
1579 if (GetMinimum(fFourierHistos[i].dataFourierRe, xmin, xmax) < ymin)
1580 ymin = GetMinimum(fFourierHistos[i].dataFourierRe, xmin, xmax);
1581 }
1582 fFourierHistos[0].dataFourierRe->GetYaxis()->SetRangeUser(1.05*ymin, 1.05*ymax);
1583 fFourierHistos[0].dataFourierRe->GetYaxis()->SetTitle("Real");
1584 fFourierHistos[0].dataFourierRe->GetYaxis()->SetTitleOffset(1.3);
1585 fFourierHistos[0].dataFourierRe->GetYaxis()->SetDecimals(kTRUE);
1586 fFourierHistos[0].dataFourierRe->GetXaxis()->SetTitle(fXaxisTitle.Data());
1587 fFourierHistos[0].dataFourierRe->Draw("p");
1588 for (UInt_t i=1; i<fFourierHistos.size(); i++) {
1589 fFourierHistos[i].dataFourierRe->Draw("psame");
1590 }
1591 break;
1592 case FOURIER_PLOT_IMAG:
1593 fFourierHistos[0].dataFourierIm->GetXaxis()->SetRangeUser(xmin, xmax);
1594 ymin = GetMinimum(fFourierHistos[0].dataFourierIm, xmin, xmax);
1595 ymax = GetMaximum(fFourierHistos[0].dataFourierIm, xmin, xmax);
1596 for (UInt_t i=1; i<fFourierHistos.size(); i++) {
1597 if (GetMaximum(fFourierHistos[i].dataFourierIm, xmin, xmax) > ymax)
1598 ymax = GetMaximum(fFourierHistos[i].dataFourierIm, xmin, xmax);
1599 if (GetMinimum(fFourierHistos[i].dataFourierIm, xmin, xmax) < ymin)
1600 ymin = GetMinimum(fFourierHistos[i].dataFourierIm, xmin, xmax);
1601 }
1602 fFourierHistos[0].dataFourierIm->GetYaxis()->SetRangeUser(1.05*ymin, 1.05*ymax);
1603 fFourierHistos[0].dataFourierIm->GetYaxis()->SetTitleOffset(1.3);
1604 fFourierHistos[0].dataFourierIm->GetYaxis()->SetDecimals(kTRUE);
1605 fFourierHistos[0].dataFourierIm->GetYaxis()->SetTitle("Imag");
1606 fFourierHistos[0].dataFourierIm->GetXaxis()->SetTitle(fXaxisTitle.Data());
1607 fFourierHistos[0].dataFourierIm->Draw("p");
1608 for (UInt_t i=1; i<fFourierHistos.size(); i++) {
1609 fFourierHistos[i].dataFourierIm->Draw("psame");
1610 }
1611 break;
1613 fFourierHistos[0].dataFourierRe->GetXaxis()->SetRangeUser(xmin, xmax);
1614 ymin = GetMinimum(fFourierHistos[0].dataFourierRe, xmin, xmax);
1615 ymax = GetMaximum(fFourierHistos[0].dataFourierRe, xmin, xmax);
1616 for (UInt_t i=1; i<fFourierHistos.size(); i++) {
1617 if (GetMaximum(fFourierHistos[i].dataFourierRe, xmin, xmax) > ymax)
1618 ymax = GetMaximum(fFourierHistos[i].dataFourierRe, xmin, xmax);
1619 if (GetMaximum(fFourierHistos[i].dataFourierIm, xmin, xmax) > ymax)
1620 ymax = GetMaximum(fFourierHistos[i].dataFourierIm, xmin, xmax);
1621 if (GetMinimum(fFourierHistos[i].dataFourierRe, xmin, xmax) < ymin)
1622 ymin = GetMinimum(fFourierHistos[i].dataFourierRe, xmin, xmax);
1623 if (GetMinimum(fFourierHistos[i].dataFourierIm, xmin, xmax) < ymin)
1624 ymin = GetMinimum(fFourierHistos[i].dataFourierIm, xmin, xmax);
1625 }
1626 fFourierHistos[0].dataFourierRe->GetYaxis()->SetRangeUser(1.05*ymin, 1.05*ymax);
1627 fFourierHistos[0].dataFourierRe->GetYaxis()->SetTitleOffset(1.3);
1628 fFourierHistos[0].dataFourierRe->GetYaxis()->SetDecimals(kTRUE);
1629 fFourierHistos[0].dataFourierRe->GetYaxis()->SetTitle("Real");
1630 fFourierHistos[0].dataFourierRe->GetXaxis()->SetTitle(fXaxisTitle.Data());
1631 fFourierHistos[0].dataFourierRe->Draw("p");
1632 for (UInt_t i=1; i<fFourierHistos.size(); i++) {
1633 fFourierHistos[i].dataFourierRe->Draw("psame");
1634 }
1635 for (UInt_t i=0; i<fFourierHistos.size(); i++) {
1636 fFourierHistos[i].dataFourierIm->Draw("psame");
1637 }
1638 break;
1639 case FOURIER_PLOT_POWER:
1640 // get maximum of Fourier data in the range
1641 fFourierHistos[0].dataFourierPwr->GetXaxis()->SetRangeUser(xmin, xmax);
1642 ymin = 0.0;
1643 ymax = GetMaximum(fFourierHistos[0].dataFourierPwr, xmin, xmax);
1644 for (UInt_t i=1; i<fFourierHistos.size(); i++) {
1645 if (GetMaximum(fFourierHistos[i].dataFourierPwr, xmin, xmax) > ymax)
1646 ymax = GetMaximum(fFourierHistos[i].dataFourierPwr, xmin, xmax);
1647 }
1648 fFourierHistos[0].dataFourierPwr->GetYaxis()->SetRangeUser(ymin, 1.03*ymax);
1649 fFourierHistos[0].dataFourierPwr->GetYaxis()->SetTitle("Power");
1650 fFourierHistos[0].dataFourierPwr->GetYaxis()->SetTitleOffset(1.3);
1651 fFourierHistos[0].dataFourierPwr->GetYaxis()->SetDecimals(kTRUE);
1652 fFourierHistos[0].dataFourierPwr->GetXaxis()->SetTitle(fXaxisTitle.Data());
1653 fFourierHistos[0].dataFourierPwr->Draw("p");
1654 for (UInt_t i=1; i<fFourierHistos.size(); i++) {
1655 fFourierHistos[i].dataFourierPwr->Draw("psame");
1656 }
1657 break;
1658 case FOURIER_PLOT_PHASE:
1659 fFourierHistos[0].dataFourierPhase->GetXaxis()->SetRangeUser(xmin, xmax);
1660 ymin = GetMinimum(fFourierHistos[0].dataFourierPhase, xmin, xmax);
1661 ymax = GetMaximum(fFourierHistos[0].dataFourierPhase, xmin, xmax);
1662 for (UInt_t i=1; i<fFourierHistos.size(); i++) {
1663 if (GetMaximum(fFourierHistos[i].dataFourierPhase, xmin, xmax) > ymax)
1664 ymax = GetMaximum(fFourierHistos[i].dataFourierPhase, xmin, xmax);
1665 if (GetMinimum(fFourierHistos[i].dataFourierPhase, xmin, xmax) < ymin)
1666 ymin = GetMinimum(fFourierHistos[i].dataFourierPhase, xmin, xmax);
1667 }
1668 fFourierHistos[0].dataFourierPhase->GetYaxis()->SetRangeUser(1.05*ymin, 1.05*ymax);
1669 fFourierHistos[0].dataFourierPhase->GetYaxis()->SetTitleOffset(1.3);
1670 fFourierHistos[0].dataFourierPhase->GetYaxis()->SetDecimals(kTRUE);
1671 fFourierHistos[0].dataFourierPhase->GetYaxis()->SetTitle("Phase");
1672 fFourierHistos[0].dataFourierPhase->GetXaxis()->SetTitle(fXaxisTitle.Data());
1673 fFourierHistos[0].dataFourierPhase->Draw("p");
1674 for (UInt_t i=1; i<fFourierHistos.size(); i++) {
1675 fFourierHistos[i].dataFourierPhase->Draw("psame");
1676 }
1677 break;
1679 fFourierHistos[0].dataFourierPhaseOptReal->GetXaxis()->SetRangeUser(xmin, xmax);
1680 ymin = GetMinimum(fFourierHistos[0].dataFourierPhaseOptReal, xmin, xmax);
1681 ymax = GetMaximum(fFourierHistos[0].dataFourierPhaseOptReal, xmin, xmax);
1682 for (UInt_t i=1; i<fFourierHistos.size(); i++) {
1683 if (GetMaximum(fFourierHistos[i].dataFourierPhaseOptReal, xmin, xmax) > ymax)
1684 ymax = GetMaximum(fFourierHistos[i].dataFourierPhaseOptReal, xmin, xmax);
1685 if (GetMinimum(fFourierHistos[i].dataFourierPhaseOptReal, xmin, xmax) < ymin)
1686 ymin = GetMinimum(fFourierHistos[i].dataFourierPhaseOptReal, xmin, xmax);
1687 }
1688 fFourierHistos[0].dataFourierPhaseOptReal->GetYaxis()->SetRangeUser(ymin, 1.05*ymax);
1689 fFourierHistos[0].dataFourierPhaseOptReal->GetYaxis()->SetTitleOffset(1.3);
1690 fFourierHistos[0].dataFourierPhaseOptReal->GetYaxis()->SetDecimals(kTRUE);
1691 fFourierHistos[0].dataFourierPhaseOptReal->GetYaxis()->SetTitle("Phase Opt. Real");
1692 fFourierHistos[0].dataFourierPhaseOptReal->GetXaxis()->SetTitle(fXaxisTitle.Data());
1693 fFourierHistos[0].dataFourierPhaseOptReal->Draw("p");
1694 for (UInt_t i=1; i<fFourierHistos.size(); i++) {
1695 fFourierHistos[i].dataFourierPhaseOptReal->Draw("psame");
1696 }
1697 break;
1698 default:
1699 break;
1700 }
1701
1702 fFourierPad->Update();
1703
1704 fMainCanvas->cd();
1705 fMainCanvas->Update();
1706}
1707
1708//--------------------------------------------------------------------------
1709// PlotFourierPhaseValue (private)
1710//--------------------------------------------------------------------------
1715{
1716 Double_t x, y;
1717 TString str;
1718
1719 // plot Fourier phase
1720 str = TString("phase = ");
1721 str += fCurrentFourierPhase;
1722 x = 0.7;
1723 y = 0.85;
1724 fCurrentFourierPhaseText.reset(new TLatex());
1725 fCurrentFourierPhaseText->SetNDC(kTRUE);
1726 fCurrentFourierPhaseText->SetText(x, y, str.Data());
1727 fCurrentFourierPhaseText->SetTextFont(62);
1728 fCurrentFourierPhaseText->SetTextSize(0.03);
1729
1730 fFourierPad->cd();
1731
1733
1734 fFourierPad->Update();
1735}
1736
1737//--------------------------------------------------------------------------
1738// PlotAverage (private)
1739//--------------------------------------------------------------------------
1744{
1745 fFourierPad->cd();
1746
1747 if (fFourierAverage.size() == 0) { // ups, HandleAverage never called!
1748 HandleAverage();
1749 }
1750
1751 Double_t xmin=0.0, xmax=0.0;
1752 xmin = fInitialXRange[0];
1753 xmax = fInitialXRange[1];
1754 Double_t ymin=0.0, ymax=0.0;
1755
1756 if (fLegAvgPerDataSet.get()) {
1757 fLegAvgPerDataSet->Clear();
1758 }
1759
1760 switch (fCurrentPlotView) {
1761 case FOURIER_PLOT_REAL:
1762 fFourierAverage[0].dataFourierRe->GetXaxis()->SetRangeUser(xmin, xmax);
1763 ymin = GetMinimum(fFourierAverage[0].dataFourierRe, xmin, xmax);
1764 ymax = GetMaximum(fFourierAverage[0].dataFourierRe, xmin, xmax);
1765 for (UInt_t i=1; i<fFourierAverage.size(); i++) {
1766 if (GetMaximum(fFourierAverage[i].dataFourierRe, xmin, xmax) > ymax)
1767 ymax = GetMaximum(fFourierAverage[i].dataFourierRe, xmin, xmax);
1768 if (GetMinimum(fFourierAverage[i].dataFourierRe, xmin, xmax) < ymin)
1769 ymin = GetMinimum(fFourierAverage[i].dataFourierRe, xmin, xmax);
1770 }
1771 fFourierAverage[0].dataFourierRe->GetYaxis()->SetRangeUser(1.03*ymin, 1.03*ymax);
1772 fFourierAverage[0].dataFourierRe->GetYaxis()->SetTitleOffset(1.3);
1773 fFourierAverage[0].dataFourierRe->GetYaxis()->SetDecimals(kTRUE);
1774 fFourierAverage[0].dataFourierRe->GetYaxis()->SetTitle("<Real>");
1775 fFourierAverage[0].dataFourierRe->GetXaxis()->SetTitle(fXaxisTitle.Data());
1776 fFourierAverage[0].dataFourierRe->GetXaxis()->SetRangeUser(xmin, xmax);
1777 fFourierAverage[0].dataFourierRe->Draw("p");
1778 break;
1779 case FOURIER_PLOT_IMAG:
1780 fFourierAverage[0].dataFourierIm->GetXaxis()->SetRangeUser(xmin, xmax);
1781 ymin = GetMinimum(fFourierAverage[0].dataFourierIm, xmin, xmax);
1782 ymax = GetMaximum(fFourierAverage[0].dataFourierIm, xmin, xmax);
1783 for (UInt_t i=1; i<fFourierAverage.size(); i++) {
1784 if (GetMaximum(fFourierAverage[i].dataFourierIm, xmin, xmax) > ymax)
1785 ymax = GetMaximum(fFourierAverage[i].dataFourierIm, xmin, xmax);
1786 if (GetMinimum(fFourierAverage[i].dataFourierIm, xmin, xmax) < ymin)
1787 ymin = GetMinimum(fFourierAverage[i].dataFourierIm, xmin, xmax);
1788 }
1789 fFourierAverage[0].dataFourierIm->GetYaxis()->SetRangeUser(1.03*ymin, 1.03*ymax);
1790 fFourierAverage[0].dataFourierIm->GetYaxis()->SetTitleOffset(1.3);
1791 fFourierAverage[0].dataFourierIm->GetYaxis()->SetDecimals(kTRUE);
1792 fFourierAverage[0].dataFourierIm->GetYaxis()->SetTitle("<Imag>");
1793 fFourierAverage[0].dataFourierIm->GetXaxis()->SetTitle(fXaxisTitle.Data());
1794 fFourierAverage[0].dataFourierIm->GetXaxis()->SetRangeUser(xmin, xmax);
1795 fFourierAverage[0].dataFourierIm->Draw("p");
1796 break;
1798 fFourierAverage[0].dataFourierRe->GetXaxis()->SetRangeUser(xmin, xmax);
1799 ymin = GetMinimum(fFourierAverage[0].dataFourierRe, xmin, xmax);
1800 ymax = GetMaximum(fFourierAverage[0].dataFourierRe, xmin, xmax);
1801 for (UInt_t i=1; i<fFourierAverage.size(); i++) {
1802 if (GetMaximum(fFourierAverage[i].dataFourierRe, xmin, xmax) > ymax)
1803 ymax = GetMaximum(fFourierAverage[i].dataFourierRe, xmin, xmax);
1804 if (GetMinimum(fFourierAverage[i].dataFourierRe, xmin, xmax) < ymin)
1805 ymin = GetMinimum(fFourierAverage[i].dataFourierRe, xmin, xmax);
1806 }
1807 fFourierAverage[0].dataFourierRe->GetYaxis()->SetRangeUser(1.03*ymin, 1.03*ymax);
1808 fFourierAverage[0].dataFourierRe->GetYaxis()->SetTitleOffset(1.3);
1809 fFourierAverage[0].dataFourierRe->GetYaxis()->SetDecimals(kTRUE);
1810 fFourierAverage[0].dataFourierRe->GetYaxis()->SetTitle("<Real+Imag>");
1811 fFourierAverage[0].dataFourierRe->GetXaxis()->SetTitle(fXaxisTitle.Data());
1812 fFourierAverage[0].dataFourierRe->GetXaxis()->SetRangeUser(xmin, xmax);
1813 fFourierAverage[0].dataFourierRe->Draw("p");
1814 fFourierAverage[0].dataFourierIm->Draw("psame");
1815 break;
1816 case FOURIER_PLOT_POWER:
1817 // get maximum of Fourier data in the range
1818 fFourierAverage[0].dataFourierPwr->GetXaxis()->SetRangeUser(xmin, xmax);
1819 ymin = 0.0;
1820 ymax = GetMaximum(fFourierAverage[0].dataFourierPwr, xmin, xmax);
1821 for (UInt_t i=1; i<fFourierAverage.size(); i++) {
1822 if (GetMaximum(fFourierAverage[i].dataFourierPwr, xmin, xmax) > ymax)
1823 ymax = GetMaximum(fFourierAverage[i].dataFourierPwr, xmin, xmax);
1824 }
1825 fFourierAverage[0].dataFourierPwr->GetYaxis()->SetRangeUser(ymin, 1.03*ymax);
1826 fFourierAverage[0].dataFourierPwr->GetYaxis()->SetTitleOffset(1.3);
1827 fFourierAverage[0].dataFourierPwr->GetYaxis()->SetDecimals(kTRUE);
1828 fFourierAverage[0].dataFourierPwr->GetYaxis()->SetTitle("<Power>");
1829 fFourierAverage[0].dataFourierPwr->GetXaxis()->SetTitle(fXaxisTitle.Data());
1830 fFourierAverage[0].dataFourierPwr->Draw("p");
1831 break;
1832 case FOURIER_PLOT_PHASE:
1833 fFourierAverage[0].dataFourierPhase->GetXaxis()->SetRangeUser(xmin, xmax);
1834 ymin = GetMinimum(fFourierAverage[0].dataFourierPhase, xmin, xmax);
1835 ymax = GetMaximum(fFourierAverage[0].dataFourierPhase, xmin, xmax);
1836 for (UInt_t i=1; i<fFourierAverage.size(); i++) {
1837 if (GetMaximum(fFourierAverage[i].dataFourierPhase, xmin, xmax) > ymax)
1838 ymax = GetMaximum(fFourierAverage[i].dataFourierPhase, xmin, xmax);
1839 if (GetMinimum(fFourierAverage[i].dataFourierPhase, xmin, xmax) < ymin)
1840 ymin = GetMinimum(fFourierAverage[i].dataFourierPhase, xmin, xmax);
1841 }
1842 fFourierAverage[0].dataFourierPhase->GetYaxis()->SetRangeUser(1.03*ymin, 1.03*ymax);
1843 fFourierAverage[0].dataFourierPhase->GetYaxis()->SetTitleOffset(1.3);
1844 fFourierAverage[0].dataFourierPhase->GetYaxis()->SetDecimals(kTRUE);
1845 fFourierAverage[0].dataFourierPhase->GetYaxis()->SetTitle("<Phase>");
1846 fFourierAverage[0].dataFourierPhase->GetXaxis()->SetTitle(fXaxisTitle.Data());
1847 fFourierAverage[0].dataFourierPhase->GetXaxis()->SetRangeUser(xmin, xmax);
1848 fFourierAverage[0].dataFourierPhase->Draw("p");
1849 break;
1851 if (fFourierHistos[0].dataFourierPhaseOptReal == nullptr) {
1852 std::cout << "debug> need to calculate phase opt. average first ..." << std::endl;
1854 HandleAverage();
1855 }
1856 fFourierAverage[0].dataFourierPhaseOptReal->GetXaxis()->SetRangeUser(xmin, xmax);
1857 ymin = GetMinimum(fFourierAverage[0].dataFourierPhaseOptReal, xmin, xmax);
1858 ymax = GetMaximum(fFourierAverage[0].dataFourierPhaseOptReal, xmin, xmax);
1859 for (UInt_t i=1; i<fFourierAverage.size(); i++) {
1860 if (GetMaximum(fFourierAverage[i].dataFourierPhaseOptReal, xmin, xmax) > ymax)
1861 ymax = GetMaximum(fFourierAverage[i].dataFourierPhaseOptReal, xmin, xmax);
1862 if (GetMinimum(fFourierAverage[i].dataFourierPhaseOptReal, xmin, xmax) < ymin)
1863 ymin = GetMinimum(fFourierAverage[i].dataFourierPhaseOptReal, xmin, xmax);
1864 }
1865 fFourierAverage[0].dataFourierPhaseOptReal->GetYaxis()->SetRangeUser(ymin, 1.03*ymax);
1866 fFourierAverage[0].dataFourierPhaseOptReal->GetYaxis()->SetTitleOffset(1.3);
1867 fFourierAverage[0].dataFourierPhaseOptReal->GetYaxis()->SetDecimals(kTRUE);
1868 fFourierAverage[0].dataFourierPhaseOptReal->GetYaxis()->SetTitle("<Phase Opt. Real>");
1869 fFourierAverage[0].dataFourierPhaseOptReal->GetXaxis()->SetTitle(fXaxisTitle.Data());
1870 fFourierAverage[0].dataFourierPhaseOptReal->GetXaxis()->SetRangeUser(xmin, xmax);
1871 fFourierAverage[0].dataFourierPhaseOptReal->Draw("p");
1872 break;
1873 default:
1874 break;
1875 }
1876
1877 if (fAveragedViewPerDataSet) { // plot all the rest
1878 fLegAvgPerDataSet = std::make_unique<TLegend>(0.55, 0.4, 0.85, 0.6);
1879 TString str = GetDataSetName(fFourierAverage[0].dataFourierPwr->GetTitle());
1880 TString label = TString::Format("<%s>", str.Data());
1881 fLegAvgPerDataSet->AddEntry(fFourierAverage[0].dataFourierPwr, label.Data());
1882 for (UInt_t i=1; i<fFourierAverage.size(); i++) {
1883 switch (fCurrentPlotView) {
1884 case FOURIER_PLOT_REAL:
1885 fFourierAverage[i].dataFourierRe->Draw("psame");
1886 break;
1887 case FOURIER_PLOT_IMAG:
1888 fFourierAverage[i].dataFourierIm->Draw("psame");
1889 break;
1891 fFourierAverage[i].dataFourierRe->Draw("psame");
1892 fFourierAverage[i].dataFourierIm->Draw("psame");
1893 break;
1894 case FOURIER_PLOT_POWER:
1895 fFourierAverage[i].dataFourierPwr->Draw("psame");
1896 break;
1897 case FOURIER_PLOT_PHASE:
1898 fFourierAverage[i].dataFourierPhase->Draw("psame");
1899 break;
1901 fFourierAverage[i].dataFourierPhaseOptReal->Draw("psame");
1902 break;
1903 default:
1904 break;
1905 }
1906 // add legend ?!?!
1907 str = GetDataSetName(fFourierAverage[i].dataFourierPwr->GetTitle());
1908 label = TString::Format("<%s>", str.Data());
1909 fLegAvgPerDataSet->AddEntry(fFourierAverage[i].dataFourierPwr, label.Data());
1910 }
1911 fLegAvgPerDataSet->Draw();
1912 }
1913
1914 fFourierPad->Update();
1915
1916 fMainCanvas->cd();
1917 fMainCanvas->Update();
1918}
1919
1920//--------------------------------------------------------------------------
1921// IncrementFourierPhase (private)
1922//--------------------------------------------------------------------------
1927{
1929 return;
1930
1931 Double_t re, im;
1932 Double_t inc = 1.0;
1933 const Double_t cp = TMath::Cos(inc/180.0*TMath::Pi());
1934 const Double_t sp = TMath::Sin(inc/180.0*TMath::Pi());
1935
1936 fCurrentFourierPhase += inc;
1938
1939 for (UInt_t i=0; i<fFourierHistos.size(); i++) { // loop over all data sets
1940 if ((fFourierHistos[i].dataFourierRe != nullptr) && (fFourierHistos[i].dataFourierIm != nullptr)) {
1941 for (Int_t j=0; j<fFourierHistos[i].dataFourierRe->GetNbinsX(); j++) { // loop over a fourier data set
1942 // calculate new fourier data set value
1943 re = fFourierHistos[i].dataFourierRe->GetBinContent(j) * cp + fFourierHistos[i].dataFourierIm->GetBinContent(j) * sp;
1944 im = fFourierHistos[i].dataFourierIm->GetBinContent(j) * cp - fFourierHistos[i].dataFourierRe->GetBinContent(j) * sp;
1945 // overwrite fourier data set value
1946 fFourierHistos[i].dataFourierRe->SetBinContent(j, re);
1947 fFourierHistos[i].dataFourierIm->SetBinContent(j, im);
1948 }
1949 }
1950 }
1951}
1952
1953//--------------------------------------------------------------------------
1954// DecrementFourierPhase (private)
1955//--------------------------------------------------------------------------
1960{
1962 return;
1963
1964 Double_t re, im;
1965 Double_t inc = 1.0;
1966 const Double_t cp = TMath::Cos(inc/180.0*TMath::Pi());
1967 const Double_t sp = TMath::Sin(inc/180.0*TMath::Pi());
1968
1969 fCurrentFourierPhase -= inc;
1971
1972 for (UInt_t i=0; i<fFourierHistos.size(); i++) { // loop over all data sets
1973 if ((fFourierHistos[i].dataFourierRe != nullptr) && (fFourierHistos[i].dataFourierIm != nullptr)) {
1974 for (Int_t j=0; j<fFourierHistos[i].dataFourierRe->GetNbinsX(); j++) { // loop over a fourier data set
1975 // calculate new fourier data set value
1976 re = fFourierHistos[i].dataFourierRe->GetBinContent(j) * cp - fFourierHistos[i].dataFourierIm->GetBinContent(j) * sp;
1977 im = fFourierHistos[i].dataFourierIm->GetBinContent(j) * cp + fFourierHistos[i].dataFourierRe->GetBinContent(j) * sp;
1978 // overwrite fourier data set value
1979 fFourierHistos[i].dataFourierRe->SetBinContent(j, re);
1980 fFourierHistos[i].dataFourierIm->SetBinContent(j, im);
1981 }
1982 }
1983 }
1984}
1985
1986//--------------------------------------------------------------------------
1987// GetMaximum (private)
1988//--------------------------------------------------------------------------
2000Double_t PFourierCanvas::GetMaximum(TH1F* histo, Double_t xmin, Double_t xmax)
2001{
2002 if (histo == nullptr)
2003 return 0.0;
2004
2005 Int_t start=0, end=0;
2006 if (xmin == xmax) {
2007 start = 1;
2008 end = histo->GetNbinsX();
2009 } else {
2010 start = histo->FindBin(xmin);
2011 if ((start==0) || (start==histo->GetNbinsX()+1)) // underflow/overflow
2012 start = 1;
2013 end = histo->FindBin(xmax);
2014 if ((end==0) || (end==histo->GetNbinsX()+1)) // underflow/overflow
2015 end = histo->GetNbinsX();
2016 }
2017
2018 Double_t max = histo->GetBinContent(start);
2019 Double_t binContent;
2020 for (Int_t i=start; i<end; i++) {
2021 binContent = histo->GetBinContent(i);
2022 if (max < binContent)
2023 max = binContent;
2024 }
2025
2026 return max;
2027}
2028
2029//--------------------------------------------------------------------------
2030// GetMinimum (private)
2031//--------------------------------------------------------------------------
2043Double_t PFourierCanvas::GetMinimum(TH1F* histo, Double_t xmin, Double_t xmax)
2044{
2045 if (histo == nullptr)
2046 return 0.0;
2047
2048 Int_t start=0, end=0;
2049 if (xmin == xmax) {
2050 start = 1;
2051 end = histo->GetNbinsX();
2052 } else {
2053 start = histo->FindBin(xmin);
2054 if ((start==0) || (start==histo->GetNbinsX()+1)) // underflow/overflow
2055 start = 1;
2056 end = histo->FindBin(xmax);
2057 if ((end==0) || (end==histo->GetNbinsX()+1)) // underflow/overflow
2058 end = histo->GetNbinsX();
2059 }
2060
2061 Double_t min = histo->GetBinContent(start);
2062 Double_t binContent;
2063 for (Int_t i=start; i<end; i++) {
2064 binContent = histo->GetBinContent(i);
2065 if (min > binContent)
2066 min = binContent;
2067 }
2068
2069 return min;
2070}
2071
2072//--------------------------------------------------------------------------
2073// GetInterpolatedValue (private)
2074//--------------------------------------------------------------------------
2085Double_t PFourierCanvas::GetInterpolatedValue(TH1F* histo, Double_t xVal)
2086{
2087 if (histo == nullptr)
2088 return 0.0;
2089
2090 Int_t idx = histo->FindBin(xVal);
2091
2092 // make sure idx is within range
2093 if ((idx < 1) || (idx > histo->GetNbinsX()))
2094 return 0.0;
2095
2096 // make sure the lower bound idx is found. This is needed since
2097 // FindBin rounds towards the closer idx.
2098 if (histo->GetBinCenter(idx) > xVal)
2099 --idx;
2100
2101 Double_t x0, x1, y0, y1;
2102 x0 = histo->GetBinCenter(idx);
2103 x1 = histo->GetBinCenter(idx+1);
2104 y0 = histo->GetBinContent(idx);
2105 y1 = histo->GetBinContent(idx+1);
2106
2107 return (y1-y0)*(xVal-x0)/(x1-x0)+y0;
2108}
2109
2110//--------------------------------------------------------------------------
2111// GetDataSetName (private)
2112//--------------------------------------------------------------------------
2122{
2123 TString str(title);
2124
2125 Ssiz_t idx = str.First(':');
2126 str.Remove(0, idx+1);
2127 idx = str.First(',');
2128 str.Remove(idx);
2129
2130 return str;
2131}
static const Char_t * gFiletypes[]
ClassImpQ(PFourierCanvas) PFourierCanvas
#define P_MENU_ID_AVERAGE_PER_DATA_SET
#define P_MENU_ID_FOURIER_PHASE_PLUS
#define P_MENU_ID_FOURIER
#define P_MENU_ID_FOURIER_IMAG
#define P_MENU_ID_AVERAGE
#define P_MENU_ID_EXPORT_DATA
#define P_MENU_ID_FOURIER_REAL
#define P_MENU_ID_FOURIER_PHASE_MINUS
#define P_MENU_ID_FOURIER_REAL_AND_IMAG
#define P_MENU_ID_FOURIER_PWR
#define P_MENU_ID_FOURIER_PHASE
#define P_MENU_ID_FOURIER_PHASE_OPT_REAL
#define YINFO
Y-position of info/legend pad.
Definition PMusrCanvas.h:56
#define YTITLE
Y-position of title pad.
Definition PMusrCanvas.h:57
#define FOURIER_UNIT_FREQ
Frequency in MHz.
Definition PMusr.h:276
#define FOURIER_PLOT_REAL_AND_IMAG
Plot both real and imaginary components (default)
Definition PMusr.h:314
#define FOURIER_UNIT_GAUSS
Magnetic field in Gauss (G)
Definition PMusr.h:272
#define FOURIER_PLOT_NOT_GIVEN
Plot type not specified.
Definition PMusr.h:308
#define FOURIER_PLOT_POWER
Plot power spectrum |F(ω)|²
Definition PMusr.h:316
#define FOURIER_PLOT_REAL
Plot real component only.
Definition PMusr.h:310
#define FOURIER_PLOT_PHASE_OPT_REAL
Plot phase-optimized real component.
Definition PMusr.h:320
#define FOURIER_UNIT_CYCLES
Angular frequency in Mc/s (Mega-cycles per second)
Definition PMusr.h:278
std::vector< Int_t > PIntVector
Definition PMusr.h:367
#define FOURIER_PLOT_IMAG
Plot imaginary component only.
Definition PMusr.h:312
#define FOURIER_PLOT_PHASE
Plot phase spectrum arg(F(ω))
Definition PMusr.h:318
#define FOURIER_UNIT_TESLA
Magnetic field in Tesla (T)
Definition PMusr.h:274
return status
virtual void CalcPhaseOptReal()
Calculates phase-optimized real Fourier for all datasets.
Bool_t fValid
if true, everything looks OK
Double_t fInitialXRange[2]
keeps the initial x-range
virtual void LastCanvasClosed()
virtual void HandleMenuPopup(Int_t id)
TGMenuBar * fBar
menu bar
virtual void HandleAverage()
Computes averaged Fourier spectra across runs or per dataset.
std::unique_ptr< TStyle > fStyle
A collection of all graphics attributes.
virtual void Done(Int_t status=0)
virtual void SetTimeout(Int_t ival)
Int_t fCurrentPlotView
tag showing what the current plot view is: real, imag, power, phase, ...
virtual void DecrementFourierPhase()
Decreases phase by 5° and redraws Re/Im spectra.
virtual void PlotFourier()
Draws individual Fourier spectra (non-averaged view)
PIntVector fMarkerList
list of markers
std::unique_ptr< TPaveText > fTitlePad
title pad used to display a title
Bool_t fBatchMode
musrview in ROOT batch mode
virtual void PlotAverage()
Draws averaged Fourier spectra (averaged view modes)
std::unique_ptr< TLatex > fCurrentFourierPhaseText
used in Re/Im Fourier to show the current phase in the pad
PFourierCanvasDataList fFourierAverage
keeps the average of the Fourier histos
Double_t fCurrentFourierPhase
keeps the current Fourier phase (real/imag)
std::vector< PFourier * > fFourier
keeps all the Fourier data, ownership is with the caller
Int_t fTimeout
timeout after which the Done signal should be emited. If timeout <= 0, no timeout is taking place
virtual void PlotFourierPhaseValue()
Displays current phase value as text overlay on canvas.
virtual void SaveGraphicsAndQuit(const Char_t *fileName)
virtual void HandleCmdKey(Int_t event, Int_t x, Int_t y, TObject *selected)
PFourierCanvasDataList fFourierHistos
keeps all the Fourier histos
virtual Double_t GetInterpolatedValue(TH1F *histo, Double_t xVal)
std::unique_ptr< TLegend > fLegAvgPerDataSet
legend used for averaged per data set view
TGPopupMenu * fPopupMain
popup menu MusrFT in the main menu bar
PIntVector fDataSetTag
vector holding the data set tags
std::unique_ptr< TCanvas > fMainCanvas
main canvas
std::unique_ptr< TLegend > fInfoPad
info pad used to display a legend of the data plotted
PIntVector fColorList
list of colors
virtual Double_t GetMaximum(TH1F *histo, Double_t xmin=-1.0, Double_t xmax=-1.0)
virtual void UpdateInfoPad()
virtual void UpdateFourierPad()
virtual void CreateStyle()
Initializes ROOT plotting style (colors, fonts, margins, etc.)
virtual Double_t GetMinimum(TH1F *histo, Double_t xmin=-1.0, Double_t xmax=-1.0)
virtual void InitFourierCanvas(const Char_t *title, Int_t wtopx, Int_t wtopy, Int_t ww, Int_t wh)
std::unique_ptr< TGPopupMenu > fPopupFourier
popup menu of the MusrFT/Fourier sub menu
Bool_t fAveragedView
tag showing that the averaged view for ALL data or normal view should be presented.
virtual void CreateXaxisTitle()
Creates X-axis label based on unit type (Gauss/Tesla/MHz/Mc/s)
virtual void IncrementFourierPhase()
Increases phase by 5° and redraws Re/Im spectra.
virtual void InitFourierDataSets()
Generates all Fourier histograms (Re/Im/Pwr/Phase) from PFourier objects.
virtual void CleanupAverage()
Deletes averaged histogram data to free memory.
std::unique_ptr< TPad > fFourierPad
fourier pad used to display the fourier
TRootCanvas * fImp
ROOT native GUI version of main window with menubar and drawing area.
virtual void ExportData(const Char_t *pathFileName)
virtual TString GetDataSetName(TString title)
std::unique_ptr< TTimer > fTimeoutTimer
timeout timer in order to terminate if no action is taking place for too long
Bool_t fAveragedViewPerDataSet
tag showing that the averaged view for individual data sets or normal view should be presented.
static int timeout
Definition musrfit.cpp:71