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 // the rgb values need to be drawn into separate variables first: the evaluation order of
150 // function arguments is unspecified in C++, hence calling rand.Integer() three times within
151 // the argument list would yield compiler dependent (r,g,b) permutations.
152 Int_t r = static_cast<Int_t>(rand.Integer(255));
153 Int_t g = static_cast<Int_t>(rand.Integer(255));
154 Int_t b = static_cast<Int_t>(rand.Integer(255));
155 color = TColor::GetColor(r, g, b);
156 fColorList.push_back(color);
157 }
158
159 CreateXaxisTitle();
160 CreateStyle();
161 InitFourierDataSets();
162 InitFourierCanvas(fTitle, wtopx, wtopy, ww, wh);
163
164 gStyle->SetHistMinimumZero(kTRUE); // needed to enforce proper bar option handling
165}
166
167//---------------------------------------------------------------------------
209PFourierCanvas::PFourierCanvas(std::vector<PFourier*> &fourier, PIntVector dataSetTag, const Char_t* title,
210 const Bool_t showAverage, const Bool_t showAveragePerDataSet,
211 const Int_t fourierPlotOpt, Double_t fourierXrange[], Double_t phase,
212 Int_t wtopx, Int_t wtopy, Int_t ww, Int_t wh,
213 const PIntVector markerList, const PIntVector colorList, const Bool_t batch) :
214 fBatchMode(batch), fAveragedView(showAverage), fAveragedViewPerDataSet(showAveragePerDataSet),
215 fDataSetTag(dataSetTag), fCurrentPlotView(fourierPlotOpt), fTitle(title), fFourier(fourier),
216 fCurrentFourierPhase(phase), fMarkerList(markerList), fColorList(colorList)
217{
218 fInitialXRange[0] = fourierXrange[0];
219 fInitialXRange[1] = fourierXrange[1];
220
221 fTimeout = 0;
222
223 fValid = false;
224
225 // generate fMarkerList and fColorList, since they are not provided
226 TRandom rand;
227 Int_t style, color;
228 for (UInt_t i=static_cast<UInt_t>(fMarkerList.size()); i<fourier.size(); i++) {
229 rand.SetSeed(i);
230 style = 20+static_cast<Int_t>(rand.Integer(10));
231 fMarkerList.push_back(style);
232 }
233 for (UInt_t i=static_cast<UInt_t>(fColorList.size()); i<fourier.size(); i++) {
234 rand.SetSeed(i);
235 // the rgb values need to be drawn into separate variables first: the evaluation order of
236 // function arguments is unspecified in C++, hence calling rand.Integer() three times within
237 // the argument list would yield compiler dependent (r,g,b) permutations.
238 Int_t r = static_cast<Int_t>(rand.Integer(255));
239 Int_t g = static_cast<Int_t>(rand.Integer(255));
240 Int_t b = static_cast<Int_t>(rand.Integer(255));
241 color = TColor::GetColor(r, g, b);
242 fColorList.push_back(color);
243 }
244
245 CreateXaxisTitle();
246 CreateStyle();
247 InitFourierDataSets();
248 InitFourierCanvas(fTitle, wtopx, wtopy, ww, wh);
249
250 gStyle->SetHistMinimumZero(kTRUE); // needed to enforce proper bar option handling
251}
252
253//--------------------------------------------------------------------------
254// Done (SIGNAL)
255//--------------------------------------------------------------------------
278{
279 Emit("Done(Int_t)", status);
280}
281
282//--------------------------------------------------------------------------
283// HandleCmdKey (SLOT)
284//--------------------------------------------------------------------------
318void PFourierCanvas::HandleCmdKey(Int_t event, Int_t x, Int_t y, TObject *selected)
319{
320 if (event != kKeyPress)
321 return;
322
323 if (fBatchMode)
324 return;
325
326 if (x == 'q') { // quit
327 Done(0);
328 } else if (x == 'u') { // unzoom
330 PlotAverage();
331 else
332 PlotFourier();
333 } else if (x == 'a') { // toggle between average view and single histo view
334 // toggle average view flag
336 // unset average per data set view flag
338 // update menu
339 if (fAveragedView) {
340 fPopupMain->CheckEntry(P_MENU_ID_AVERAGE);
343 PlotAverage();
344 } else {
345 fPopupMain->UnCheckEntry(P_MENU_ID_AVERAGE);
348 PlotFourier();
349 }
350 } else if (x == 'd') { // toggle between average view per data set and single histo view
351 // toggle average per data set view flag
353 // unset average view flag
354 fAveragedView = false;
355 // update menu
358 fPopupMain->UnCheckEntry(P_MENU_ID_AVERAGE);
360 PlotAverage();
361 } else {
363 fPopupMain->UnCheckEntry(P_MENU_ID_AVERAGE);
365 PlotFourier();
366 }
367 } else if (x == 'c') {
368 Int_t state = fFourierPad->GetCrosshair();
369 if (state == 0) {
370 fMainCanvas->ToggleEventStatus();
371 fFourierPad->SetCrosshair(2);
372 } else {
373 fMainCanvas->ToggleEventStatus();
374 fFourierPad->SetCrosshair(0);
375 }
376 fMainCanvas->Update();
377 } else if (x == '+') { // increment phase (Fourier real/imag)
379 } else if (x == '-') { // decrement phase (Fourier real/imag)
381 }
382}
383
384//--------------------------------------------------------------------------
385// HandleMenuPopup (SLOT)
386//--------------------------------------------------------------------------
417{
418 if (fBatchMode)
419 return;
420
422 // uncheck fourier popup items
423 fPopupFourier->UnCheckEntries();
426 if (!fAveragedView) {
427 PlotFourier();
428 } else {
430 PlotAverage();
431 }
432 } else if (id == P_MENU_ID_FOURIER+P_MENU_ID_FOURIER_IMAG) {
433 fPopupFourier->UnCheckEntries();
436 if (!fAveragedView) {
437 PlotFourier();
438 } else {
440 PlotAverage();
441 }
443 fPopupFourier->UnCheckEntries();
446 if (!fAveragedView) {
447 PlotFourier();
448 } else {
450 PlotAverage();
451 }
452 } else if (id == P_MENU_ID_FOURIER+P_MENU_ID_FOURIER_PWR) {
453 fPopupFourier->UnCheckEntries();
456 if (!fAveragedView) {
457 PlotFourier();
458 } else {
460 PlotAverage();
461 }
463 fPopupFourier->UnCheckEntries();
466 if (!fAveragedView) {
467 PlotFourier();
468 } else {
470 PlotAverage();
471 }
473 fPopupFourier->UnCheckEntries();
476 if (!fAveragedView) {
477 PlotFourier();
478 } else {
480 PlotAverage();
481 }
486 } else if (id == P_MENU_ID_AVERAGE) {
487 // toggle average view flag
489 // unset average per data set view flag
491 // update menu
492 if (fAveragedView) {
493 fPopupMain->CheckEntry(P_MENU_ID_AVERAGE);
496 PlotAverage();
497 } else {
498 fPopupMain->UnCheckEntry(P_MENU_ID_AVERAGE);
501 PlotFourier();
502 }
503 } else if (id == P_MENU_ID_AVERAGE_PER_DATA_SET) {
504 // toggle average per data set view flag
506 // unset average view flag
507 fAveragedView = false;
508 // update menu
511 fPopupMain->UnCheckEntry(P_MENU_ID_AVERAGE);
513 PlotAverage();
514 } else {
516 fPopupMain->UnCheckEntry(P_MENU_ID_AVERAGE);
518 PlotFourier();
519 }
520 } else if (id == P_MENU_ID_EXPORT_DATA) {
521 static TString dir(".");
522 TGFileInfo fi;
523 fi.fFileTypes = gFiletypes;
524 fi.fIniDir = StrDup(dir);
525 fi.fOverwrite = true;
526 new TGFileDialog(nullptr, fImp, kFDSave, &fi);
527 if (fi.fFilename && strlen(fi.fFilename)) {
528 ExportData(fi.fFilename);
529 }
530 }
531}
532
533//--------------------------------------------------------------------------
534// LastCanvasClosed (SLOT)
535//--------------------------------------------------------------------------
541{
542 if (gROOT->GetListOfCanvases()->IsEmpty()) {
543 Done(0);
544 }
545}
546
547//--------------------------------------------------------------------------
548// UpdateFourierPad (public)
549//--------------------------------------------------------------------------
554{
555 if (!fValid)
556 return;
557
559 PlotAverage();
560 else
561 PlotFourier();
562
563 fFourierPad->Draw();
564 fMainCanvas->cd();
565 fMainCanvas->Update();
566}
567
568//--------------------------------------------------------------------------
569// UpdateInfoPad (public)
570//--------------------------------------------------------------------------
575{
576 if (!fValid)
577 return;
578
579 // write header line
580 TDatime dt;
581 Char_t dtStr[128];
582 strncpy(dtStr, dt.AsSQLString(), sizeof(dtStr));
583 TString str("musrFT: ");
584 str += dtStr;
585 fInfoPad->SetHeader(str);
586
587 Char_t title[1024];
588 for (UInt_t i=0; i<fFourier.size(); i++) {
589 strncpy(title, fFourier[i]->GetDataTitle(), sizeof(title));
590 // add entry
591 fInfoPad->AddEntry(fFourierHistos[i].dataFourierRe, title, "p");
592 }
593
594 fInfoPad->Draw();
595 fMainCanvas->cd();
596 fMainCanvas->Update();
597}
598
599//--------------------------------------------------------------------------
600// SetTimeout (public)
601//--------------------------------------------------------------------------
625{
627
628 if (fTimeout <= 0)
629 return;
630
631 fTimeoutTimer.reset(new TTimer());
632
633 fTimeoutTimer->Connect("Timeout()", "PFourierCanvas", this, "Done()");
634
635 fTimeoutTimer->Start(1000*fTimeout, kTRUE);
636}
637
638//--------------------------------------------------------------------------
639// SaveGraphicsAndQuit
640//--------------------------------------------------------------------------
669void PFourierCanvas::SaveGraphicsAndQuit(const Char_t *fileName)
670{
671 std::cout << std::endl << ">> SaveGraphicsAndQuit: will dump the canvas into a graphics output file: " << fileName << " ..." << std::endl;
672
673 fMainCanvas->SaveAs(fileName);
674
675 Done(0);
676}
677
678//--------------------------------------------------------------------------
679// ExportData
680//--------------------------------------------------------------------------
721void PFourierCanvas::ExportData(const Char_t *pathFileName)
722{
723 TString pfn("");
724
725 if (pathFileName) { // path file name provided
726 pfn = TString(pathFileName);
727 } else { // path file name NOT provided, generate a default path file name
728 std::cerr << std::endl << ">> PFourierCanvas::ExportData **ERROR** NO path file name provided. Will do nothing." << std::endl;
729 return;
730 }
731
732 TString xAxis(""), yAxis("");
733 Int_t xMinBin, xMaxBin;
734 if (fAveragedView) {
735 switch (fCurrentPlotView) {
737 xAxis = fFourierHistos[0].dataFourierRe->GetXaxis()->GetTitle();
738 yAxis = TString("<Real>");
739 xMinBin = fFourierHistos[0].dataFourierRe->GetXaxis()->GetFirst();
740 xMaxBin = fFourierHistos[0].dataFourierRe->GetXaxis()->GetLast();
741 break;
743 xAxis = fFourierHistos[0].dataFourierIm->GetXaxis()->GetTitle();
744 yAxis = TString("<Imag>");
745 xMinBin = fFourierHistos[0].dataFourierIm->GetXaxis()->GetFirst();
746 xMaxBin = fFourierHistos[0].dataFourierIm->GetXaxis()->GetLast();
747 break;
749 xAxis = fFourierHistos[0].dataFourierPwr->GetXaxis()->GetTitle();
750 yAxis = TString("<Power>");
751 xMinBin = fFourierHistos[0].dataFourierPwr->GetXaxis()->GetFirst();
752 xMaxBin = fFourierHistos[0].dataFourierPwr->GetXaxis()->GetLast();
753 break;
755 xAxis = fFourierHistos[0].dataFourierPhase->GetXaxis()->GetTitle();
756 yAxis = TString("<Phase>");
757 xMinBin = fFourierHistos[0].dataFourierPhase->GetXaxis()->GetFirst();
758 xMaxBin = fFourierHistos[0].dataFourierPhase->GetXaxis()->GetLast();
759 break;
761 xAxis = fFourierHistos[0].dataFourierPhaseOptReal->GetXaxis()->GetTitle();
762 yAxis = TString("<Phase>");
763 xMinBin = fFourierHistos[0].dataFourierPhaseOptReal->GetXaxis()->GetFirst();
764 xMaxBin = fFourierHistos[0].dataFourierPhaseOptReal->GetXaxis()->GetLast();
765 break;
766 default:
767 xAxis = TString("??");
768 yAxis = TString("??");
769 xMinBin = 0;
770 xMaxBin = 0;
771 break;
772 }
773 } else {
774 switch (fCurrentPlotView) {
776 xAxis = fFourierHistos[0].dataFourierRe->GetXaxis()->GetTitle();
777 yAxis = TString("Real");
778 xMinBin = fFourierHistos[0].dataFourierRe->GetXaxis()->GetFirst();
779 xMaxBin = fFourierHistos[0].dataFourierRe->GetXaxis()->GetLast();
780 break;
782 xAxis = fFourierHistos[0].dataFourierIm->GetXaxis()->GetTitle();
783 yAxis = TString("Imag");
784 xMinBin = fFourierHistos[0].dataFourierIm->GetXaxis()->GetFirst();
785 xMaxBin = fFourierHistos[0].dataFourierIm->GetXaxis()->GetLast();
786 break;
788 xAxis = fFourierHistos[0].dataFourierRe->GetXaxis()->GetTitle();
789 yAxis = TString("Real+Imag");
790 xMinBin = fFourierHistos[0].dataFourierRe->GetXaxis()->GetFirst();
791 xMaxBin = fFourierHistos[0].dataFourierRe->GetXaxis()->GetLast();
792 break;
794 xAxis = fFourierHistos[0].dataFourierPwr->GetXaxis()->GetTitle();
795 yAxis = TString("Power");
796 xMinBin = fFourierHistos[0].dataFourierPwr->GetXaxis()->GetFirst();
797 xMaxBin = fFourierHistos[0].dataFourierPwr->GetXaxis()->GetLast();
798 break;
800 xAxis = fFourierHistos[0].dataFourierPhase->GetXaxis()->GetTitle();
801 yAxis = TString("Phase");
802 xMinBin = fFourierHistos[0].dataFourierPhase->GetXaxis()->GetFirst();
803 xMaxBin = fFourierHistos[0].dataFourierPhase->GetXaxis()->GetLast();
804 break;
806 xAxis = fFourierHistos[0].dataFourierPhaseOptReal->GetXaxis()->GetTitle();
807 yAxis = TString("Phase");
808 xMinBin = fFourierHistos[0].dataFourierPhaseOptReal->GetXaxis()->GetFirst();
809 xMaxBin = fFourierHistos[0].dataFourierPhaseOptReal->GetXaxis()->GetLast();
810 break;
811 default:
812 xAxis = TString("??");
813 yAxis = TString("??");
814 xMinBin = 0;
815 xMaxBin = 0;
816 break;
817 }
818 }
819
820 // write data to file
821 std::ofstream fout(pfn.Data(), std::ofstream::out);
822
823 if (fAveragedView) {
824 // write header
825 fout << "% " << pfn << std::endl;
826 fout << "% averaged data of:" << std::endl;
827 for (UInt_t i=0; i<fFourierHistos.size(); i++) {
828 fout << "% " << fFourierHistos[i].dataFourierRe->GetTitle() << std::endl;
829 }
830 fout << "%------------" << std::endl;
831 fout << "% " << xAxis << ", " << yAxis << std::endl;
832 for (Int_t i=xMinBin; i<xMaxBin; i++) {
833 switch (fCurrentPlotView) {
835 fout << fFourierAverage[0].dataFourierRe->GetBinCenter(i) << ", " << fFourierAverage[0].dataFourierRe->GetBinContent(i) << std::endl;
836 break;
838 fout << fFourierAverage[0].dataFourierIm->GetBinCenter(i) << ", " << fFourierAverage[0].dataFourierIm->GetBinContent(i) << std::endl;
839 break;
841 fout << fFourierAverage[0].dataFourierPwr->GetBinCenter(i) << ", " << fFourierAverage[0].dataFourierPwr->GetBinContent(i) << std::endl;
842 break;
844 fout << fFourierAverage[0].dataFourierPhase->GetBinCenter(i) << ", " << fFourierAverage[0].dataFourierPhase->GetBinContent(i) << std::endl;
845 break;
847 fout << fFourierAverage[0].dataFourierPhaseOptReal->GetBinCenter(i) << ", " << fFourierAverage[0].dataFourierPhaseOptReal->GetBinContent(i) << std::endl;
848 break;
849 default:
850 break;
851 }
852 }
853 } else {
854 // write header
855 fout << "% " << pfn << std::endl;
856 fout << "% data of:" << std::endl;
857 for (UInt_t i=0; i<fFourierHistos.size(); i++) {
858 fout << "% " << fFourierHistos[i].dataFourierRe->GetTitle() << std::endl;
859 }
860 fout << "%------------" << std::endl;
861 fout << "% ";
862 for (UInt_t i=0; i<fFourierHistos.size()-1; i++) {
863 fout << xAxis << i << ", " << yAxis << i << ", ";
864 }
865 fout << xAxis << fFourierHistos.size()-1 << ", " << yAxis << fFourierHistos.size()-1 << std::endl;
866
867 // write data
868 for (Int_t i=xMinBin; i<xMaxBin; i++) {
869 for (UInt_t j=0; j<fFourierHistos.size()-1; j++) {
870 switch (fCurrentPlotView) {
872 fout << fFourierHistos[j].dataFourierRe->GetBinCenter(i) << ", " << fFourierHistos[j].dataFourierRe->GetBinContent(i) << ", ";
873 break;
875 fout << fFourierHistos[j].dataFourierIm->GetBinCenter(i) << ", " << fFourierHistos[j].dataFourierIm->GetBinContent(i) << ", ";
876 break;
878 break;
880 fout << fFourierHistos[j].dataFourierPwr->GetBinCenter(i) << ", " << fFourierHistos[j].dataFourierPwr->GetBinContent(i) << ", ";
881 break;
883 fout << fFourierHistos[j].dataFourierPhase->GetBinCenter(i) << ", " << fFourierHistos[j].dataFourierPhase->GetBinContent(i) << ", ";
884 break;
886 fout << fFourierHistos[j].dataFourierPhaseOptReal->GetBinCenter(i) << ", " << fFourierHistos[j].dataFourierPhaseOptReal->GetBinContent(i) << ", ";
887 break;
888 default:
889 break;
890 }
891 }
892 switch (fCurrentPlotView) {
894 fout << fFourierHistos[fFourierHistos.size()-1].dataFourierRe->GetBinCenter(i) << ", " << fFourierHistos[fFourierHistos.size()-1].dataFourierRe->GetBinContent(i) << std::endl;
895 break;
897 fout << fFourierHistos[fFourierHistos.size()-1].dataFourierIm->GetBinCenter(i) << ", " << fFourierHistos[fFourierHistos.size()-1].dataFourierIm->GetBinContent(i) << std::endl;
898 break;
900 break;
902 fout << fFourierHistos[fFourierHistos.size()-1].dataFourierPwr->GetBinCenter(i) << ", " << fFourierHistos[fFourierHistos.size()-1].dataFourierPwr->GetBinContent(i) << std::endl;
903 break;
905 fout << fFourierHistos[fFourierHistos.size()-1].dataFourierPhase->GetBinCenter(i) << ", " << fFourierHistos[fFourierHistos.size()-1].dataFourierPhase->GetBinContent(i) << std::endl;
906 break;
908 fout << fFourierHistos[fFourierHistos.size()-1].dataFourierPhaseOptReal->GetBinCenter(i) << ", " << fFourierHistos[fFourierHistos.size()-1].dataFourierPhaseOptReal->GetBinContent(i) << std::endl;
909 break;
910 default:
911 break;
912 }
913 }
914 }
915
916 fout.close();
917}
918
919//--------------------------------------------------------------------------
920// CreateXaxisTitle (private)
921//--------------------------------------------------------------------------
926{
927 switch (fFourier[0]->GetUnitTag()) {
929 fXaxisTitle = TString("Field (Gauss)");
930 break;
932 fXaxisTitle = TString("Field (Tesla)");
933 break;
935 fXaxisTitle = TString("Frequency (MHz)");
936 break;
938 fXaxisTitle = TString("Angular Frequency (Mc/s)");
939 break;
940 default:
941 fXaxisTitle = TString("??");
942 break;
943 }
944}
945
946//--------------------------------------------------------------------------
947// CreateStyle (private)
948//--------------------------------------------------------------------------
953{
954 TString musrFTStyle("musrFTStyle");
955 fStyle = std::make_unique<TStyle>(musrFTStyle, musrFTStyle);
956 fStyle->SetOptStat(0); // no statistics options
957 fStyle->SetOptTitle(0); // no title
958 fStyle->cd();
959}
960
961//--------------------------------------------------------------------------
962// InitFourierDataSets (private)
963//--------------------------------------------------------------------------
969{
970 // get all the Fourier histos
971 fFourierHistos.resize(fFourier.size());
972 for (UInt_t i=0; i<fFourierHistos.size(); i++) {
973 fFourierHistos[i].dataFourierRe = fFourier[i]->GetRealFourier();
974 fFourierHistos[i].dataFourierIm = fFourier[i]->GetImaginaryFourier();
975 fFourierHistos[i].dataFourierPwr = fFourier[i]->GetPowerFourier();
976 fFourierHistos[i].dataFourierPhase = fFourier[i]->GetPhaseFourier();
978 fFourierHistos[i].dataFourierPhaseOptReal = fFourier[i]->GetPhaseOptRealFourier(fFourierHistos[i].dataFourierRe,
979 fFourierHistos[i].dataFourierIm, fFourierHistos[i].optPhase, 1.0, fInitialXRange[0], fInitialXRange[1]);
980 }
981 }
982
983 // rescale histo to abs(maximum) == 1
984 Double_t max = 0.0, dval = 0.0;
985 Int_t start = fFourierHistos[0].dataFourierRe->FindBin(fInitialXRange[0]);
986 Int_t end = fFourierHistos[0].dataFourierRe->FindBin(fInitialXRange[1]);
987 // real
988 for (UInt_t i=0; i<fFourierHistos.size(); i++) {
989 for (Int_t j=start; j<=end; j++) {
990 dval = fFourierHistos[i].dataFourierRe->GetBinContent(j);
991 if (fabs(dval) > max)
992 max = dval;
993 }
994 }
995 for (UInt_t i=0; i<fFourierHistos.size(); i++) {
996 for (Int_t j=1; j<fFourierHistos[i].dataFourierRe->GetNbinsX(); j++) {
997 fFourierHistos[i].dataFourierRe->SetBinContent(j, fFourierHistos[i].dataFourierRe->GetBinContent(j)/fabs(max));
998 }
999 }
1000
1001 // imaginary
1002 for (UInt_t i=0; i<fFourierHistos.size(); i++) {
1003 for (Int_t j=start; j<=end; j++) {
1004 dval = fFourierHistos[i].dataFourierIm->GetBinContent(j);
1005 if (fabs(dval) > max)
1006 max = dval;
1007 }
1008 }
1009 for (UInt_t i=0; i<fFourierHistos.size(); i++) {
1010 for (Int_t j=1; j<fFourierHistos[i].dataFourierIm->GetNbinsX(); j++) {
1011 fFourierHistos[i].dataFourierIm->SetBinContent(j, fFourierHistos[i].dataFourierIm->GetBinContent(j)/fabs(max));
1012 }
1013 }
1014
1015 // power
1016 max = 0.0;
1017 for (UInt_t i=0; i<fFourierHistos.size(); i++) {
1018 for (Int_t j=start; j<=end; j++) {
1019 dval = fFourierHistos[i].dataFourierPwr->GetBinContent(j);
1020 if (fabs(dval) > max)
1021 max = dval;
1022 }
1023 }
1024 for (UInt_t i=0; i<fFourierHistos.size(); i++) {
1025 for (Int_t j=1; j<fFourierHistos[i].dataFourierPwr->GetNbinsX(); j++) {
1026 fFourierHistos[i].dataFourierPwr->SetBinContent(j, fFourierHistos[i].dataFourierPwr->GetBinContent(j)/fabs(max));
1027 }
1028 }
1029
1030 // phase
1031 max = 0.0;
1032 for (UInt_t i=0; i<fFourierHistos.size(); i++) {
1033 for (Int_t j=start; j<=end; j++) {
1034 dval = fFourierHistos[i].dataFourierPhase->GetBinContent(j);
1035 if (fabs(dval) > max)
1036 max = dval;
1037 }
1038 }
1039 for (UInt_t i=0; i<fFourierHistos.size(); i++) {
1040 for (Int_t j=1; j<fFourierHistos[i].dataFourierPhase->GetNbinsX(); j++) {
1041 fFourierHistos[i].dataFourierPhase->SetBinContent(j, fFourierHistos[i].dataFourierPhase->GetBinContent(j)/fabs(max));
1042 }
1043 }
1044
1046 // phase opt real
1047 for (UInt_t i=0; i<fFourierHistos.size(); i++) {
1048 for (Int_t j=start; j<=end; j++) {
1049 dval = fFourierHistos[i].dataFourierPhaseOptReal->GetBinContent(j);
1050 if (fabs(dval) > max)
1051 max = dval;
1052 }
1053 }
1054 for (UInt_t i=0; i<fFourierHistos.size(); i++) {
1055 for (Int_t j=1; j<fFourierHistos[i].dataFourierPhaseOptReal->GetNbinsX(); j++) {
1056 fFourierHistos[i].dataFourierPhaseOptReal->SetBinContent(j, fFourierHistos[i].dataFourierPhaseOptReal->GetBinContent(j)/fabs(max));
1057 }
1058 }
1059 }
1060
1061 // set the marker and line color
1062 for (UInt_t i=0; i<fFourierHistos.size(); i++) {
1063 fFourierHistos[i].dataFourierRe->SetMarkerColor(fColorList[i]);
1064 fFourierHistos[i].dataFourierRe->SetLineColor(fColorList[i]);
1065 fFourierHistos[i].dataFourierIm->SetMarkerColor(fColorList[i]);
1066 fFourierHistos[i].dataFourierIm->SetLineColor(fColorList[i]);
1067 fFourierHistos[i].dataFourierPwr->SetMarkerColor(fColorList[i]);
1068 fFourierHistos[i].dataFourierPwr->SetLineColor(fColorList[i]);
1069 fFourierHistos[i].dataFourierPhase->SetMarkerColor(fColorList[i]);
1070 fFourierHistos[i].dataFourierPhase->SetLineColor(fColorList[i]);
1072 fFourierHistos[i].dataFourierPhaseOptReal->SetMarkerColor(fColorList[i]);
1073 fFourierHistos[i].dataFourierPhaseOptReal->SetLineColor(fColorList[i]);
1074 }
1075 }
1076
1077 // set the marker symbol and size
1078 for (UInt_t i=0; i<fFourierHistos.size(); i++) {
1079 fFourierHistos[i].dataFourierRe->SetMarkerStyle(fMarkerList[i]);
1080 fFourierHistos[i].dataFourierRe->SetMarkerSize(0.7);
1081 fFourierHistos[i].dataFourierIm->SetMarkerStyle(fMarkerList[i]);
1082 fFourierHistos[i].dataFourierIm->SetMarkerSize(0.7);
1083 fFourierHistos[i].dataFourierPwr->SetMarkerStyle(fMarkerList[i]);
1084 fFourierHistos[i].dataFourierPwr->SetMarkerSize(0.7);
1085 fFourierHistos[i].dataFourierPhase->SetMarkerStyle(fMarkerList[i]);
1086 fFourierHistos[i].dataFourierPhase->SetMarkerSize(0.7);
1088 fFourierHistos[i].dataFourierPhaseOptReal->SetMarkerStyle(fMarkerList[i]);
1089 fFourierHistos[i].dataFourierPhaseOptReal->SetMarkerSize(0.7);
1090 }
1091 }
1092
1093 // initialize average histos
1095}
1096
1097//--------------------------------------------------------------------------
1098// InitFourierCanvas (private)
1099//--------------------------------------------------------------------------
1109void PFourierCanvas::InitFourierCanvas(const Char_t* title, Int_t wtopx, Int_t wtopy, Int_t ww, Int_t wh)
1110{
1111 fImp = nullptr;
1112 fBar = nullptr;
1113 fPopupMain = nullptr;
1114
1115 // invoke canvas
1116 TString canvasName = TString("fMainCanvas");
1117 fMainCanvas = std::make_unique<TCanvas>(canvasName.Data(), title, wtopx, wtopy, ww, wh);
1118
1119 // add canvas menu if not in batch mode
1120 if (!fBatchMode) {
1121 fImp = static_cast<TRootCanvas*>(fMainCanvas->GetCanvasImp());
1122 fBar = fImp->GetMenuBar();
1123 fPopupMain = fBar->AddPopup("MusrFT");
1124
1125 fPopupFourier = std::make_unique<TGPopupMenu>();
1126
1127 fPopupMain->AddPopup("&Fourier", fPopupFourier.get());
1131 fPopupFourier->AddEntry("Show Power", P_MENU_ID_FOURIER+P_MENU_ID_FOURIER_PWR);
1133 fPopupFourier->AddEntry("Show Phase Opt Fourier", P_MENU_ID_FOURIER+P_MENU_ID_FOURIER_PHASE_OPT_REAL);
1134 fPopupFourier->AddSeparator();
1139
1140 switch (fCurrentPlotView) {
1141 case FOURIER_PLOT_REAL:
1143 break;
1144 case FOURIER_PLOT_IMAG:
1146 break;
1149 break;
1150 case FOURIER_PLOT_POWER:
1152 break;
1153 case FOURIER_PLOT_PHASE:
1155 break;
1158 break;
1159 default:
1160 break;
1161 }
1162
1163 fPopupMain->AddEntry("Average", P_MENU_ID_AVERAGE);
1164 if (fAveragedView)
1165 fPopupMain->CheckEntry(P_MENU_ID_AVERAGE);
1166 fPopupMain->AddEntry("Average per Data Set", P_MENU_ID_AVERAGE_PER_DATA_SET);
1169 fPopupMain->AddSeparator();
1170
1171 fPopupMain->AddEntry("Export Data", P_MENU_ID_EXPORT_DATA);
1172 fBar->MapSubwindows();
1173 fBar->Layout();
1174
1175 fPopupMain->Connect("TGPopupMenu", "Activated(Int_t)", "PFourierCanvas", this, "HandleMenuPopup(Int_t)");
1176 }
1177
1178 // divide the canvas into sub pads
1179 // title pad
1180 fTitlePad = std::make_unique<TPaveText>(0.0, YTITLE, 1.0, 1.0, "NDC");
1181
1182 fTitlePad->SetFillColor(TColor::GetColor(255,255,255));
1183 fTitlePad->SetTextAlign(12); // middle, left
1184 fTitlePad->AddText(title);
1185 fTitlePad->Draw();
1186
1187 // fourier pad
1188 fFourierPad = std::make_unique<TPad>("fFourierPad", "fFourierPad", 0.0, YINFO, 1.0, YTITLE);
1189
1190 fFourierPad->SetFillColor(TColor::GetColor(255,255,255));
1191 fFourierPad->Draw();
1192
1193 // info pad
1194 fInfoPad = std::make_unique<TLegend>(0.0, 0.0, 1.0, YINFO, "NDC");
1195
1196 fInfoPad->SetFillColor(TColor::GetColor(255,255,255));
1197 fInfoPad->SetTextAlign(12); // middle, left
1198
1199 fValid = true;
1200
1201 if ((fFourier.size() != fDataSetTag.size()) && fAveragedViewPerDataSet) {
1202 fValid = false;
1203 std::cerr << std::endl << "PFourierCanvas::PFourierCanvas: **PANIC ERROR**: # Fourier != # Data Set Tags." << std::endl;
1204 }
1205
1206 fMainCanvas->cd();
1207
1208 fMainCanvas->Show();
1209
1210 fMainCanvas->Connect("ProcessedEvent(Int_t,Int_t,Int_t,TObject*)", "PFourierCanvas",
1211 this, "HandleCmdKey(Int_t,Int_t,Int_t,TObject*)");
1212}
1213
1214//--------------------------------------------------------------------------
1215// CleanupAverage (private)
1216//--------------------------------------------------------------------------
1221{
1222 for (UInt_t i=0; i<fFourierAverage.size(); i++) {
1223 if (fFourierAverage[i].dataFourierRe != nullptr) {
1224 delete fFourierAverage[i].dataFourierRe;
1225 fFourierAverage[i].dataFourierRe = nullptr;
1226 }
1227 if (fFourierAverage[i].dataFourierIm) {
1228 delete fFourierAverage[i].dataFourierIm;
1229 fFourierAverage[i].dataFourierIm = nullptr;
1230 }
1231 if (fFourierAverage[i].dataFourierPwr) {
1232 delete fFourierAverage[i].dataFourierPwr;
1233 fFourierAverage[i].dataFourierPwr = nullptr;
1234 }
1235 if (fFourierAverage[i].dataFourierPhase) {
1236 delete fFourierAverage[i].dataFourierPhase;
1237 fFourierAverage[i].dataFourierPhase = nullptr;
1238 }
1239 if (fFourierAverage[i].dataFourierPhaseOptReal) {
1240 delete fFourierAverage[i].dataFourierPhaseOptReal;
1241 fFourierAverage[i].dataFourierPhaseOptReal = nullptr;
1242 }
1243 }
1244 fFourierAverage.clear();
1245}
1246
1247//--------------------------------------------------------------------------
1248// HandleAverage (private)
1249//--------------------------------------------------------------------------
1254{
1255 if (fFourierHistos.size() == 0)
1256 return;
1257
1259
1260 TString name("");
1261 Double_t dval=0.0;
1262
1263 Bool_t phaseOptRealPresent = false;
1264 if (fFourierHistos[0].dataFourierPhaseOptReal != nullptr)
1265 phaseOptRealPresent = true;
1266
1267 // check if ALL data shall be averaged
1268 if (fAveragedView) {
1269 fFourierAverage.resize(1);
1270
1271 // create average histograms
1272 name = TString(fFourierHistos[0].dataFourierRe->GetTitle()) + "_avg";
1273 fFourierAverage[0].dataFourierRe = new TH1F(name, name, fFourierHistos[0].dataFourierRe->GetNbinsX(),
1274 fFourierHistos[0].dataFourierRe->GetXaxis()->GetXmin(),
1275 fFourierHistos[0].dataFourierRe->GetXaxis()->GetXmax());
1276
1277 name = TString(fFourierHistos[0].dataFourierIm->GetTitle()) + "_avg";
1278 fFourierAverage[0].dataFourierIm = new TH1F(name, name, fFourierHistos[0].dataFourierIm->GetNbinsX(),
1279 fFourierHistos[0].dataFourierIm->GetXaxis()->GetXmin(),
1280 fFourierHistos[0].dataFourierIm->GetXaxis()->GetXmax());
1281
1282 name = TString(fFourierHistos[0].dataFourierPwr->GetTitle()) + "_avg";
1283 fFourierAverage[0].dataFourierPwr = new TH1F(name, name, fFourierHistos[0].dataFourierPwr->GetNbinsX(),
1284 fFourierHistos[0].dataFourierPwr->GetXaxis()->GetXmin(),
1285 fFourierHistos[0].dataFourierPwr->GetXaxis()->GetXmax());
1286
1287 name = TString(fFourierHistos[0].dataFourierPhase->GetTitle()) + "_avg";
1288 fFourierAverage[0].dataFourierPhase = new TH1F(name, name, fFourierHistos[0].dataFourierPhase->GetNbinsX(),
1289 fFourierHistos[0].dataFourierPhase->GetXaxis()->GetXmin(),
1290 fFourierHistos[0].dataFourierPhase->GetXaxis()->GetXmax());
1291
1292 if (phaseOptRealPresent) {
1293 name = TString(fFourierHistos[0].dataFourierPhaseOptReal->GetTitle()) + "_avg";
1294 fFourierAverage[0].dataFourierPhaseOptReal = new TH1F(name, name, fFourierHistos[0].dataFourierPhaseOptReal->GetNbinsX(),
1295 fFourierHistos[0].dataFourierPhaseOptReal->GetXaxis()->GetXmin(),
1296 fFourierHistos[0].dataFourierPhaseOptReal->GetXaxis()->GetXmax());
1297 }
1298
1299 // real average
1300 for (Int_t j=0; j<fFourierHistos[0].dataFourierRe->GetNbinsX(); j++) {
1301 dval = 0.0;
1302 for (UInt_t i=0; i<fFourierHistos.size(); i++) {
1303 if (j < fFourierHistos[i].dataFourierRe->GetNbinsX())
1304 dval += GetInterpolatedValue(fFourierHistos[i].dataFourierRe, fFourierHistos[0].dataFourierRe->GetBinCenter(j));
1305 }
1306 fFourierAverage[0].dataFourierRe->SetBinContent(j, dval/fFourierHistos.size());
1307 }
1308 // set marker color, line color, maker size, marker type
1309 fFourierAverage[0].dataFourierRe->SetMarkerColor(kBlack);
1310 fFourierAverage[0].dataFourierRe->SetLineColor(kBlack);
1311 fFourierAverage[0].dataFourierRe->SetMarkerSize(0.8);
1312 fFourierAverage[0].dataFourierRe->SetMarkerStyle(22); // closed up triangle
1313
1314 // imaginary average
1315 for (Int_t j=0; j<fFourierHistos[0].dataFourierIm->GetNbinsX(); j++) {
1316 dval = 0.0;
1317 for (UInt_t i=0; i<fFourierHistos.size(); i++) {
1318 if (j < fFourierHistos[i].dataFourierIm->GetNbinsX())
1319 dval += GetInterpolatedValue(fFourierHistos[i].dataFourierIm, fFourierHistos[0].dataFourierIm->GetBinCenter(j));
1320 }
1321 fFourierAverage[0].dataFourierIm->SetBinContent(j, dval/fFourierHistos.size());
1322 }
1323 // set marker color, line color, maker size, marker type
1324 fFourierAverage[0].dataFourierIm->SetMarkerColor(kBlack);
1325 fFourierAverage[0].dataFourierIm->SetLineColor(kBlack);
1326 fFourierAverage[0].dataFourierIm->SetMarkerSize(0.8);
1327 fFourierAverage[0].dataFourierIm->SetMarkerStyle(22); // closed up triangle
1328
1329 // power average
1330 for (Int_t j=0; j<fFourierHistos[0].dataFourierPwr->GetNbinsX(); j++) {
1331 dval = 0.0;
1332 for (UInt_t i=0; i<fFourierHistos.size(); i++) {
1333 if (j < fFourierHistos[i].dataFourierPwr->GetNbinsX())
1334 dval += GetInterpolatedValue(fFourierHistos[i].dataFourierPwr, fFourierHistos[0].dataFourierPwr->GetBinCenter(j));
1335 }
1336 fFourierAverage[0].dataFourierPwr->SetBinContent(j, dval/fFourierHistos.size());
1337 }
1338 // set marker color, line color, maker size, marker type
1339 fFourierAverage[0].dataFourierPwr->SetMarkerColor(kBlack);
1340 fFourierAverage[0].dataFourierPwr->SetLineColor(kBlack);
1341 fFourierAverage[0].dataFourierPwr->SetMarkerSize(0.8);
1342 fFourierAverage[0].dataFourierPwr->SetMarkerStyle(22); // closed up triangle
1343
1344 // phase average
1345 for (Int_t j=0; j<fFourierHistos[0].dataFourierPhase->GetNbinsX(); j++) {
1346 dval = 0.0;
1347 for (UInt_t i=0; i<fFourierHistos.size(); i++) {
1348 if (j < fFourierHistos[i].dataFourierPhase->GetNbinsX())
1349 dval += GetInterpolatedValue(fFourierHistos[i].dataFourierPhase, fFourierHistos[0].dataFourierPhase->GetBinCenter(j));
1350 }
1351 fFourierAverage[0].dataFourierPhase->SetBinContent(j, dval/fFourierHistos.size());
1352 }
1353 // set marker color, line color, maker size, marker type
1354 fFourierAverage[0].dataFourierPhase->SetMarkerColor(kBlack);
1355 fFourierAverage[0].dataFourierPhase->SetLineColor(kBlack);
1356 fFourierAverage[0].dataFourierPhase->SetMarkerSize(0.8);
1357 fFourierAverage[0].dataFourierPhase->SetMarkerStyle(22);
1358
1359 if (phaseOptRealPresent) {
1360 // phase optimised real average
1361 for (Int_t j=0; j<fFourierHistos[0].dataFourierPhaseOptReal->GetNbinsX(); j++) {
1362 dval = 0.0;
1363 for (UInt_t i=0; i<fFourierHistos.size(); i++) {
1364 if (j < fFourierHistos[i].dataFourierPhaseOptReal->GetNbinsX())
1365 dval += GetInterpolatedValue(fFourierHistos[i].dataFourierPhaseOptReal, fFourierHistos[0].dataFourierPhaseOptReal->GetBinCenter(j));
1366 }
1367 fFourierAverage[0].dataFourierPhaseOptReal->SetBinContent(j, dval/fFourierHistos.size());
1368 }
1369 // set marker color, line color, maker size, marker type
1370 fFourierAverage[0].dataFourierPhaseOptReal->SetMarkerColor(kBlack);
1371 fFourierAverage[0].dataFourierPhaseOptReal->SetLineColor(kBlack);
1372 fFourierAverage[0].dataFourierPhaseOptReal->SetMarkerSize(0.8);
1373 fFourierAverage[0].dataFourierPhaseOptReal->SetMarkerStyle(22);
1374 }
1375 }
1376
1377 // check if per data set shall be averaged
1379 // check what size is required
1380 UInt_t count = 1;
1381 Int_t currentTag = fDataSetTag[0];
1382 for (UInt_t i=1; i<fDataSetTag.size(); i++) {
1383 if (fDataSetTag[i] != currentTag) {
1384 currentTag = fDataSetTag[i];
1385 count++;
1386 }
1387 }
1388 fFourierAverage.resize(count);
1389
1390 Int_t start=0, end=0;
1391 for (UInt_t i=0; i<fFourierAverage.size(); i++) {
1392 // get data set range
1393 count = 0;
1394 currentTag = fDataSetTag[0];
1395 start = -1, end = -1;
1396 for (UInt_t j=0; j<fDataSetTag.size(); j++) {
1397 if ((count == i) && (start == -1)) {
1398 if (j > 0)
1399 start = j-1;
1400 else
1401 start = 0;
1402 }
1403 if (currentTag != fDataSetTag[j]) {
1404 if (count == i) {
1405 end = j-1;
1406 break;
1407 }
1408 count++;
1409 currentTag = fDataSetTag[j];
1410 }
1411 }
1412 if (start == -1)
1413 start = fDataSetTag.size()-1;
1414 if (end == -1)
1415 end = fDataSetTag.size()-1;
1416
1417 // create average histograms
1418 name = TString(fFourierHistos[start].dataFourierRe->GetTitle()) + "_avg";
1419 fFourierAverage[i].dataFourierRe = new TH1F(name, name, fFourierHistos[0].dataFourierRe->GetNbinsX(),
1420 fFourierHistos[0].dataFourierRe->GetXaxis()->GetXmin(),
1421 fFourierHistos[0].dataFourierRe->GetXaxis()->GetXmax());
1422
1423 name = TString(fFourierHistos[start].dataFourierIm->GetTitle()) + "_avg";
1424 fFourierAverage[i].dataFourierIm = new TH1F(name, name, fFourierHistos[0].dataFourierIm->GetNbinsX(),
1425 fFourierHistos[0].dataFourierIm->GetXaxis()->GetXmin(),
1426 fFourierHistos[0].dataFourierIm->GetXaxis()->GetXmax());
1427
1428 name = TString(fFourierHistos[start].dataFourierPwr->GetTitle()) + "_avg";
1429 fFourierAverage[i].dataFourierPwr = new TH1F(name, name, fFourierHistos[0].dataFourierPwr->GetNbinsX(),
1430 fFourierHistos[0].dataFourierPwr->GetXaxis()->GetXmin(),
1431 fFourierHistos[0].dataFourierPwr->GetXaxis()->GetXmax());
1432
1433 name = TString(fFourierHistos[start].dataFourierPhase->GetTitle()) + "_avg";
1434 fFourierAverage[i].dataFourierPhase = new TH1F(name, name, fFourierHistos[0].dataFourierPhase->GetNbinsX(),
1435 fFourierHistos[0].dataFourierPhase->GetXaxis()->GetXmin(),
1436 fFourierHistos[0].dataFourierPhase->GetXaxis()->GetXmax());
1437
1438 if (phaseOptRealPresent) {
1439 name = TString(fFourierHistos[start].dataFourierPhaseOptReal->GetTitle()) + "_avg";
1440 fFourierAverage[i].dataFourierPhaseOptReal = new TH1F(name, name, fFourierHistos[0].dataFourierPhaseOptReal->GetNbinsX(),
1441 fFourierHistos[0].dataFourierPhaseOptReal->GetXaxis()->GetXmin(),
1442 fFourierHistos[0].dataFourierPhaseOptReal->GetXaxis()->GetXmax());
1443 }
1444
1445 // real average
1446 for (Int_t j=0; j<fFourierHistos[0].dataFourierRe->GetNbinsX(); j++) {
1447 dval = 0.0;
1448 for (Int_t k=start; k<=end; k++) {
1449 if (j < fFourierHistos[k].dataFourierRe->GetNbinsX())
1450 dval += GetInterpolatedValue(fFourierHistos[k].dataFourierRe, fFourierHistos[0].dataFourierRe->GetBinCenter(j));
1451 }
1452 fFourierAverage[i].dataFourierRe->SetBinContent(j, dval/(end-start+1));
1453 }
1454 // set marker color, line color, maker size, marker type
1455 fFourierAverage[i].dataFourierRe->SetMarkerColor(fColorList[i]);
1456 fFourierAverage[i].dataFourierRe->SetLineColor(fColorList[i]);
1457 fFourierAverage[i].dataFourierRe->SetMarkerSize(0.8);
1458 fFourierAverage[i].dataFourierRe->SetMarkerStyle(22); // closed up triangle
1459
1460 // imaginary average
1461 for (Int_t j=0; j<fFourierHistos[0].dataFourierIm->GetNbinsX(); j++) {
1462 dval = 0.0;
1463 for (Int_t k=start; k<=end; k++) {
1464 if (j < fFourierHistos[k].dataFourierIm->GetNbinsX())
1465 dval += GetInterpolatedValue(fFourierHistos[k].dataFourierIm, fFourierHistos[0].dataFourierIm->GetBinCenter(j));
1466 }
1467 fFourierAverage[i].dataFourierIm->SetBinContent(j, dval/(end-start+1));
1468 }
1469 // set marker color, line color, maker size, marker type
1470 fFourierAverage[i].dataFourierIm->SetMarkerColor(fColorList[i]);
1471 fFourierAverage[i].dataFourierIm->SetLineColor(fColorList[i]);
1472 fFourierAverage[i].dataFourierIm->SetMarkerSize(0.8);
1473 fFourierAverage[i].dataFourierIm->SetMarkerStyle(22); // closed up triangle
1474
1475 // power average
1476 for (Int_t j=0; j<fFourierHistos[0].dataFourierPwr->GetNbinsX(); j++) {
1477 dval = 0.0;
1478 for (Int_t k=start; k<=end; k++) {
1479 if (j < fFourierHistos[k].dataFourierPwr->GetNbinsX())
1480 dval += GetInterpolatedValue(fFourierHistos[k].dataFourierPwr, fFourierHistos[0].dataFourierPwr->GetBinCenter(j));
1481 }
1482 fFourierAverage[i].dataFourierPwr->SetBinContent(j, dval/(end-start+1));
1483 }
1484 // set marker color, line color, maker size, marker type
1485 fFourierAverage[i].dataFourierPwr->SetMarkerColor(fColorList[i]);
1486 fFourierAverage[i].dataFourierPwr->SetLineColor(fColorList[i]);
1487 fFourierAverage[i].dataFourierPwr->SetMarkerSize(0.8);
1488 fFourierAverage[i].dataFourierPwr->SetMarkerStyle(22); // closed up triangle
1489
1490 // phase average
1491 for (Int_t j=0; j<fFourierHistos[0].dataFourierPhase->GetNbinsX(); j++) {
1492 dval = 0.0;
1493 for (Int_t k=start; k<=end; k++) {
1494 if (j < fFourierHistos[k].dataFourierPhase->GetNbinsX())
1495 dval += GetInterpolatedValue(fFourierHistos[k].dataFourierPhase, fFourierHistos[0].dataFourierPhase->GetBinCenter(j));
1496 }
1497 fFourierAverage[i].dataFourierPhase->SetBinContent(j, dval/(end-start+1));
1498 }
1499 // set marker color, line color, maker size, marker type
1500 fFourierAverage[i].dataFourierPhase->SetMarkerColor(fColorList[i]);
1501 fFourierAverage[i].dataFourierPhase->SetLineColor(fColorList[i]);
1502 fFourierAverage[i].dataFourierPhase->SetMarkerSize(0.8);
1503 fFourierAverage[i].dataFourierPhase->SetMarkerStyle(22); // closed up triangle
1504
1505 if (phaseOptRealPresent) {
1506 // phase optimised real average
1507 for (Int_t j=0; j<fFourierHistos[0].dataFourierPhaseOptReal->GetNbinsX(); j++) {
1508 dval = 0.0;
1509 for (Int_t k=start; k<=end; k++) {
1510 if (j < fFourierHistos[k].dataFourierPhaseOptReal->GetNbinsX())
1511 dval += GetInterpolatedValue(fFourierHistos[k].dataFourierPhaseOptReal, fFourierHistos[0].dataFourierPhaseOptReal->GetBinCenter(j));
1512 }
1513 fFourierAverage[i].dataFourierPhaseOptReal->SetBinContent(j, dval/(end-start+1));
1514 }
1515 // set marker color, line color, maker size, marker type
1516 fFourierAverage[i].dataFourierPhaseOptReal->SetMarkerColor(fColorList[i]);
1517 fFourierAverage[i].dataFourierPhaseOptReal->SetLineColor(fColorList[i]);
1518 fFourierAverage[i].dataFourierPhaseOptReal->SetMarkerSize(0.8);
1519 fFourierAverage[i].dataFourierPhaseOptReal->SetMarkerStyle(22); // closed up triangle
1520 }
1521 }
1522 }
1523}
1524
1525//--------------------------------------------------------------------------
1526// CalcPhaseOptReal (private)
1527//--------------------------------------------------------------------------
1532{
1533 Int_t start = fFourierHistos[0].dataFourierRe->FindFixBin(fInitialXRange[0]);
1534 Int_t end = fFourierHistos[0].dataFourierRe->FindFixBin(fInitialXRange[1]);
1535
1536 Double_t dval=0.0, max=0.0;
1537 for (UInt_t i=0; i<fFourierHistos.size(); i++) {
1538 fFourierHistos[i].dataFourierPhaseOptReal = fFourier[i]->GetPhaseOptRealFourier(fFourierHistos[i].dataFourierRe,
1539 fFourierHistos[i].dataFourierIm, fFourierHistos[i].optPhase, 1.0, fInitialXRange[0], fInitialXRange[1]);
1540 // normalize it
1541 max = 0.0;
1542 for (Int_t j=start; j<=end; j++) {
1543 dval = fFourierHistos[i].dataFourierPhaseOptReal->GetBinContent(j);
1544 if (fabs(dval) > max)
1545 max = dval;
1546 }
1547 for (Int_t j=1; j<fFourierHistos[i].dataFourierPhaseOptReal->GetNbinsX(); j++) {
1548 fFourierHistos[i].dataFourierPhaseOptReal->SetBinContent(j, fFourierHistos[i].dataFourierPhaseOptReal->GetBinContent(j)/fabs(max));
1549 }
1550 // set the marker and line color
1551 fFourierHistos[i].dataFourierPhaseOptReal->SetMarkerColor(fColorList[i]);
1552 fFourierHistos[i].dataFourierPhaseOptReal->SetLineColor(fColorList[i]);
1553
1554 // set the marker symbol and size
1555 fFourierHistos[i].dataFourierPhaseOptReal->SetMarkerStyle(fMarkerList[i]);
1556 fFourierHistos[i].dataFourierPhaseOptReal->SetMarkerSize(0.7);
1557 }
1558}
1559
1560//--------------------------------------------------------------------------
1561// PlotFourier (private)
1562//--------------------------------------------------------------------------
1567{
1568 // check if phase opt real Fourier spectra already exists if requested,
1569 // and if not calculate them first
1571 if (fFourierHistos[0].dataFourierPhaseOptReal == nullptr) { // not yet calculated
1573 }
1574 }
1575
1576 fFourierPad->cd();
1577
1578 Double_t xmin=0, xmax=0;
1579 xmin = fInitialXRange[0];
1580 xmax = fInitialXRange[1];
1581
1582 Double_t ymin=0, ymax=0;
1583 switch (fCurrentPlotView) {
1584 case FOURIER_PLOT_REAL:
1585 fFourierHistos[0].dataFourierRe->GetXaxis()->SetRangeUser(xmin, xmax);
1586 ymin = GetMinimum(fFourierHistos[0].dataFourierRe, xmin, xmax);
1587 ymax = GetMaximum(fFourierHistos[0].dataFourierRe, xmin, xmax);
1588 for (UInt_t i=1; i<fFourierHistos.size(); i++) {
1589 if (GetMaximum(fFourierHistos[i].dataFourierRe, xmin, xmax) > ymax)
1590 ymax = GetMaximum(fFourierHistos[i].dataFourierRe, xmin, xmax);
1591 if (GetMinimum(fFourierHistos[i].dataFourierRe, xmin, xmax) < ymin)
1592 ymin = GetMinimum(fFourierHistos[i].dataFourierRe, xmin, xmax);
1593 }
1594 fFourierHistos[0].dataFourierRe->GetYaxis()->SetRangeUser(1.05*ymin, 1.05*ymax);
1595 fFourierHistos[0].dataFourierRe->GetYaxis()->SetTitle("Real");
1596 fFourierHistos[0].dataFourierRe->GetYaxis()->SetTitleOffset(1.3);
1597 fFourierHistos[0].dataFourierRe->GetYaxis()->SetDecimals(kTRUE);
1598 fFourierHistos[0].dataFourierRe->GetXaxis()->SetTitle(fXaxisTitle.Data());
1599 fFourierHistos[0].dataFourierRe->Draw("p");
1600 for (UInt_t i=1; i<fFourierHistos.size(); i++) {
1601 fFourierHistos[i].dataFourierRe->Draw("psame");
1602 }
1603 break;
1604 case FOURIER_PLOT_IMAG:
1605 fFourierHistos[0].dataFourierIm->GetXaxis()->SetRangeUser(xmin, xmax);
1606 ymin = GetMinimum(fFourierHistos[0].dataFourierIm, xmin, xmax);
1607 ymax = GetMaximum(fFourierHistos[0].dataFourierIm, xmin, xmax);
1608 for (UInt_t i=1; i<fFourierHistos.size(); i++) {
1609 if (GetMaximum(fFourierHistos[i].dataFourierIm, xmin, xmax) > ymax)
1610 ymax = GetMaximum(fFourierHistos[i].dataFourierIm, xmin, xmax);
1611 if (GetMinimum(fFourierHistos[i].dataFourierIm, xmin, xmax) < ymin)
1612 ymin = GetMinimum(fFourierHistos[i].dataFourierIm, xmin, xmax);
1613 }
1614 fFourierHistos[0].dataFourierIm->GetYaxis()->SetRangeUser(1.05*ymin, 1.05*ymax);
1615 fFourierHistos[0].dataFourierIm->GetYaxis()->SetTitleOffset(1.3);
1616 fFourierHistos[0].dataFourierIm->GetYaxis()->SetDecimals(kTRUE);
1617 fFourierHistos[0].dataFourierIm->GetYaxis()->SetTitle("Imag");
1618 fFourierHistos[0].dataFourierIm->GetXaxis()->SetTitle(fXaxisTitle.Data());
1619 fFourierHistos[0].dataFourierIm->Draw("p");
1620 for (UInt_t i=1; i<fFourierHistos.size(); i++) {
1621 fFourierHistos[i].dataFourierIm->Draw("psame");
1622 }
1623 break;
1625 fFourierHistos[0].dataFourierRe->GetXaxis()->SetRangeUser(xmin, xmax);
1626 ymin = GetMinimum(fFourierHistos[0].dataFourierRe, xmin, xmax);
1627 ymax = GetMaximum(fFourierHistos[0].dataFourierRe, xmin, xmax);
1628 for (UInt_t i=1; i<fFourierHistos.size(); i++) {
1629 if (GetMaximum(fFourierHistos[i].dataFourierRe, xmin, xmax) > ymax)
1630 ymax = GetMaximum(fFourierHistos[i].dataFourierRe, xmin, xmax);
1631 if (GetMaximum(fFourierHistos[i].dataFourierIm, xmin, xmax) > ymax)
1632 ymax = GetMaximum(fFourierHistos[i].dataFourierIm, xmin, xmax);
1633 if (GetMinimum(fFourierHistos[i].dataFourierRe, xmin, xmax) < ymin)
1634 ymin = GetMinimum(fFourierHistos[i].dataFourierRe, xmin, xmax);
1635 if (GetMinimum(fFourierHistos[i].dataFourierIm, xmin, xmax) < ymin)
1636 ymin = GetMinimum(fFourierHistos[i].dataFourierIm, xmin, xmax);
1637 }
1638 fFourierHistos[0].dataFourierRe->GetYaxis()->SetRangeUser(1.05*ymin, 1.05*ymax);
1639 fFourierHistos[0].dataFourierRe->GetYaxis()->SetTitleOffset(1.3);
1640 fFourierHistos[0].dataFourierRe->GetYaxis()->SetDecimals(kTRUE);
1641 fFourierHistos[0].dataFourierRe->GetYaxis()->SetTitle("Real");
1642 fFourierHistos[0].dataFourierRe->GetXaxis()->SetTitle(fXaxisTitle.Data());
1643 fFourierHistos[0].dataFourierRe->Draw("p");
1644 for (UInt_t i=1; i<fFourierHistos.size(); i++) {
1645 fFourierHistos[i].dataFourierRe->Draw("psame");
1646 }
1647 for (UInt_t i=0; i<fFourierHistos.size(); i++) {
1648 fFourierHistos[i].dataFourierIm->Draw("psame");
1649 }
1650 break;
1651 case FOURIER_PLOT_POWER:
1652 // get maximum of Fourier data in the range
1653 fFourierHistos[0].dataFourierPwr->GetXaxis()->SetRangeUser(xmin, xmax);
1654 ymin = 0.0;
1655 ymax = GetMaximum(fFourierHistos[0].dataFourierPwr, xmin, xmax);
1656 for (UInt_t i=1; i<fFourierHistos.size(); i++) {
1657 if (GetMaximum(fFourierHistos[i].dataFourierPwr, xmin, xmax) > ymax)
1658 ymax = GetMaximum(fFourierHistos[i].dataFourierPwr, xmin, xmax);
1659 }
1660 fFourierHistos[0].dataFourierPwr->GetYaxis()->SetRangeUser(ymin, 1.03*ymax);
1661 fFourierHistos[0].dataFourierPwr->GetYaxis()->SetTitle("Power");
1662 fFourierHistos[0].dataFourierPwr->GetYaxis()->SetTitleOffset(1.3);
1663 fFourierHistos[0].dataFourierPwr->GetYaxis()->SetDecimals(kTRUE);
1664 fFourierHistos[0].dataFourierPwr->GetXaxis()->SetTitle(fXaxisTitle.Data());
1665 fFourierHistos[0].dataFourierPwr->Draw("p");
1666 for (UInt_t i=1; i<fFourierHistos.size(); i++) {
1667 fFourierHistos[i].dataFourierPwr->Draw("psame");
1668 }
1669 break;
1670 case FOURIER_PLOT_PHASE:
1671 fFourierHistos[0].dataFourierPhase->GetXaxis()->SetRangeUser(xmin, xmax);
1672 ymin = GetMinimum(fFourierHistos[0].dataFourierPhase, xmin, xmax);
1673 ymax = GetMaximum(fFourierHistos[0].dataFourierPhase, xmin, xmax);
1674 for (UInt_t i=1; i<fFourierHistos.size(); i++) {
1675 if (GetMaximum(fFourierHistos[i].dataFourierPhase, xmin, xmax) > ymax)
1676 ymax = GetMaximum(fFourierHistos[i].dataFourierPhase, xmin, xmax);
1677 if (GetMinimum(fFourierHistos[i].dataFourierPhase, xmin, xmax) < ymin)
1678 ymin = GetMinimum(fFourierHistos[i].dataFourierPhase, xmin, xmax);
1679 }
1680 fFourierHistos[0].dataFourierPhase->GetYaxis()->SetRangeUser(1.05*ymin, 1.05*ymax);
1681 fFourierHistos[0].dataFourierPhase->GetYaxis()->SetTitleOffset(1.3);
1682 fFourierHistos[0].dataFourierPhase->GetYaxis()->SetDecimals(kTRUE);
1683 fFourierHistos[0].dataFourierPhase->GetYaxis()->SetTitle("Phase");
1684 fFourierHistos[0].dataFourierPhase->GetXaxis()->SetTitle(fXaxisTitle.Data());
1685 fFourierHistos[0].dataFourierPhase->Draw("p");
1686 for (UInt_t i=1; i<fFourierHistos.size(); i++) {
1687 fFourierHistos[i].dataFourierPhase->Draw("psame");
1688 }
1689 break;
1691 fFourierHistos[0].dataFourierPhaseOptReal->GetXaxis()->SetRangeUser(xmin, xmax);
1692 ymin = GetMinimum(fFourierHistos[0].dataFourierPhaseOptReal, xmin, xmax);
1693 ymax = GetMaximum(fFourierHistos[0].dataFourierPhaseOptReal, xmin, xmax);
1694 for (UInt_t i=1; i<fFourierHistos.size(); i++) {
1695 if (GetMaximum(fFourierHistos[i].dataFourierPhaseOptReal, xmin, xmax) > ymax)
1696 ymax = GetMaximum(fFourierHistos[i].dataFourierPhaseOptReal, xmin, xmax);
1697 if (GetMinimum(fFourierHistos[i].dataFourierPhaseOptReal, xmin, xmax) < ymin)
1698 ymin = GetMinimum(fFourierHistos[i].dataFourierPhaseOptReal, xmin, xmax);
1699 }
1700 fFourierHistos[0].dataFourierPhaseOptReal->GetYaxis()->SetRangeUser(ymin, 1.05*ymax);
1701 fFourierHistos[0].dataFourierPhaseOptReal->GetYaxis()->SetTitleOffset(1.3);
1702 fFourierHistos[0].dataFourierPhaseOptReal->GetYaxis()->SetDecimals(kTRUE);
1703 fFourierHistos[0].dataFourierPhaseOptReal->GetYaxis()->SetTitle("Phase Opt. Real");
1704 fFourierHistos[0].dataFourierPhaseOptReal->GetXaxis()->SetTitle(fXaxisTitle.Data());
1705 fFourierHistos[0].dataFourierPhaseOptReal->Draw("p");
1706 for (UInt_t i=1; i<fFourierHistos.size(); i++) {
1707 fFourierHistos[i].dataFourierPhaseOptReal->Draw("psame");
1708 }
1709 break;
1710 default:
1711 break;
1712 }
1713
1714 fFourierPad->Update();
1715
1716 fMainCanvas->cd();
1717 fMainCanvas->Update();
1718}
1719
1720//--------------------------------------------------------------------------
1721// PlotFourierPhaseValue (private)
1722//--------------------------------------------------------------------------
1727{
1728 Double_t x, y;
1729 TString str;
1730
1731 // plot Fourier phase
1732 str = TString("phase = ");
1733 str += fCurrentFourierPhase;
1734 x = 0.7;
1735 y = 0.85;
1736 fCurrentFourierPhaseText.reset(new TLatex());
1737 fCurrentFourierPhaseText->SetNDC(kTRUE);
1738 fCurrentFourierPhaseText->SetText(x, y, str.Data());
1739 fCurrentFourierPhaseText->SetTextFont(62);
1740 fCurrentFourierPhaseText->SetTextSize(0.03);
1741
1742 fFourierPad->cd();
1743
1745
1746 fFourierPad->Update();
1747}
1748
1749//--------------------------------------------------------------------------
1750// PlotAverage (private)
1751//--------------------------------------------------------------------------
1756{
1757 fFourierPad->cd();
1758
1759 if (fFourierAverage.size() == 0) { // ups, HandleAverage never called!
1760 HandleAverage();
1761 }
1762
1763 Double_t xmin=0.0, xmax=0.0;
1764 xmin = fInitialXRange[0];
1765 xmax = fInitialXRange[1];
1766 Double_t ymin=0.0, ymax=0.0;
1767
1768 if (fLegAvgPerDataSet.get()) {
1769 fLegAvgPerDataSet->Clear();
1770 }
1771
1772 switch (fCurrentPlotView) {
1773 case FOURIER_PLOT_REAL:
1774 fFourierAverage[0].dataFourierRe->GetXaxis()->SetRangeUser(xmin, xmax);
1775 ymin = GetMinimum(fFourierAverage[0].dataFourierRe, xmin, xmax);
1776 ymax = GetMaximum(fFourierAverage[0].dataFourierRe, xmin, xmax);
1777 for (UInt_t i=1; i<fFourierAverage.size(); i++) {
1778 if (GetMaximum(fFourierAverage[i].dataFourierRe, xmin, xmax) > ymax)
1779 ymax = GetMaximum(fFourierAverage[i].dataFourierRe, xmin, xmax);
1780 if (GetMinimum(fFourierAverage[i].dataFourierRe, xmin, xmax) < ymin)
1781 ymin = GetMinimum(fFourierAverage[i].dataFourierRe, xmin, xmax);
1782 }
1783 fFourierAverage[0].dataFourierRe->GetYaxis()->SetRangeUser(1.03*ymin, 1.03*ymax);
1784 fFourierAverage[0].dataFourierRe->GetYaxis()->SetTitleOffset(1.3);
1785 fFourierAverage[0].dataFourierRe->GetYaxis()->SetDecimals(kTRUE);
1786 fFourierAverage[0].dataFourierRe->GetYaxis()->SetTitle("<Real>");
1787 fFourierAverage[0].dataFourierRe->GetXaxis()->SetTitle(fXaxisTitle.Data());
1788 fFourierAverage[0].dataFourierRe->GetXaxis()->SetRangeUser(xmin, xmax);
1789 fFourierAverage[0].dataFourierRe->Draw("p");
1790 break;
1791 case FOURIER_PLOT_IMAG:
1792 fFourierAverage[0].dataFourierIm->GetXaxis()->SetRangeUser(xmin, xmax);
1793 ymin = GetMinimum(fFourierAverage[0].dataFourierIm, xmin, xmax);
1794 ymax = GetMaximum(fFourierAverage[0].dataFourierIm, xmin, xmax);
1795 for (UInt_t i=1; i<fFourierAverage.size(); i++) {
1796 if (GetMaximum(fFourierAverage[i].dataFourierIm, xmin, xmax) > ymax)
1797 ymax = GetMaximum(fFourierAverage[i].dataFourierIm, xmin, xmax);
1798 if (GetMinimum(fFourierAverage[i].dataFourierIm, xmin, xmax) < ymin)
1799 ymin = GetMinimum(fFourierAverage[i].dataFourierIm, xmin, xmax);
1800 }
1801 fFourierAverage[0].dataFourierIm->GetYaxis()->SetRangeUser(1.03*ymin, 1.03*ymax);
1802 fFourierAverage[0].dataFourierIm->GetYaxis()->SetTitleOffset(1.3);
1803 fFourierAverage[0].dataFourierIm->GetYaxis()->SetDecimals(kTRUE);
1804 fFourierAverage[0].dataFourierIm->GetYaxis()->SetTitle("<Imag>");
1805 fFourierAverage[0].dataFourierIm->GetXaxis()->SetTitle(fXaxisTitle.Data());
1806 fFourierAverage[0].dataFourierIm->GetXaxis()->SetRangeUser(xmin, xmax);
1807 fFourierAverage[0].dataFourierIm->Draw("p");
1808 break;
1810 fFourierAverage[0].dataFourierRe->GetXaxis()->SetRangeUser(xmin, xmax);
1811 ymin = GetMinimum(fFourierAverage[0].dataFourierRe, xmin, xmax);
1812 ymax = GetMaximum(fFourierAverage[0].dataFourierRe, xmin, xmax);
1813 for (UInt_t i=1; i<fFourierAverage.size(); i++) {
1814 if (GetMaximum(fFourierAverage[i].dataFourierRe, xmin, xmax) > ymax)
1815 ymax = GetMaximum(fFourierAverage[i].dataFourierRe, xmin, xmax);
1816 if (GetMinimum(fFourierAverage[i].dataFourierRe, xmin, xmax) < ymin)
1817 ymin = GetMinimum(fFourierAverage[i].dataFourierRe, xmin, xmax);
1818 }
1819 fFourierAverage[0].dataFourierRe->GetYaxis()->SetRangeUser(1.03*ymin, 1.03*ymax);
1820 fFourierAverage[0].dataFourierRe->GetYaxis()->SetTitleOffset(1.3);
1821 fFourierAverage[0].dataFourierRe->GetYaxis()->SetDecimals(kTRUE);
1822 fFourierAverage[0].dataFourierRe->GetYaxis()->SetTitle("<Real+Imag>");
1823 fFourierAverage[0].dataFourierRe->GetXaxis()->SetTitle(fXaxisTitle.Data());
1824 fFourierAverage[0].dataFourierRe->GetXaxis()->SetRangeUser(xmin, xmax);
1825 fFourierAverage[0].dataFourierRe->Draw("p");
1826 fFourierAverage[0].dataFourierIm->Draw("psame");
1827 break;
1828 case FOURIER_PLOT_POWER:
1829 // get maximum of Fourier data in the range
1830 fFourierAverage[0].dataFourierPwr->GetXaxis()->SetRangeUser(xmin, xmax);
1831 ymin = 0.0;
1832 ymax = GetMaximum(fFourierAverage[0].dataFourierPwr, xmin, xmax);
1833 for (UInt_t i=1; i<fFourierAverage.size(); i++) {
1834 if (GetMaximum(fFourierAverage[i].dataFourierPwr, xmin, xmax) > ymax)
1835 ymax = GetMaximum(fFourierAverage[i].dataFourierPwr, xmin, xmax);
1836 }
1837 fFourierAverage[0].dataFourierPwr->GetYaxis()->SetRangeUser(ymin, 1.03*ymax);
1838 fFourierAverage[0].dataFourierPwr->GetYaxis()->SetTitleOffset(1.3);
1839 fFourierAverage[0].dataFourierPwr->GetYaxis()->SetDecimals(kTRUE);
1840 fFourierAverage[0].dataFourierPwr->GetYaxis()->SetTitle("<Power>");
1841 fFourierAverage[0].dataFourierPwr->GetXaxis()->SetTitle(fXaxisTitle.Data());
1842 fFourierAverage[0].dataFourierPwr->Draw("p");
1843 break;
1844 case FOURIER_PLOT_PHASE:
1845 fFourierAverage[0].dataFourierPhase->GetXaxis()->SetRangeUser(xmin, xmax);
1846 ymin = GetMinimum(fFourierAverage[0].dataFourierPhase, xmin, xmax);
1847 ymax = GetMaximum(fFourierAverage[0].dataFourierPhase, xmin, xmax);
1848 for (UInt_t i=1; i<fFourierAverage.size(); i++) {
1849 if (GetMaximum(fFourierAverage[i].dataFourierPhase, xmin, xmax) > ymax)
1850 ymax = GetMaximum(fFourierAverage[i].dataFourierPhase, xmin, xmax);
1851 if (GetMinimum(fFourierAverage[i].dataFourierPhase, xmin, xmax) < ymin)
1852 ymin = GetMinimum(fFourierAverage[i].dataFourierPhase, xmin, xmax);
1853 }
1854 fFourierAverage[0].dataFourierPhase->GetYaxis()->SetRangeUser(1.03*ymin, 1.03*ymax);
1855 fFourierAverage[0].dataFourierPhase->GetYaxis()->SetTitleOffset(1.3);
1856 fFourierAverage[0].dataFourierPhase->GetYaxis()->SetDecimals(kTRUE);
1857 fFourierAverage[0].dataFourierPhase->GetYaxis()->SetTitle("<Phase>");
1858 fFourierAverage[0].dataFourierPhase->GetXaxis()->SetTitle(fXaxisTitle.Data());
1859 fFourierAverage[0].dataFourierPhase->GetXaxis()->SetRangeUser(xmin, xmax);
1860 fFourierAverage[0].dataFourierPhase->Draw("p");
1861 break;
1863 if (fFourierHistos[0].dataFourierPhaseOptReal == nullptr) {
1864 std::cout << "debug> need to calculate phase opt. average first ..." << std::endl;
1866 HandleAverage();
1867 }
1868 fFourierAverage[0].dataFourierPhaseOptReal->GetXaxis()->SetRangeUser(xmin, xmax);
1869 ymin = GetMinimum(fFourierAverage[0].dataFourierPhaseOptReal, xmin, xmax);
1870 ymax = GetMaximum(fFourierAverage[0].dataFourierPhaseOptReal, xmin, xmax);
1871 for (UInt_t i=1; i<fFourierAverage.size(); i++) {
1872 if (GetMaximum(fFourierAverage[i].dataFourierPhaseOptReal, xmin, xmax) > ymax)
1873 ymax = GetMaximum(fFourierAverage[i].dataFourierPhaseOptReal, xmin, xmax);
1874 if (GetMinimum(fFourierAverage[i].dataFourierPhaseOptReal, xmin, xmax) < ymin)
1875 ymin = GetMinimum(fFourierAverage[i].dataFourierPhaseOptReal, xmin, xmax);
1876 }
1877 fFourierAverage[0].dataFourierPhaseOptReal->GetYaxis()->SetRangeUser(ymin, 1.03*ymax);
1878 fFourierAverage[0].dataFourierPhaseOptReal->GetYaxis()->SetTitleOffset(1.3);
1879 fFourierAverage[0].dataFourierPhaseOptReal->GetYaxis()->SetDecimals(kTRUE);
1880 fFourierAverage[0].dataFourierPhaseOptReal->GetYaxis()->SetTitle("<Phase Opt. Real>");
1881 fFourierAverage[0].dataFourierPhaseOptReal->GetXaxis()->SetTitle(fXaxisTitle.Data());
1882 fFourierAverage[0].dataFourierPhaseOptReal->GetXaxis()->SetRangeUser(xmin, xmax);
1883 fFourierAverage[0].dataFourierPhaseOptReal->Draw("p");
1884 break;
1885 default:
1886 break;
1887 }
1888
1889 if (fAveragedViewPerDataSet) { // plot all the rest
1890 fLegAvgPerDataSet = std::make_unique<TLegend>(0.55, 0.4, 0.85, 0.6);
1891 TString str = GetDataSetName(fFourierAverage[0].dataFourierPwr->GetTitle());
1892 TString label = TString::Format("<%s>", str.Data());
1893 fLegAvgPerDataSet->AddEntry(fFourierAverage[0].dataFourierPwr, label.Data());
1894 for (UInt_t i=1; i<fFourierAverage.size(); i++) {
1895 switch (fCurrentPlotView) {
1896 case FOURIER_PLOT_REAL:
1897 fFourierAverage[i].dataFourierRe->Draw("psame");
1898 break;
1899 case FOURIER_PLOT_IMAG:
1900 fFourierAverage[i].dataFourierIm->Draw("psame");
1901 break;
1903 fFourierAverage[i].dataFourierRe->Draw("psame");
1904 fFourierAverage[i].dataFourierIm->Draw("psame");
1905 break;
1906 case FOURIER_PLOT_POWER:
1907 fFourierAverage[i].dataFourierPwr->Draw("psame");
1908 break;
1909 case FOURIER_PLOT_PHASE:
1910 fFourierAverage[i].dataFourierPhase->Draw("psame");
1911 break;
1913 fFourierAverage[i].dataFourierPhaseOptReal->Draw("psame");
1914 break;
1915 default:
1916 break;
1917 }
1918 // add legend ?!?!
1919 str = GetDataSetName(fFourierAverage[i].dataFourierPwr->GetTitle());
1920 label = TString::Format("<%s>", str.Data());
1921 fLegAvgPerDataSet->AddEntry(fFourierAverage[i].dataFourierPwr, label.Data());
1922 }
1923 fLegAvgPerDataSet->Draw();
1924 }
1925
1926 fFourierPad->Update();
1927
1928 fMainCanvas->cd();
1929 fMainCanvas->Update();
1930}
1931
1932//--------------------------------------------------------------------------
1933// IncrementFourierPhase (private)
1934//--------------------------------------------------------------------------
1939{
1941 return;
1942
1943 Double_t re, im;
1944 Double_t inc = 1.0;
1945 const Double_t cp = TMath::Cos(inc/180.0*TMath::Pi());
1946 const Double_t sp = TMath::Sin(inc/180.0*TMath::Pi());
1947
1948 fCurrentFourierPhase += inc;
1950
1951 for (UInt_t i=0; i<fFourierHistos.size(); i++) { // loop over all data sets
1952 if ((fFourierHistos[i].dataFourierRe != nullptr) && (fFourierHistos[i].dataFourierIm != nullptr)) {
1953 for (Int_t j=0; j<fFourierHistos[i].dataFourierRe->GetNbinsX(); j++) { // loop over a fourier data set
1954 // calculate new fourier data set value
1955 re = fFourierHistos[i].dataFourierRe->GetBinContent(j) * cp + fFourierHistos[i].dataFourierIm->GetBinContent(j) * sp;
1956 im = fFourierHistos[i].dataFourierIm->GetBinContent(j) * cp - fFourierHistos[i].dataFourierRe->GetBinContent(j) * sp;
1957 // overwrite fourier data set value
1958 fFourierHistos[i].dataFourierRe->SetBinContent(j, re);
1959 fFourierHistos[i].dataFourierIm->SetBinContent(j, im);
1960 }
1961 }
1962 }
1963}
1964
1965//--------------------------------------------------------------------------
1966// DecrementFourierPhase (private)
1967//--------------------------------------------------------------------------
1972{
1974 return;
1975
1976 Double_t re, im;
1977 Double_t inc = 1.0;
1978 const Double_t cp = TMath::Cos(inc/180.0*TMath::Pi());
1979 const Double_t sp = TMath::Sin(inc/180.0*TMath::Pi());
1980
1981 fCurrentFourierPhase -= inc;
1983
1984 for (UInt_t i=0; i<fFourierHistos.size(); i++) { // loop over all data sets
1985 if ((fFourierHistos[i].dataFourierRe != nullptr) && (fFourierHistos[i].dataFourierIm != nullptr)) {
1986 for (Int_t j=0; j<fFourierHistos[i].dataFourierRe->GetNbinsX(); j++) { // loop over a fourier data set
1987 // calculate new fourier data set value
1988 re = fFourierHistos[i].dataFourierRe->GetBinContent(j) * cp - fFourierHistos[i].dataFourierIm->GetBinContent(j) * sp;
1989 im = fFourierHistos[i].dataFourierIm->GetBinContent(j) * cp + fFourierHistos[i].dataFourierRe->GetBinContent(j) * sp;
1990 // overwrite fourier data set value
1991 fFourierHistos[i].dataFourierRe->SetBinContent(j, re);
1992 fFourierHistos[i].dataFourierIm->SetBinContent(j, im);
1993 }
1994 }
1995 }
1996}
1997
1998//--------------------------------------------------------------------------
1999// GetMaximum (private)
2000//--------------------------------------------------------------------------
2012Double_t PFourierCanvas::GetMaximum(TH1F* histo, Double_t xmin, Double_t xmax)
2013{
2014 if (histo == nullptr)
2015 return 0.0;
2016
2017 Int_t start=0, end=0;
2018 if (xmin == xmax) {
2019 start = 1;
2020 end = histo->GetNbinsX();
2021 } else {
2022 start = histo->FindBin(xmin);
2023 if ((start==0) || (start==histo->GetNbinsX()+1)) // underflow/overflow
2024 start = 1;
2025 end = histo->FindBin(xmax);
2026 if ((end==0) || (end==histo->GetNbinsX()+1)) // underflow/overflow
2027 end = histo->GetNbinsX();
2028 }
2029
2030 Double_t max = histo->GetBinContent(start);
2031 Double_t binContent;
2032 for (Int_t i=start; i<end; i++) {
2033 binContent = histo->GetBinContent(i);
2034 if (max < binContent)
2035 max = binContent;
2036 }
2037
2038 return max;
2039}
2040
2041//--------------------------------------------------------------------------
2042// GetMinimum (private)
2043//--------------------------------------------------------------------------
2055Double_t PFourierCanvas::GetMinimum(TH1F* histo, Double_t xmin, Double_t xmax)
2056{
2057 if (histo == nullptr)
2058 return 0.0;
2059
2060 Int_t start=0, end=0;
2061 if (xmin == xmax) {
2062 start = 1;
2063 end = histo->GetNbinsX();
2064 } else {
2065 start = histo->FindBin(xmin);
2066 if ((start==0) || (start==histo->GetNbinsX()+1)) // underflow/overflow
2067 start = 1;
2068 end = histo->FindBin(xmax);
2069 if ((end==0) || (end==histo->GetNbinsX()+1)) // underflow/overflow
2070 end = histo->GetNbinsX();
2071 }
2072
2073 Double_t min = histo->GetBinContent(start);
2074 Double_t binContent;
2075 for (Int_t i=start; i<end; i++) {
2076 binContent = histo->GetBinContent(i);
2077 if (min > binContent)
2078 min = binContent;
2079 }
2080
2081 return min;
2082}
2083
2084//--------------------------------------------------------------------------
2085// GetInterpolatedValue (private)
2086//--------------------------------------------------------------------------
2097Double_t PFourierCanvas::GetInterpolatedValue(TH1F* histo, Double_t xVal)
2098{
2099 if (histo == nullptr)
2100 return 0.0;
2101
2102 Int_t idx = histo->FindBin(xVal);
2103
2104 // make sure idx is within range
2105 if ((idx < 1) || (idx > histo->GetNbinsX()))
2106 return 0.0;
2107
2108 // make sure the lower bound idx is found. This is needed since
2109 // FindBin rounds towards the closer idx.
2110 if (histo->GetBinCenter(idx) > xVal)
2111 --idx;
2112
2113 Double_t x0, x1, y0, y1;
2114 x0 = histo->GetBinCenter(idx);
2115 x1 = histo->GetBinCenter(idx+1);
2116 y0 = histo->GetBinContent(idx);
2117 y1 = histo->GetBinContent(idx+1);
2118
2119 return (y1-y0)*(xVal-x0)/(x1-x0)+y0;
2120}
2121
2122//--------------------------------------------------------------------------
2123// GetDataSetName (private)
2124//--------------------------------------------------------------------------
2134{
2135 TString str(title);
2136
2137 Ssiz_t idx = str.First(':');
2138 str.Remove(0, idx+1);
2139 idx = str.First(',');
2140 str.Remove(idx);
2141
2142 return str;
2143}
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:290
#define FOURIER_PLOT_REAL_AND_IMAG
Plot both real and imaginary components (default)
Definition PMusr.h:328
#define FOURIER_UNIT_GAUSS
Magnetic field in Gauss (G)
Definition PMusr.h:286
#define FOURIER_PLOT_NOT_GIVEN
Plot type not specified.
Definition PMusr.h:322
#define FOURIER_PLOT_POWER
Plot power spectrum |F(ω)|²
Definition PMusr.h:330
#define FOURIER_PLOT_REAL
Plot real component only.
Definition PMusr.h:324
#define FOURIER_PLOT_PHASE_OPT_REAL
Plot phase-optimized real component.
Definition PMusr.h:334
#define FOURIER_UNIT_CYCLES
Angular frequency in Mc/s (Mega-cycles per second)
Definition PMusr.h:292
std::vector< Int_t > PIntVector
Definition PMusr.h:381
#define FOURIER_PLOT_IMAG
Plot imaginary component only.
Definition PMusr.h:326
#define FOURIER_PLOT_PHASE
Plot phase spectrum arg(F(ω))
Definition PMusr.h:332
#define FOURIER_UNIT_TESLA
Magnetic field in Tesla (T)
Definition PMusr.h:288
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:72