musrfit 1.12.1
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 "PFourier.h"
41#include "PFourierCanvas.h"
42
43#include "icons/musrFT_icon.xpm"
44#ifdef __APPLE__
45#include "PMacDockIcon.h"
46#include "icons/musrFT_icon_png.h"
47#endif
48
49#define YINFO 0.2
50#define YTITLE 0.95
51
52static const Char_t *gFiletypes[] = { "Data files", "*.dat",
53 "All files", "*",
54 nullptr, nullptr };
55
57
58//---------------------------------------------------------------------------
76{
77 fTimeout = 0;
78
79 fBatchMode = false;
80 fValid = false;
81 fAveragedView = false;
84 fInitialXRange[0] = 0.0;
85 fInitialXRange[1] = 0.0;
86
87 fTitle = TString("");
88 fXaxisTitle = TString("");
89
91
92 fImp = nullptr;
93 fBar = nullptr;
94 fPopupMain = nullptr;
95}
96
97//---------------------------------------------------------------------------
133PFourierCanvas::PFourierCanvas(std::vector<PFourier*> &fourier, PIntVector dataSetTag, const Char_t* title,
134 const Bool_t showAverage, const Bool_t showAveragePerDataSet,
135 const Int_t fourierPlotOpt, Double_t fourierXrange[], Double_t phase,
136 Int_t wtopx, Int_t wtopy, Int_t ww, Int_t wh,
137 const Bool_t batch) :
138 fBatchMode(batch), fAveragedView(showAverage), fAveragedViewPerDataSet(showAveragePerDataSet),
139 fDataSetTag(dataSetTag), fCurrentPlotView(fourierPlotOpt), fTitle(title), fFourier(fourier),
140 fCurrentFourierPhase(phase)
141{
142 fInitialXRange[0] = fourierXrange[0];
143 fInitialXRange[1] = fourierXrange[1];
144
145 fTimeout = 0;
146
147 fValid = false;
148
149 // generate fMarkerList and fColorList, since they are not provided
150 TRandom rand;
151 Int_t style, color;
152 for (UInt_t i=0; i<fourier.size(); i++) {
153 rand.SetSeed(i);
154 style = 20+static_cast<Int_t>(rand.Integer(10));
155 fMarkerList.push_back(style);
156 // the rgb values need to be drawn into separate variables first: the evaluation order of
157 // function arguments is unspecified in C++, hence calling rand.Integer() three times within
158 // the argument list would yield compiler dependent (r,g,b) permutations.
159 Int_t r = static_cast<Int_t>(rand.Integer(255));
160 Int_t g = static_cast<Int_t>(rand.Integer(255));
161 Int_t b = static_cast<Int_t>(rand.Integer(255));
162 color = TColor::GetColor(r, g, b);
163 fColorList.push_back(color);
164 }
165
166 CreateXaxisTitle();
167 CreateStyle();
168 InitFourierDataSets();
169 InitFourierCanvas(fTitle, wtopx, wtopy, ww, wh);
170
171 gStyle->SetHistMinimumZero(kTRUE); // needed to enforce proper bar option handling
172}
173
174//---------------------------------------------------------------------------
216PFourierCanvas::PFourierCanvas(std::vector<PFourier*> &fourier, PIntVector dataSetTag, const Char_t* title,
217 const Bool_t showAverage, const Bool_t showAveragePerDataSet,
218 const Int_t fourierPlotOpt, Double_t fourierXrange[], Double_t phase,
219 Int_t wtopx, Int_t wtopy, Int_t ww, Int_t wh,
220 const PIntVector markerList, const PIntVector colorList, const Bool_t batch) :
221 fBatchMode(batch), fAveragedView(showAverage), fAveragedViewPerDataSet(showAveragePerDataSet),
222 fDataSetTag(dataSetTag), fCurrentPlotView(fourierPlotOpt), fTitle(title), fFourier(fourier),
223 fCurrentFourierPhase(phase), fMarkerList(markerList), fColorList(colorList)
224{
225 fInitialXRange[0] = fourierXrange[0];
226 fInitialXRange[1] = fourierXrange[1];
227
228 fTimeout = 0;
229
230 fValid = false;
231
232 // generate fMarkerList and fColorList, since they are not provided
233 TRandom rand;
234 Int_t style, color;
235 for (UInt_t i=static_cast<UInt_t>(fMarkerList.size()); i<fourier.size(); i++) {
236 rand.SetSeed(i);
237 style = 20+static_cast<Int_t>(rand.Integer(10));
238 fMarkerList.push_back(style);
239 }
240 for (UInt_t i=static_cast<UInt_t>(fColorList.size()); i<fourier.size(); i++) {
241 rand.SetSeed(i);
242 // the rgb values need to be drawn into separate variables first: the evaluation order of
243 // function arguments is unspecified in C++, hence calling rand.Integer() three times within
244 // the argument list would yield compiler dependent (r,g,b) permutations.
245 Int_t r = static_cast<Int_t>(rand.Integer(255));
246 Int_t g = static_cast<Int_t>(rand.Integer(255));
247 Int_t b = static_cast<Int_t>(rand.Integer(255));
248 color = TColor::GetColor(r, g, b);
249 fColorList.push_back(color);
250 }
251
252 CreateXaxisTitle();
253 CreateStyle();
254 InitFourierDataSets();
255 InitFourierCanvas(fTitle, wtopx, wtopy, ww, wh);
256
257 gStyle->SetHistMinimumZero(kTRUE); // needed to enforce proper bar option handling
258}
259
260//--------------------------------------------------------------------------
261// Done (SIGNAL)
262//--------------------------------------------------------------------------
285{
286 Emit("Done(Int_t)", status);
287}
288
289//--------------------------------------------------------------------------
290// HandleCmdKey (SLOT)
291//--------------------------------------------------------------------------
325void PFourierCanvas::HandleCmdKey(Int_t event, Int_t x, Int_t y, TObject *selected)
326{
327 if (event != kKeyPress)
328 return;
329
330 if (fBatchMode)
331 return;
332
333 if (x == 'q') { // quit
334 Done(0);
335 } else if (x == 'u') { // unzoom
337 PlotAverage();
338 else
339 PlotFourier();
340 } else if (x == 'a') { // toggle between average view and single histo view
341 // toggle average view flag
343 // unset average per data set view flag
345 // update menu
346 if (fAveragedView) {
347 fPopupMain->CheckEntry(P_MENU_ID_AVERAGE);
350 PlotAverage();
351 } else {
352 fPopupMain->UnCheckEntry(P_MENU_ID_AVERAGE);
355 PlotFourier();
356 }
357 } else if (x == 'd') { // toggle between average view per data set and single histo view
358 // toggle average per data set view flag
360 // unset average view flag
361 fAveragedView = false;
362 // update menu
365 fPopupMain->UnCheckEntry(P_MENU_ID_AVERAGE);
367 PlotAverage();
368 } else {
370 fPopupMain->UnCheckEntry(P_MENU_ID_AVERAGE);
372 PlotFourier();
373 }
374 } else if (x == 'c') {
375 Int_t state = fFourierPad->GetCrosshair();
376 if (state == 0) {
377 fMainCanvas->ToggleEventStatus();
378 fFourierPad->SetCrosshair(2);
379 } else {
380 fMainCanvas->ToggleEventStatus();
381 fFourierPad->SetCrosshair(0);
382 }
383 fMainCanvas->Update();
384 } else if (x == '+') { // increment phase (Fourier real/imag)
386 } else if (x == '-') { // decrement phase (Fourier real/imag)
388 }
389}
390
391//--------------------------------------------------------------------------
392// HandleMenuPopup (SLOT)
393//--------------------------------------------------------------------------
424{
425 if (fBatchMode)
426 return;
427
429 // uncheck fourier popup items
430 fPopupFourier->UnCheckEntries();
433 if (!fAveragedView) {
434 PlotFourier();
435 } else {
437 PlotAverage();
438 }
439 } else if (id == P_MENU_ID_FOURIER+P_MENU_ID_FOURIER_IMAG) {
440 fPopupFourier->UnCheckEntries();
443 if (!fAveragedView) {
444 PlotFourier();
445 } else {
447 PlotAverage();
448 }
450 fPopupFourier->UnCheckEntries();
453 if (!fAveragedView) {
454 PlotFourier();
455 } else {
457 PlotAverage();
458 }
459 } else if (id == P_MENU_ID_FOURIER+P_MENU_ID_FOURIER_PWR) {
460 fPopupFourier->UnCheckEntries();
463 if (!fAveragedView) {
464 PlotFourier();
465 } else {
467 PlotAverage();
468 }
470 fPopupFourier->UnCheckEntries();
473 if (!fAveragedView) {
474 PlotFourier();
475 } else {
477 PlotAverage();
478 }
480 fPopupFourier->UnCheckEntries();
483 if (!fAveragedView) {
484 PlotFourier();
485 } else {
487 PlotAverage();
488 }
493 } else if (id == P_MENU_ID_AVERAGE) {
494 // toggle average view flag
496 // unset average per data set view flag
498 // update menu
499 if (fAveragedView) {
500 fPopupMain->CheckEntry(P_MENU_ID_AVERAGE);
503 PlotAverage();
504 } else {
505 fPopupMain->UnCheckEntry(P_MENU_ID_AVERAGE);
508 PlotFourier();
509 }
510 } else if (id == P_MENU_ID_AVERAGE_PER_DATA_SET) {
511 // toggle average per data set view flag
513 // unset average view flag
514 fAveragedView = false;
515 // update menu
518 fPopupMain->UnCheckEntry(P_MENU_ID_AVERAGE);
520 PlotAverage();
521 } else {
523 fPopupMain->UnCheckEntry(P_MENU_ID_AVERAGE);
525 PlotFourier();
526 }
527 } else if (id == P_MENU_ID_EXPORT_DATA) {
528 static TString dir(".");
529 TGFileInfo fi;
530 fi.fFileTypes = gFiletypes;
531 fi.fIniDir = StrDup(dir);
532 fi.fOverwrite = true;
533 new TGFileDialog(nullptr, fImp, kFDSave, &fi);
534 if (fi.fFilename && strlen(fi.fFilename)) {
535 ExportData(fi.fFilename);
536 }
537 }
538}
539
540//--------------------------------------------------------------------------
541// LastCanvasClosed (SLOT)
542//--------------------------------------------------------------------------
548{
549 if (gROOT->GetListOfCanvases()->IsEmpty()) {
550 Done(0);
551 }
552}
553
554//--------------------------------------------------------------------------
555// UpdateFourierPad (public)
556//--------------------------------------------------------------------------
561{
562 if (!fValid)
563 return;
564
566 PlotAverage();
567 else
568 PlotFourier();
569
570 fFourierPad->Draw();
571 fMainCanvas->cd();
572 fMainCanvas->Update();
573}
574
575//--------------------------------------------------------------------------
576// UpdateInfoPad (public)
577//--------------------------------------------------------------------------
582{
583 if (!fValid)
584 return;
585
586 // write header line
587 TDatime dt;
588 Char_t dtStr[128];
589 strncpy(dtStr, dt.AsSQLString(), sizeof(dtStr));
590 TString str("musrFT: ");
591 str += dtStr;
592 fInfoPad->SetHeader(str);
593
594 Char_t title[1024];
595 for (UInt_t i=0; i<fFourier.size(); i++) {
596 strncpy(title, fFourier[i]->GetDataTitle(), sizeof(title));
597 // add entry
598 fInfoPad->AddEntry(fFourierHistos[i].dataFourierRe, title, "p");
599 }
600
601 fInfoPad->Draw();
602 fMainCanvas->cd();
603 fMainCanvas->Update();
604}
605
606//--------------------------------------------------------------------------
607// SetTimeout (public)
608//--------------------------------------------------------------------------
632{
634
635 if (fTimeout <= 0)
636 return;
637
638 fTimeoutTimer.reset(new TTimer());
639
640 fTimeoutTimer->Connect("Timeout()", "PFourierCanvas", this, "Done()");
641
642 fTimeoutTimer->Start(1000*fTimeout, kTRUE);
643}
644
645//--------------------------------------------------------------------------
646// SaveGraphicsAndQuit
647//--------------------------------------------------------------------------
676void PFourierCanvas::SaveGraphicsAndQuit(const Char_t *fileName)
677{
678 std::cout << std::endl << ">> SaveGraphicsAndQuit: will dump the canvas into a graphics output file: " << fileName << " ..." << std::endl;
679
680 fMainCanvas->SaveAs(fileName);
681
682 Done(0);
683}
684
685//--------------------------------------------------------------------------
686// ExportData
687//--------------------------------------------------------------------------
728void PFourierCanvas::ExportData(const Char_t *pathFileName)
729{
730 TString pfn("");
731
732 if (pathFileName) { // path file name provided
733 pfn = TString(pathFileName);
734 } else { // path file name NOT provided, generate a default path file name
735 std::cerr << std::endl << ">> PFourierCanvas::ExportData **ERROR** NO path file name provided. Will do nothing." << std::endl;
736 return;
737 }
738
739 TString xAxis(""), yAxis("");
740 Int_t xMinBin, xMaxBin;
741 if (fAveragedView) {
742 switch (fCurrentPlotView) {
744 xAxis = fFourierHistos[0].dataFourierRe->GetXaxis()->GetTitle();
745 yAxis = TString("<Real>");
746 xMinBin = fFourierHistos[0].dataFourierRe->GetXaxis()->GetFirst();
747 xMaxBin = fFourierHistos[0].dataFourierRe->GetXaxis()->GetLast();
748 break;
750 xAxis = fFourierHistos[0].dataFourierIm->GetXaxis()->GetTitle();
751 yAxis = TString("<Imag>");
752 xMinBin = fFourierHistos[0].dataFourierIm->GetXaxis()->GetFirst();
753 xMaxBin = fFourierHistos[0].dataFourierIm->GetXaxis()->GetLast();
754 break;
756 xAxis = fFourierHistos[0].dataFourierPwr->GetXaxis()->GetTitle();
757 yAxis = TString("<Power>");
758 xMinBin = fFourierHistos[0].dataFourierPwr->GetXaxis()->GetFirst();
759 xMaxBin = fFourierHistos[0].dataFourierPwr->GetXaxis()->GetLast();
760 break;
762 xAxis = fFourierHistos[0].dataFourierPhase->GetXaxis()->GetTitle();
763 yAxis = TString("<Phase>");
764 xMinBin = fFourierHistos[0].dataFourierPhase->GetXaxis()->GetFirst();
765 xMaxBin = fFourierHistos[0].dataFourierPhase->GetXaxis()->GetLast();
766 break;
768 xAxis = fFourierHistos[0].dataFourierPhaseOptReal->GetXaxis()->GetTitle();
769 yAxis = TString("<Phase>");
770 xMinBin = fFourierHistos[0].dataFourierPhaseOptReal->GetXaxis()->GetFirst();
771 xMaxBin = fFourierHistos[0].dataFourierPhaseOptReal->GetXaxis()->GetLast();
772 break;
773 default:
774 xAxis = TString("??");
775 yAxis = TString("??");
776 xMinBin = 0;
777 xMaxBin = 0;
778 break;
779 }
780 } else {
781 switch (fCurrentPlotView) {
783 xAxis = fFourierHistos[0].dataFourierRe->GetXaxis()->GetTitle();
784 yAxis = TString("Real");
785 xMinBin = fFourierHistos[0].dataFourierRe->GetXaxis()->GetFirst();
786 xMaxBin = fFourierHistos[0].dataFourierRe->GetXaxis()->GetLast();
787 break;
789 xAxis = fFourierHistos[0].dataFourierIm->GetXaxis()->GetTitle();
790 yAxis = TString("Imag");
791 xMinBin = fFourierHistos[0].dataFourierIm->GetXaxis()->GetFirst();
792 xMaxBin = fFourierHistos[0].dataFourierIm->GetXaxis()->GetLast();
793 break;
795 xAxis = fFourierHistos[0].dataFourierRe->GetXaxis()->GetTitle();
796 yAxis = TString("Real+Imag");
797 xMinBin = fFourierHistos[0].dataFourierRe->GetXaxis()->GetFirst();
798 xMaxBin = fFourierHistos[0].dataFourierRe->GetXaxis()->GetLast();
799 break;
801 xAxis = fFourierHistos[0].dataFourierPwr->GetXaxis()->GetTitle();
802 yAxis = TString("Power");
803 xMinBin = fFourierHistos[0].dataFourierPwr->GetXaxis()->GetFirst();
804 xMaxBin = fFourierHistos[0].dataFourierPwr->GetXaxis()->GetLast();
805 break;
807 xAxis = fFourierHistos[0].dataFourierPhase->GetXaxis()->GetTitle();
808 yAxis = TString("Phase");
809 xMinBin = fFourierHistos[0].dataFourierPhase->GetXaxis()->GetFirst();
810 xMaxBin = fFourierHistos[0].dataFourierPhase->GetXaxis()->GetLast();
811 break;
813 xAxis = fFourierHistos[0].dataFourierPhaseOptReal->GetXaxis()->GetTitle();
814 yAxis = TString("Phase");
815 xMinBin = fFourierHistos[0].dataFourierPhaseOptReal->GetXaxis()->GetFirst();
816 xMaxBin = fFourierHistos[0].dataFourierPhaseOptReal->GetXaxis()->GetLast();
817 break;
818 default:
819 xAxis = TString("??");
820 yAxis = TString("??");
821 xMinBin = 0;
822 xMaxBin = 0;
823 break;
824 }
825 }
826
827 // write data to file
828 std::ofstream fout(pfn.Data(), std::ofstream::out);
829
830 if (fAveragedView) {
831 // write header
832 fout << "% " << pfn << std::endl;
833 fout << "% averaged data of:" << std::endl;
834 for (UInt_t i=0; i<fFourierHistos.size(); i++) {
835 fout << "% " << fFourierHistos[i].dataFourierRe->GetTitle() << std::endl;
836 }
837 fout << "%------------" << std::endl;
838 fout << "% " << xAxis << ", " << yAxis << std::endl;
839 for (Int_t i=xMinBin; i<xMaxBin; i++) {
840 switch (fCurrentPlotView) {
842 fout << fFourierAverage[0].dataFourierRe->GetBinCenter(i) << ", " << fFourierAverage[0].dataFourierRe->GetBinContent(i) << std::endl;
843 break;
845 fout << fFourierAverage[0].dataFourierIm->GetBinCenter(i) << ", " << fFourierAverage[0].dataFourierIm->GetBinContent(i) << std::endl;
846 break;
848 fout << fFourierAverage[0].dataFourierPwr->GetBinCenter(i) << ", " << fFourierAverage[0].dataFourierPwr->GetBinContent(i) << std::endl;
849 break;
851 fout << fFourierAverage[0].dataFourierPhase->GetBinCenter(i) << ", " << fFourierAverage[0].dataFourierPhase->GetBinContent(i) << std::endl;
852 break;
854 fout << fFourierAverage[0].dataFourierPhaseOptReal->GetBinCenter(i) << ", " << fFourierAverage[0].dataFourierPhaseOptReal->GetBinContent(i) << std::endl;
855 break;
856 default:
857 break;
858 }
859 }
860 } else {
861 // write header
862 fout << "% " << pfn << std::endl;
863 fout << "% data of:" << std::endl;
864 for (UInt_t i=0; i<fFourierHistos.size(); i++) {
865 fout << "% " << fFourierHistos[i].dataFourierRe->GetTitle() << std::endl;
866 }
867 fout << "%------------" << std::endl;
868 fout << "% ";
869 for (UInt_t i=0; i<fFourierHistos.size()-1; i++) {
870 fout << xAxis << i << ", " << yAxis << i << ", ";
871 }
872 fout << xAxis << fFourierHistos.size()-1 << ", " << yAxis << fFourierHistos.size()-1 << std::endl;
873
874 // write data
875 for (Int_t i=xMinBin; i<xMaxBin; i++) {
876 for (UInt_t j=0; j<fFourierHistos.size()-1; j++) {
877 switch (fCurrentPlotView) {
879 fout << fFourierHistos[j].dataFourierRe->GetBinCenter(i) << ", " << fFourierHistos[j].dataFourierRe->GetBinContent(i) << ", ";
880 break;
882 fout << fFourierHistos[j].dataFourierIm->GetBinCenter(i) << ", " << fFourierHistos[j].dataFourierIm->GetBinContent(i) << ", ";
883 break;
885 break;
887 fout << fFourierHistos[j].dataFourierPwr->GetBinCenter(i) << ", " << fFourierHistos[j].dataFourierPwr->GetBinContent(i) << ", ";
888 break;
890 fout << fFourierHistos[j].dataFourierPhase->GetBinCenter(i) << ", " << fFourierHistos[j].dataFourierPhase->GetBinContent(i) << ", ";
891 break;
893 fout << fFourierHistos[j].dataFourierPhaseOptReal->GetBinCenter(i) << ", " << fFourierHistos[j].dataFourierPhaseOptReal->GetBinContent(i) << ", ";
894 break;
895 default:
896 break;
897 }
898 }
899 switch (fCurrentPlotView) {
901 fout << fFourierHistos[fFourierHistos.size()-1].dataFourierRe->GetBinCenter(i) << ", " << fFourierHistos[fFourierHistos.size()-1].dataFourierRe->GetBinContent(i) << std::endl;
902 break;
904 fout << fFourierHistos[fFourierHistos.size()-1].dataFourierIm->GetBinCenter(i) << ", " << fFourierHistos[fFourierHistos.size()-1].dataFourierIm->GetBinContent(i) << std::endl;
905 break;
907 break;
909 fout << fFourierHistos[fFourierHistos.size()-1].dataFourierPwr->GetBinCenter(i) << ", " << fFourierHistos[fFourierHistos.size()-1].dataFourierPwr->GetBinContent(i) << std::endl;
910 break;
912 fout << fFourierHistos[fFourierHistos.size()-1].dataFourierPhase->GetBinCenter(i) << ", " << fFourierHistos[fFourierHistos.size()-1].dataFourierPhase->GetBinContent(i) << std::endl;
913 break;
915 fout << fFourierHistos[fFourierHistos.size()-1].dataFourierPhaseOptReal->GetBinCenter(i) << ", " << fFourierHistos[fFourierHistos.size()-1].dataFourierPhaseOptReal->GetBinContent(i) << std::endl;
916 break;
917 default:
918 break;
919 }
920 }
921 }
922
923 fout.close();
924}
925
926//--------------------------------------------------------------------------
927// CreateXaxisTitle (private)
928//--------------------------------------------------------------------------
933{
934 switch (fFourier[0]->GetUnitTag()) {
936 fXaxisTitle = TString("Field (Gauss)");
937 break;
939 fXaxisTitle = TString("Field (Tesla)");
940 break;
942 fXaxisTitle = TString("Frequency (MHz)");
943 break;
945 fXaxisTitle = TString("Angular Frequency (Mc/s)");
946 break;
947 default:
948 fXaxisTitle = TString("??");
949 break;
950 }
951}
952
953//--------------------------------------------------------------------------
954// CreateStyle (private)
955//--------------------------------------------------------------------------
960{
961 TString musrFTStyle("musrFTStyle");
962 fStyle = std::make_unique<TStyle>(musrFTStyle, musrFTStyle);
963 fStyle->SetOptStat(0); // no statistics options
964 fStyle->SetOptTitle(0); // no title
965 fStyle->cd();
966}
967
968//--------------------------------------------------------------------------
969// InitFourierDataSets (private)
970//--------------------------------------------------------------------------
976{
977 // get all the Fourier histos
978 fFourierHistos.resize(fFourier.size());
979 for (UInt_t i=0; i<fFourierHistos.size(); i++) {
980 fFourierHistos[i].dataFourierRe = fFourier[i]->GetRealFourier();
981 fFourierHistos[i].dataFourierIm = fFourier[i]->GetImaginaryFourier();
982 fFourierHistos[i].dataFourierPwr = fFourier[i]->GetPowerFourier();
983 fFourierHistos[i].dataFourierPhase = fFourier[i]->GetPhaseFourier();
985 fFourierHistos[i].dataFourierPhaseOptReal = fFourier[i]->GetPhaseOptRealFourier(fFourierHistos[i].dataFourierRe,
986 fFourierHistos[i].dataFourierIm, fFourierHistos[i].optPhase, 1.0, fInitialXRange[0], fInitialXRange[1]);
987 }
988 }
989
990 // rescale histo to abs(maximum) == 1
991 Double_t max = 0.0, dval = 0.0;
992 Int_t start = fFourierHistos[0].dataFourierRe->FindBin(fInitialXRange[0]);
993 Int_t end = fFourierHistos[0].dataFourierRe->FindBin(fInitialXRange[1]);
994 // real
995 for (UInt_t i=0; i<fFourierHistos.size(); i++) {
996 for (Int_t j=start; j<=end; j++) {
997 dval = fFourierHistos[i].dataFourierRe->GetBinContent(j);
998 if (fabs(dval) > max)
999 max = dval;
1000 }
1001 }
1002 for (UInt_t i=0; i<fFourierHistos.size(); i++) {
1003 for (Int_t j=1; j<fFourierHistos[i].dataFourierRe->GetNbinsX(); j++) {
1004 fFourierHistos[i].dataFourierRe->SetBinContent(j, fFourierHistos[i].dataFourierRe->GetBinContent(j)/fabs(max));
1005 }
1006 }
1007
1008 // imaginary
1009 for (UInt_t i=0; i<fFourierHistos.size(); i++) {
1010 for (Int_t j=start; j<=end; j++) {
1011 dval = fFourierHistos[i].dataFourierIm->GetBinContent(j);
1012 if (fabs(dval) > max)
1013 max = dval;
1014 }
1015 }
1016 for (UInt_t i=0; i<fFourierHistos.size(); i++) {
1017 for (Int_t j=1; j<fFourierHistos[i].dataFourierIm->GetNbinsX(); j++) {
1018 fFourierHistos[i].dataFourierIm->SetBinContent(j, fFourierHistos[i].dataFourierIm->GetBinContent(j)/fabs(max));
1019 }
1020 }
1021
1022 // power
1023 max = 0.0;
1024 for (UInt_t i=0; i<fFourierHistos.size(); i++) {
1025 for (Int_t j=start; j<=end; j++) {
1026 dval = fFourierHistos[i].dataFourierPwr->GetBinContent(j);
1027 if (fabs(dval) > max)
1028 max = dval;
1029 }
1030 }
1031 for (UInt_t i=0; i<fFourierHistos.size(); i++) {
1032 for (Int_t j=1; j<fFourierHistos[i].dataFourierPwr->GetNbinsX(); j++) {
1033 fFourierHistos[i].dataFourierPwr->SetBinContent(j, fFourierHistos[i].dataFourierPwr->GetBinContent(j)/fabs(max));
1034 }
1035 }
1036
1037 // phase
1038 max = 0.0;
1039 for (UInt_t i=0; i<fFourierHistos.size(); i++) {
1040 for (Int_t j=start; j<=end; j++) {
1041 dval = fFourierHistos[i].dataFourierPhase->GetBinContent(j);
1042 if (fabs(dval) > max)
1043 max = dval;
1044 }
1045 }
1046 for (UInt_t i=0; i<fFourierHistos.size(); i++) {
1047 for (Int_t j=1; j<fFourierHistos[i].dataFourierPhase->GetNbinsX(); j++) {
1048 fFourierHistos[i].dataFourierPhase->SetBinContent(j, fFourierHistos[i].dataFourierPhase->GetBinContent(j)/fabs(max));
1049 }
1050 }
1051
1053 // phase opt real
1054 for (UInt_t i=0; i<fFourierHistos.size(); i++) {
1055 for (Int_t j=start; j<=end; j++) {
1056 dval = fFourierHistos[i].dataFourierPhaseOptReal->GetBinContent(j);
1057 if (fabs(dval) > max)
1058 max = dval;
1059 }
1060 }
1061 for (UInt_t i=0; i<fFourierHistos.size(); i++) {
1062 for (Int_t j=1; j<fFourierHistos[i].dataFourierPhaseOptReal->GetNbinsX(); j++) {
1063 fFourierHistos[i].dataFourierPhaseOptReal->SetBinContent(j, fFourierHistos[i].dataFourierPhaseOptReal->GetBinContent(j)/fabs(max));
1064 }
1065 }
1066 }
1067
1068 // set the marker and line color
1069 for (UInt_t i=0; i<fFourierHistos.size(); i++) {
1070 fFourierHistos[i].dataFourierRe->SetMarkerColor(fColorList[i]);
1071 fFourierHistos[i].dataFourierRe->SetLineColor(fColorList[i]);
1072 fFourierHistos[i].dataFourierIm->SetMarkerColor(fColorList[i]);
1073 fFourierHistos[i].dataFourierIm->SetLineColor(fColorList[i]);
1074 fFourierHistos[i].dataFourierPwr->SetMarkerColor(fColorList[i]);
1075 fFourierHistos[i].dataFourierPwr->SetLineColor(fColorList[i]);
1076 fFourierHistos[i].dataFourierPhase->SetMarkerColor(fColorList[i]);
1077 fFourierHistos[i].dataFourierPhase->SetLineColor(fColorList[i]);
1079 fFourierHistos[i].dataFourierPhaseOptReal->SetMarkerColor(fColorList[i]);
1080 fFourierHistos[i].dataFourierPhaseOptReal->SetLineColor(fColorList[i]);
1081 }
1082 }
1083
1084 // set the marker symbol and size
1085 for (UInt_t i=0; i<fFourierHistos.size(); i++) {
1086 fFourierHistos[i].dataFourierRe->SetMarkerStyle(fMarkerList[i]);
1087 fFourierHistos[i].dataFourierRe->SetMarkerSize(0.7);
1088 fFourierHistos[i].dataFourierIm->SetMarkerStyle(fMarkerList[i]);
1089 fFourierHistos[i].dataFourierIm->SetMarkerSize(0.7);
1090 fFourierHistos[i].dataFourierPwr->SetMarkerStyle(fMarkerList[i]);
1091 fFourierHistos[i].dataFourierPwr->SetMarkerSize(0.7);
1092 fFourierHistos[i].dataFourierPhase->SetMarkerStyle(fMarkerList[i]);
1093 fFourierHistos[i].dataFourierPhase->SetMarkerSize(0.7);
1095 fFourierHistos[i].dataFourierPhaseOptReal->SetMarkerStyle(fMarkerList[i]);
1096 fFourierHistos[i].dataFourierPhaseOptReal->SetMarkerSize(0.7);
1097 }
1098 }
1099
1100 // initialize average histos
1102}
1103
1104//--------------------------------------------------------------------------
1105// InitFourierCanvas (private)
1106//--------------------------------------------------------------------------
1116void PFourierCanvas::InitFourierCanvas(const Char_t* title, Int_t wtopx, Int_t wtopy, Int_t ww, Int_t wh)
1117{
1118 fImp = nullptr;
1119 fBar = nullptr;
1120 fPopupMain = nullptr;
1121
1122 // invoke canvas
1123 TString canvasName = TString("fMainCanvas");
1124 fMainCanvas = std::make_unique<TCanvas>(canvasName.Data(), title, wtopx, wtopy, ww, wh);
1125
1126 // add canvas menu if not in batch mode
1127 if (!fBatchMode) {
1128 fImp = static_cast<TRootCanvas*>(fMainCanvas->GetCanvasImp());
1129 // replace the generic ROOT window icon; the class hint lets the desktop match musrFT.desktop
1130 fImp->SetIconPixmap(const_cast<char**>(musrFT_icon_xpm));
1131 fImp->SetClassHints("musrFT", "musrFT");
1132#ifdef __APPLE__
1133 // on macOS, TGCocoa::SetIconPixmap()/SetClassHints() above are no-ops: the Dock icon
1134 // is process-wide and must be set via NSApplication instead
1135 SetMacDockIcon(musrFT_icon_png, musrFT_icon_png_len);
1136#endif
1137 fBar = fImp->GetMenuBar();
1138 fPopupMain = fBar->AddPopup("MusrFT");
1139
1140 fPopupFourier = std::make_unique<TGPopupMenu>();
1141
1142 fPopupMain->AddPopup("&Fourier", fPopupFourier.get());
1146 fPopupFourier->AddEntry("Show Power", P_MENU_ID_FOURIER+P_MENU_ID_FOURIER_PWR);
1148 fPopupFourier->AddEntry("Show Phase Opt Fourier", P_MENU_ID_FOURIER+P_MENU_ID_FOURIER_PHASE_OPT_REAL);
1149 fPopupFourier->AddSeparator();
1154
1155 switch (fCurrentPlotView) {
1156 case FOURIER_PLOT_REAL:
1158 break;
1159 case FOURIER_PLOT_IMAG:
1161 break;
1164 break;
1165 case FOURIER_PLOT_POWER:
1167 break;
1168 case FOURIER_PLOT_PHASE:
1170 break;
1173 break;
1174 default:
1175 break;
1176 }
1177
1178 fPopupMain->AddEntry("Average", P_MENU_ID_AVERAGE);
1179 if (fAveragedView)
1180 fPopupMain->CheckEntry(P_MENU_ID_AVERAGE);
1181 fPopupMain->AddEntry("Average per Data Set", P_MENU_ID_AVERAGE_PER_DATA_SET);
1184 fPopupMain->AddSeparator();
1185
1186 fPopupMain->AddEntry("Export Data", P_MENU_ID_EXPORT_DATA);
1187 fBar->MapSubwindows();
1188 fBar->Layout();
1189
1190 fPopupMain->Connect("TGPopupMenu", "Activated(Int_t)", "PFourierCanvas", this, "HandleMenuPopup(Int_t)");
1191 }
1192
1193 // divide the canvas into sub pads
1194 // title pad
1195 fTitlePad = std::make_unique<TPaveText>(0.0, YTITLE, 1.0, 1.0, "NDC");
1196
1197 fTitlePad->SetFillColor(TColor::GetColor(255,255,255));
1198 fTitlePad->SetTextAlign(12); // middle, left
1199 fTitlePad->AddText(title);
1200 fTitlePad->Draw();
1201
1202 // fourier pad
1203 fFourierPad = std::make_unique<TPad>("fFourierPad", "fFourierPad", 0.0, YINFO, 1.0, YTITLE);
1204
1205 fFourierPad->SetFillColor(TColor::GetColor(255,255,255));
1206 fFourierPad->Draw();
1207
1208 // info pad
1209 fInfoPad = std::make_unique<TLegend>(0.0, 0.0, 1.0, YINFO, "NDC");
1210
1211 fInfoPad->SetFillColor(TColor::GetColor(255,255,255));
1212 fInfoPad->SetTextAlign(12); // middle, left
1213
1214 fValid = true;
1215
1216 if ((fFourier.size() != fDataSetTag.size()) && fAveragedViewPerDataSet) {
1217 fValid = false;
1218 std::cerr << std::endl << "PFourierCanvas::PFourierCanvas: **PANIC ERROR**: # Fourier != # Data Set Tags." << std::endl;
1219 }
1220
1221 fMainCanvas->cd();
1222
1223 fMainCanvas->Show();
1224
1225 fMainCanvas->Connect("ProcessedEvent(Int_t,Int_t,Int_t,TObject*)", "PFourierCanvas",
1226 this, "HandleCmdKey(Int_t,Int_t,Int_t,TObject*)");
1227}
1228
1229//--------------------------------------------------------------------------
1230// CleanupAverage (private)
1231//--------------------------------------------------------------------------
1236{
1237 for (UInt_t i=0; i<fFourierAverage.size(); i++) {
1238 if (fFourierAverage[i].dataFourierRe != nullptr) {
1239 delete fFourierAverage[i].dataFourierRe;
1240 fFourierAverage[i].dataFourierRe = nullptr;
1241 }
1242 if (fFourierAverage[i].dataFourierIm) {
1243 delete fFourierAverage[i].dataFourierIm;
1244 fFourierAverage[i].dataFourierIm = nullptr;
1245 }
1246 if (fFourierAverage[i].dataFourierPwr) {
1247 delete fFourierAverage[i].dataFourierPwr;
1248 fFourierAverage[i].dataFourierPwr = nullptr;
1249 }
1250 if (fFourierAverage[i].dataFourierPhase) {
1251 delete fFourierAverage[i].dataFourierPhase;
1252 fFourierAverage[i].dataFourierPhase = nullptr;
1253 }
1254 if (fFourierAverage[i].dataFourierPhaseOptReal) {
1255 delete fFourierAverage[i].dataFourierPhaseOptReal;
1256 fFourierAverage[i].dataFourierPhaseOptReal = nullptr;
1257 }
1258 }
1259 fFourierAverage.clear();
1260}
1261
1262//--------------------------------------------------------------------------
1263// HandleAverage (private)
1264//--------------------------------------------------------------------------
1269{
1270 if (fFourierHistos.size() == 0)
1271 return;
1272
1274
1275 TString name("");
1276 Double_t dval=0.0;
1277
1278 Bool_t phaseOptRealPresent = false;
1279 if (fFourierHistos[0].dataFourierPhaseOptReal != nullptr)
1280 phaseOptRealPresent = true;
1281
1282 // check if ALL data shall be averaged
1283 if (fAveragedView) {
1284 fFourierAverage.resize(1);
1285
1286 // create average histograms
1287 name = TString(fFourierHistos[0].dataFourierRe->GetTitle()) + "_avg";
1288 fFourierAverage[0].dataFourierRe = new TH1F(name, name, fFourierHistos[0].dataFourierRe->GetNbinsX(),
1289 fFourierHistos[0].dataFourierRe->GetXaxis()->GetXmin(),
1290 fFourierHistos[0].dataFourierRe->GetXaxis()->GetXmax());
1291
1292 name = TString(fFourierHistos[0].dataFourierIm->GetTitle()) + "_avg";
1293 fFourierAverage[0].dataFourierIm = new TH1F(name, name, fFourierHistos[0].dataFourierIm->GetNbinsX(),
1294 fFourierHistos[0].dataFourierIm->GetXaxis()->GetXmin(),
1295 fFourierHistos[0].dataFourierIm->GetXaxis()->GetXmax());
1296
1297 name = TString(fFourierHistos[0].dataFourierPwr->GetTitle()) + "_avg";
1298 fFourierAverage[0].dataFourierPwr = new TH1F(name, name, fFourierHistos[0].dataFourierPwr->GetNbinsX(),
1299 fFourierHistos[0].dataFourierPwr->GetXaxis()->GetXmin(),
1300 fFourierHistos[0].dataFourierPwr->GetXaxis()->GetXmax());
1301
1302 name = TString(fFourierHistos[0].dataFourierPhase->GetTitle()) + "_avg";
1303 fFourierAverage[0].dataFourierPhase = new TH1F(name, name, fFourierHistos[0].dataFourierPhase->GetNbinsX(),
1304 fFourierHistos[0].dataFourierPhase->GetXaxis()->GetXmin(),
1305 fFourierHistos[0].dataFourierPhase->GetXaxis()->GetXmax());
1306
1307 if (phaseOptRealPresent) {
1308 name = TString(fFourierHistos[0].dataFourierPhaseOptReal->GetTitle()) + "_avg";
1309 fFourierAverage[0].dataFourierPhaseOptReal = new TH1F(name, name, fFourierHistos[0].dataFourierPhaseOptReal->GetNbinsX(),
1310 fFourierHistos[0].dataFourierPhaseOptReal->GetXaxis()->GetXmin(),
1311 fFourierHistos[0].dataFourierPhaseOptReal->GetXaxis()->GetXmax());
1312 }
1313
1314 // real average
1315 for (Int_t j=0; j<fFourierHistos[0].dataFourierRe->GetNbinsX(); j++) {
1316 dval = 0.0;
1317 for (UInt_t i=0; i<fFourierHistos.size(); i++) {
1318 if (j < fFourierHistos[i].dataFourierRe->GetNbinsX())
1319 dval += GetInterpolatedValue(fFourierHistos[i].dataFourierRe, fFourierHistos[0].dataFourierRe->GetBinCenter(j));
1320 }
1321 fFourierAverage[0].dataFourierRe->SetBinContent(j, dval/fFourierHistos.size());
1322 }
1323 // set marker color, line color, maker size, marker type
1324 fFourierAverage[0].dataFourierRe->SetMarkerColor(kBlack);
1325 fFourierAverage[0].dataFourierRe->SetLineColor(kBlack);
1326 fFourierAverage[0].dataFourierRe->SetMarkerSize(0.8);
1327 fFourierAverage[0].dataFourierRe->SetMarkerStyle(22); // closed up triangle
1328
1329 // imaginary average
1330 for (Int_t j=0; j<fFourierHistos[0].dataFourierIm->GetNbinsX(); j++) {
1331 dval = 0.0;
1332 for (UInt_t i=0; i<fFourierHistos.size(); i++) {
1333 if (j < fFourierHistos[i].dataFourierIm->GetNbinsX())
1334 dval += GetInterpolatedValue(fFourierHistos[i].dataFourierIm, fFourierHistos[0].dataFourierIm->GetBinCenter(j));
1335 }
1336 fFourierAverage[0].dataFourierIm->SetBinContent(j, dval/fFourierHistos.size());
1337 }
1338 // set marker color, line color, maker size, marker type
1339 fFourierAverage[0].dataFourierIm->SetMarkerColor(kBlack);
1340 fFourierAverage[0].dataFourierIm->SetLineColor(kBlack);
1341 fFourierAverage[0].dataFourierIm->SetMarkerSize(0.8);
1342 fFourierAverage[0].dataFourierIm->SetMarkerStyle(22); // closed up triangle
1343
1344 // power average
1345 for (Int_t j=0; j<fFourierHistos[0].dataFourierPwr->GetNbinsX(); j++) {
1346 dval = 0.0;
1347 for (UInt_t i=0; i<fFourierHistos.size(); i++) {
1348 if (j < fFourierHistos[i].dataFourierPwr->GetNbinsX())
1349 dval += GetInterpolatedValue(fFourierHistos[i].dataFourierPwr, fFourierHistos[0].dataFourierPwr->GetBinCenter(j));
1350 }
1351 fFourierAverage[0].dataFourierPwr->SetBinContent(j, dval/fFourierHistos.size());
1352 }
1353 // set marker color, line color, maker size, marker type
1354 fFourierAverage[0].dataFourierPwr->SetMarkerColor(kBlack);
1355 fFourierAverage[0].dataFourierPwr->SetLineColor(kBlack);
1356 fFourierAverage[0].dataFourierPwr->SetMarkerSize(0.8);
1357 fFourierAverage[0].dataFourierPwr->SetMarkerStyle(22); // closed up triangle
1358
1359 // phase average
1360 for (Int_t j=0; j<fFourierHistos[0].dataFourierPhase->GetNbinsX(); j++) {
1361 dval = 0.0;
1362 for (UInt_t i=0; i<fFourierHistos.size(); i++) {
1363 if (j < fFourierHistos[i].dataFourierPhase->GetNbinsX())
1364 dval += GetInterpolatedValue(fFourierHistos[i].dataFourierPhase, fFourierHistos[0].dataFourierPhase->GetBinCenter(j));
1365 }
1366 fFourierAverage[0].dataFourierPhase->SetBinContent(j, dval/fFourierHistos.size());
1367 }
1368 // set marker color, line color, maker size, marker type
1369 fFourierAverage[0].dataFourierPhase->SetMarkerColor(kBlack);
1370 fFourierAverage[0].dataFourierPhase->SetLineColor(kBlack);
1371 fFourierAverage[0].dataFourierPhase->SetMarkerSize(0.8);
1372 fFourierAverage[0].dataFourierPhase->SetMarkerStyle(22);
1373
1374 if (phaseOptRealPresent) {
1375 // phase optimised real average
1376 for (Int_t j=0; j<fFourierHistos[0].dataFourierPhaseOptReal->GetNbinsX(); j++) {
1377 dval = 0.0;
1378 for (UInt_t i=0; i<fFourierHistos.size(); i++) {
1379 if (j < fFourierHistos[i].dataFourierPhaseOptReal->GetNbinsX())
1380 dval += GetInterpolatedValue(fFourierHistos[i].dataFourierPhaseOptReal, fFourierHistos[0].dataFourierPhaseOptReal->GetBinCenter(j));
1381 }
1382 fFourierAverage[0].dataFourierPhaseOptReal->SetBinContent(j, dval/fFourierHistos.size());
1383 }
1384 // set marker color, line color, maker size, marker type
1385 fFourierAverage[0].dataFourierPhaseOptReal->SetMarkerColor(kBlack);
1386 fFourierAverage[0].dataFourierPhaseOptReal->SetLineColor(kBlack);
1387 fFourierAverage[0].dataFourierPhaseOptReal->SetMarkerSize(0.8);
1388 fFourierAverage[0].dataFourierPhaseOptReal->SetMarkerStyle(22);
1389 }
1390 }
1391
1392 // check if per data set shall be averaged
1394 // check what size is required
1395 UInt_t count = 1;
1396 Int_t currentTag = fDataSetTag[0];
1397 for (UInt_t i=1; i<fDataSetTag.size(); i++) {
1398 if (fDataSetTag[i] != currentTag) {
1399 currentTag = fDataSetTag[i];
1400 count++;
1401 }
1402 }
1403 fFourierAverage.resize(count);
1404
1405 Int_t start=0, end=0;
1406 for (UInt_t i=0; i<fFourierAverage.size(); i++) {
1407 // get data set range
1408 count = 0;
1409 currentTag = fDataSetTag[0];
1410 start = -1, end = -1;
1411 for (UInt_t j=0; j<fDataSetTag.size(); j++) {
1412 if ((count == i) && (start == -1)) {
1413 if (j > 0)
1414 start = j-1;
1415 else
1416 start = 0;
1417 }
1418 if (currentTag != fDataSetTag[j]) {
1419 if (count == i) {
1420 end = j-1;
1421 break;
1422 }
1423 count++;
1424 currentTag = fDataSetTag[j];
1425 }
1426 }
1427 if (start == -1)
1428 start = fDataSetTag.size()-1;
1429 if (end == -1)
1430 end = fDataSetTag.size()-1;
1431
1432 // create average histograms
1433 name = TString(fFourierHistos[start].dataFourierRe->GetTitle()) + "_avg";
1434 fFourierAverage[i].dataFourierRe = new TH1F(name, name, fFourierHistos[0].dataFourierRe->GetNbinsX(),
1435 fFourierHistos[0].dataFourierRe->GetXaxis()->GetXmin(),
1436 fFourierHistos[0].dataFourierRe->GetXaxis()->GetXmax());
1437
1438 name = TString(fFourierHistos[start].dataFourierIm->GetTitle()) + "_avg";
1439 fFourierAverage[i].dataFourierIm = new TH1F(name, name, fFourierHistos[0].dataFourierIm->GetNbinsX(),
1440 fFourierHistos[0].dataFourierIm->GetXaxis()->GetXmin(),
1441 fFourierHistos[0].dataFourierIm->GetXaxis()->GetXmax());
1442
1443 name = TString(fFourierHistos[start].dataFourierPwr->GetTitle()) + "_avg";
1444 fFourierAverage[i].dataFourierPwr = new TH1F(name, name, fFourierHistos[0].dataFourierPwr->GetNbinsX(),
1445 fFourierHistos[0].dataFourierPwr->GetXaxis()->GetXmin(),
1446 fFourierHistos[0].dataFourierPwr->GetXaxis()->GetXmax());
1447
1448 name = TString(fFourierHistos[start].dataFourierPhase->GetTitle()) + "_avg";
1449 fFourierAverage[i].dataFourierPhase = new TH1F(name, name, fFourierHistos[0].dataFourierPhase->GetNbinsX(),
1450 fFourierHistos[0].dataFourierPhase->GetXaxis()->GetXmin(),
1451 fFourierHistos[0].dataFourierPhase->GetXaxis()->GetXmax());
1452
1453 if (phaseOptRealPresent) {
1454 name = TString(fFourierHistos[start].dataFourierPhaseOptReal->GetTitle()) + "_avg";
1455 fFourierAverage[i].dataFourierPhaseOptReal = new TH1F(name, name, fFourierHistos[0].dataFourierPhaseOptReal->GetNbinsX(),
1456 fFourierHistos[0].dataFourierPhaseOptReal->GetXaxis()->GetXmin(),
1457 fFourierHistos[0].dataFourierPhaseOptReal->GetXaxis()->GetXmax());
1458 }
1459
1460 // real average
1461 for (Int_t j=0; j<fFourierHistos[0].dataFourierRe->GetNbinsX(); j++) {
1462 dval = 0.0;
1463 for (Int_t k=start; k<=end; k++) {
1464 if (j < fFourierHistos[k].dataFourierRe->GetNbinsX())
1465 dval += GetInterpolatedValue(fFourierHistos[k].dataFourierRe, fFourierHistos[0].dataFourierRe->GetBinCenter(j));
1466 }
1467 fFourierAverage[i].dataFourierRe->SetBinContent(j, dval/(end-start+1));
1468 }
1469 // set marker color, line color, maker size, marker type
1470 fFourierAverage[i].dataFourierRe->SetMarkerColor(fColorList[i]);
1471 fFourierAverage[i].dataFourierRe->SetLineColor(fColorList[i]);
1472 fFourierAverage[i].dataFourierRe->SetMarkerSize(0.8);
1473 fFourierAverage[i].dataFourierRe->SetMarkerStyle(22); // closed up triangle
1474
1475 // imaginary average
1476 for (Int_t j=0; j<fFourierHistos[0].dataFourierIm->GetNbinsX(); j++) {
1477 dval = 0.0;
1478 for (Int_t k=start; k<=end; k++) {
1479 if (j < fFourierHistos[k].dataFourierIm->GetNbinsX())
1480 dval += GetInterpolatedValue(fFourierHistos[k].dataFourierIm, fFourierHistos[0].dataFourierIm->GetBinCenter(j));
1481 }
1482 fFourierAverage[i].dataFourierIm->SetBinContent(j, dval/(end-start+1));
1483 }
1484 // set marker color, line color, maker size, marker type
1485 fFourierAverage[i].dataFourierIm->SetMarkerColor(fColorList[i]);
1486 fFourierAverage[i].dataFourierIm->SetLineColor(fColorList[i]);
1487 fFourierAverage[i].dataFourierIm->SetMarkerSize(0.8);
1488 fFourierAverage[i].dataFourierIm->SetMarkerStyle(22); // closed up triangle
1489
1490 // power average
1491 for (Int_t j=0; j<fFourierHistos[0].dataFourierPwr->GetNbinsX(); j++) {
1492 dval = 0.0;
1493 for (Int_t k=start; k<=end; k++) {
1494 if (j < fFourierHistos[k].dataFourierPwr->GetNbinsX())
1495 dval += GetInterpolatedValue(fFourierHistos[k].dataFourierPwr, fFourierHistos[0].dataFourierPwr->GetBinCenter(j));
1496 }
1497 fFourierAverage[i].dataFourierPwr->SetBinContent(j, dval/(end-start+1));
1498 }
1499 // set marker color, line color, maker size, marker type
1500 fFourierAverage[i].dataFourierPwr->SetMarkerColor(fColorList[i]);
1501 fFourierAverage[i].dataFourierPwr->SetLineColor(fColorList[i]);
1502 fFourierAverage[i].dataFourierPwr->SetMarkerSize(0.8);
1503 fFourierAverage[i].dataFourierPwr->SetMarkerStyle(22); // closed up triangle
1504
1505 // phase average
1506 for (Int_t j=0; j<fFourierHistos[0].dataFourierPhase->GetNbinsX(); j++) {
1507 dval = 0.0;
1508 for (Int_t k=start; k<=end; k++) {
1509 if (j < fFourierHistos[k].dataFourierPhase->GetNbinsX())
1510 dval += GetInterpolatedValue(fFourierHistos[k].dataFourierPhase, fFourierHistos[0].dataFourierPhase->GetBinCenter(j));
1511 }
1512 fFourierAverage[i].dataFourierPhase->SetBinContent(j, dval/(end-start+1));
1513 }
1514 // set marker color, line color, maker size, marker type
1515 fFourierAverage[i].dataFourierPhase->SetMarkerColor(fColorList[i]);
1516 fFourierAverage[i].dataFourierPhase->SetLineColor(fColorList[i]);
1517 fFourierAverage[i].dataFourierPhase->SetMarkerSize(0.8);
1518 fFourierAverage[i].dataFourierPhase->SetMarkerStyle(22); // closed up triangle
1519
1520 if (phaseOptRealPresent) {
1521 // phase optimised real average
1522 for (Int_t j=0; j<fFourierHistos[0].dataFourierPhaseOptReal->GetNbinsX(); j++) {
1523 dval = 0.0;
1524 for (Int_t k=start; k<=end; k++) {
1525 if (j < fFourierHistos[k].dataFourierPhaseOptReal->GetNbinsX())
1526 dval += GetInterpolatedValue(fFourierHistos[k].dataFourierPhaseOptReal, fFourierHistos[0].dataFourierPhaseOptReal->GetBinCenter(j));
1527 }
1528 fFourierAverage[i].dataFourierPhaseOptReal->SetBinContent(j, dval/(end-start+1));
1529 }
1530 // set marker color, line color, maker size, marker type
1531 fFourierAverage[i].dataFourierPhaseOptReal->SetMarkerColor(fColorList[i]);
1532 fFourierAverage[i].dataFourierPhaseOptReal->SetLineColor(fColorList[i]);
1533 fFourierAverage[i].dataFourierPhaseOptReal->SetMarkerSize(0.8);
1534 fFourierAverage[i].dataFourierPhaseOptReal->SetMarkerStyle(22); // closed up triangle
1535 }
1536 }
1537 }
1538}
1539
1540//--------------------------------------------------------------------------
1541// CalcPhaseOptReal (private)
1542//--------------------------------------------------------------------------
1547{
1548 Int_t start = fFourierHistos[0].dataFourierRe->FindFixBin(fInitialXRange[0]);
1549 Int_t end = fFourierHistos[0].dataFourierRe->FindFixBin(fInitialXRange[1]);
1550
1551 Double_t dval=0.0, max=0.0;
1552 for (UInt_t i=0; i<fFourierHistos.size(); i++) {
1553 fFourierHistos[i].dataFourierPhaseOptReal = fFourier[i]->GetPhaseOptRealFourier(fFourierHistos[i].dataFourierRe,
1554 fFourierHistos[i].dataFourierIm, fFourierHistos[i].optPhase, 1.0, fInitialXRange[0], fInitialXRange[1]);
1555 // normalize it
1556 max = 0.0;
1557 for (Int_t j=start; j<=end; j++) {
1558 dval = fFourierHistos[i].dataFourierPhaseOptReal->GetBinContent(j);
1559 if (fabs(dval) > max)
1560 max = dval;
1561 }
1562 for (Int_t j=1; j<fFourierHistos[i].dataFourierPhaseOptReal->GetNbinsX(); j++) {
1563 fFourierHistos[i].dataFourierPhaseOptReal->SetBinContent(j, fFourierHistos[i].dataFourierPhaseOptReal->GetBinContent(j)/fabs(max));
1564 }
1565 // set the marker and line color
1566 fFourierHistos[i].dataFourierPhaseOptReal->SetMarkerColor(fColorList[i]);
1567 fFourierHistos[i].dataFourierPhaseOptReal->SetLineColor(fColorList[i]);
1568
1569 // set the marker symbol and size
1570 fFourierHistos[i].dataFourierPhaseOptReal->SetMarkerStyle(fMarkerList[i]);
1571 fFourierHistos[i].dataFourierPhaseOptReal->SetMarkerSize(0.7);
1572 }
1573}
1574
1575//--------------------------------------------------------------------------
1576// PlotFourier (private)
1577//--------------------------------------------------------------------------
1582{
1583 // check if phase opt real Fourier spectra already exists if requested,
1584 // and if not calculate them first
1586 if (fFourierHistos[0].dataFourierPhaseOptReal == nullptr) { // not yet calculated
1588 }
1589 }
1590
1591 fFourierPad->cd();
1592
1593 Double_t xmin=0, xmax=0;
1594 xmin = fInitialXRange[0];
1595 xmax = fInitialXRange[1];
1596
1597 Double_t ymin=0, ymax=0;
1598 switch (fCurrentPlotView) {
1599 case FOURIER_PLOT_REAL:
1600 fFourierHistos[0].dataFourierRe->GetXaxis()->SetRangeUser(xmin, xmax);
1601 ymin = GetMinimum(fFourierHistos[0].dataFourierRe, xmin, xmax);
1602 ymax = GetMaximum(fFourierHistos[0].dataFourierRe, xmin, xmax);
1603 for (UInt_t i=1; i<fFourierHistos.size(); i++) {
1604 if (GetMaximum(fFourierHistos[i].dataFourierRe, xmin, xmax) > ymax)
1605 ymax = GetMaximum(fFourierHistos[i].dataFourierRe, xmin, xmax);
1606 if (GetMinimum(fFourierHistos[i].dataFourierRe, xmin, xmax) < ymin)
1607 ymin = GetMinimum(fFourierHistos[i].dataFourierRe, xmin, xmax);
1608 }
1609 fFourierHistos[0].dataFourierRe->GetYaxis()->SetRangeUser(1.05*ymin, 1.05*ymax);
1610 fFourierHistos[0].dataFourierRe->GetYaxis()->SetTitle("Real");
1611 fFourierHistos[0].dataFourierRe->GetYaxis()->SetTitleOffset(1.3);
1612 fFourierHistos[0].dataFourierRe->GetYaxis()->SetDecimals(kTRUE);
1613 fFourierHistos[0].dataFourierRe->GetXaxis()->SetTitle(fXaxisTitle.Data());
1614 fFourierHistos[0].dataFourierRe->Draw("p");
1615 for (UInt_t i=1; i<fFourierHistos.size(); i++) {
1616 fFourierHistos[i].dataFourierRe->Draw("psame");
1617 }
1618 break;
1619 case FOURIER_PLOT_IMAG:
1620 fFourierHistos[0].dataFourierIm->GetXaxis()->SetRangeUser(xmin, xmax);
1621 ymin = GetMinimum(fFourierHistos[0].dataFourierIm, xmin, xmax);
1622 ymax = GetMaximum(fFourierHistos[0].dataFourierIm, xmin, xmax);
1623 for (UInt_t i=1; i<fFourierHistos.size(); i++) {
1624 if (GetMaximum(fFourierHistos[i].dataFourierIm, xmin, xmax) > ymax)
1625 ymax = GetMaximum(fFourierHistos[i].dataFourierIm, xmin, xmax);
1626 if (GetMinimum(fFourierHistos[i].dataFourierIm, xmin, xmax) < ymin)
1627 ymin = GetMinimum(fFourierHistos[i].dataFourierIm, xmin, xmax);
1628 }
1629 fFourierHistos[0].dataFourierIm->GetYaxis()->SetRangeUser(1.05*ymin, 1.05*ymax);
1630 fFourierHistos[0].dataFourierIm->GetYaxis()->SetTitleOffset(1.3);
1631 fFourierHistos[0].dataFourierIm->GetYaxis()->SetDecimals(kTRUE);
1632 fFourierHistos[0].dataFourierIm->GetYaxis()->SetTitle("Imag");
1633 fFourierHistos[0].dataFourierIm->GetXaxis()->SetTitle(fXaxisTitle.Data());
1634 fFourierHistos[0].dataFourierIm->Draw("p");
1635 for (UInt_t i=1; i<fFourierHistos.size(); i++) {
1636 fFourierHistos[i].dataFourierIm->Draw("psame");
1637 }
1638 break;
1640 fFourierHistos[0].dataFourierRe->GetXaxis()->SetRangeUser(xmin, xmax);
1641 ymin = GetMinimum(fFourierHistos[0].dataFourierRe, xmin, xmax);
1642 ymax = GetMaximum(fFourierHistos[0].dataFourierRe, xmin, xmax);
1643 for (UInt_t i=1; i<fFourierHistos.size(); i++) {
1644 if (GetMaximum(fFourierHistos[i].dataFourierRe, xmin, xmax) > ymax)
1645 ymax = GetMaximum(fFourierHistos[i].dataFourierRe, xmin, xmax);
1646 if (GetMaximum(fFourierHistos[i].dataFourierIm, xmin, xmax) > ymax)
1647 ymax = GetMaximum(fFourierHistos[i].dataFourierIm, xmin, xmax);
1648 if (GetMinimum(fFourierHistos[i].dataFourierRe, xmin, xmax) < ymin)
1649 ymin = GetMinimum(fFourierHistos[i].dataFourierRe, xmin, xmax);
1650 if (GetMinimum(fFourierHistos[i].dataFourierIm, xmin, xmax) < ymin)
1651 ymin = GetMinimum(fFourierHistos[i].dataFourierIm, xmin, xmax);
1652 }
1653 fFourierHistos[0].dataFourierRe->GetYaxis()->SetRangeUser(1.05*ymin, 1.05*ymax);
1654 fFourierHistos[0].dataFourierRe->GetYaxis()->SetTitleOffset(1.3);
1655 fFourierHistos[0].dataFourierRe->GetYaxis()->SetDecimals(kTRUE);
1656 fFourierHistos[0].dataFourierRe->GetYaxis()->SetTitle("Real");
1657 fFourierHistos[0].dataFourierRe->GetXaxis()->SetTitle(fXaxisTitle.Data());
1658 fFourierHistos[0].dataFourierRe->Draw("p");
1659 for (UInt_t i=1; i<fFourierHistos.size(); i++) {
1660 fFourierHistos[i].dataFourierRe->Draw("psame");
1661 }
1662 for (UInt_t i=0; i<fFourierHistos.size(); i++) {
1663 fFourierHistos[i].dataFourierIm->Draw("psame");
1664 }
1665 break;
1666 case FOURIER_PLOT_POWER:
1667 // get maximum of Fourier data in the range
1668 fFourierHistos[0].dataFourierPwr->GetXaxis()->SetRangeUser(xmin, xmax);
1669 ymin = 0.0;
1670 ymax = GetMaximum(fFourierHistos[0].dataFourierPwr, xmin, xmax);
1671 for (UInt_t i=1; i<fFourierHistos.size(); i++) {
1672 if (GetMaximum(fFourierHistos[i].dataFourierPwr, xmin, xmax) > ymax)
1673 ymax = GetMaximum(fFourierHistos[i].dataFourierPwr, xmin, xmax);
1674 }
1675 fFourierHistos[0].dataFourierPwr->GetYaxis()->SetRangeUser(ymin, 1.03*ymax);
1676 fFourierHistos[0].dataFourierPwr->GetYaxis()->SetTitle("Power");
1677 fFourierHistos[0].dataFourierPwr->GetYaxis()->SetTitleOffset(1.3);
1678 fFourierHistos[0].dataFourierPwr->GetYaxis()->SetDecimals(kTRUE);
1679 fFourierHistos[0].dataFourierPwr->GetXaxis()->SetTitle(fXaxisTitle.Data());
1680 fFourierHistos[0].dataFourierPwr->Draw("p");
1681 for (UInt_t i=1; i<fFourierHistos.size(); i++) {
1682 fFourierHistos[i].dataFourierPwr->Draw("psame");
1683 }
1684 break;
1685 case FOURIER_PLOT_PHASE:
1686 fFourierHistos[0].dataFourierPhase->GetXaxis()->SetRangeUser(xmin, xmax);
1687 ymin = GetMinimum(fFourierHistos[0].dataFourierPhase, xmin, xmax);
1688 ymax = GetMaximum(fFourierHistos[0].dataFourierPhase, xmin, xmax);
1689 for (UInt_t i=1; i<fFourierHistos.size(); i++) {
1690 if (GetMaximum(fFourierHistos[i].dataFourierPhase, xmin, xmax) > ymax)
1691 ymax = GetMaximum(fFourierHistos[i].dataFourierPhase, xmin, xmax);
1692 if (GetMinimum(fFourierHistos[i].dataFourierPhase, xmin, xmax) < ymin)
1693 ymin = GetMinimum(fFourierHistos[i].dataFourierPhase, xmin, xmax);
1694 }
1695 fFourierHistos[0].dataFourierPhase->GetYaxis()->SetRangeUser(1.05*ymin, 1.05*ymax);
1696 fFourierHistos[0].dataFourierPhase->GetYaxis()->SetTitleOffset(1.3);
1697 fFourierHistos[0].dataFourierPhase->GetYaxis()->SetDecimals(kTRUE);
1698 fFourierHistos[0].dataFourierPhase->GetYaxis()->SetTitle("Phase");
1699 fFourierHistos[0].dataFourierPhase->GetXaxis()->SetTitle(fXaxisTitle.Data());
1700 fFourierHistos[0].dataFourierPhase->Draw("p");
1701 for (UInt_t i=1; i<fFourierHistos.size(); i++) {
1702 fFourierHistos[i].dataFourierPhase->Draw("psame");
1703 }
1704 break;
1706 fFourierHistos[0].dataFourierPhaseOptReal->GetXaxis()->SetRangeUser(xmin, xmax);
1707 ymin = GetMinimum(fFourierHistos[0].dataFourierPhaseOptReal, xmin, xmax);
1708 ymax = GetMaximum(fFourierHistos[0].dataFourierPhaseOptReal, xmin, xmax);
1709 for (UInt_t i=1; i<fFourierHistos.size(); i++) {
1710 if (GetMaximum(fFourierHistos[i].dataFourierPhaseOptReal, xmin, xmax) > ymax)
1711 ymax = GetMaximum(fFourierHistos[i].dataFourierPhaseOptReal, xmin, xmax);
1712 if (GetMinimum(fFourierHistos[i].dataFourierPhaseOptReal, xmin, xmax) < ymin)
1713 ymin = GetMinimum(fFourierHistos[i].dataFourierPhaseOptReal, xmin, xmax);
1714 }
1715 fFourierHistos[0].dataFourierPhaseOptReal->GetYaxis()->SetRangeUser(ymin, 1.05*ymax);
1716 fFourierHistos[0].dataFourierPhaseOptReal->GetYaxis()->SetTitleOffset(1.3);
1717 fFourierHistos[0].dataFourierPhaseOptReal->GetYaxis()->SetDecimals(kTRUE);
1718 fFourierHistos[0].dataFourierPhaseOptReal->GetYaxis()->SetTitle("Phase Opt. Real");
1719 fFourierHistos[0].dataFourierPhaseOptReal->GetXaxis()->SetTitle(fXaxisTitle.Data());
1720 fFourierHistos[0].dataFourierPhaseOptReal->Draw("p");
1721 for (UInt_t i=1; i<fFourierHistos.size(); i++) {
1722 fFourierHistos[i].dataFourierPhaseOptReal->Draw("psame");
1723 }
1724 break;
1725 default:
1726 break;
1727 }
1728
1729 fFourierPad->Update();
1730
1731 fMainCanvas->cd();
1732 fMainCanvas->Update();
1733}
1734
1735//--------------------------------------------------------------------------
1736// PlotFourierPhaseValue (private)
1737//--------------------------------------------------------------------------
1742{
1743 Double_t x, y;
1744 TString str;
1745
1746 // plot Fourier phase
1747 str = TString("phase = ");
1748 str += fCurrentFourierPhase;
1749 x = 0.7;
1750 y = 0.85;
1751 fCurrentFourierPhaseText.reset(new TLatex());
1752 fCurrentFourierPhaseText->SetNDC(kTRUE);
1753 fCurrentFourierPhaseText->SetText(x, y, str.Data());
1754 fCurrentFourierPhaseText->SetTextFont(62);
1755 fCurrentFourierPhaseText->SetTextSize(0.03);
1756
1757 fFourierPad->cd();
1758
1760
1761 fFourierPad->Update();
1762}
1763
1764//--------------------------------------------------------------------------
1765// PlotAverage (private)
1766//--------------------------------------------------------------------------
1771{
1772 fFourierPad->cd();
1773
1774 if (fFourierAverage.size() == 0) { // ups, HandleAverage never called!
1775 HandleAverage();
1776 }
1777
1778 Double_t xmin=0.0, xmax=0.0;
1779 xmin = fInitialXRange[0];
1780 xmax = fInitialXRange[1];
1781 Double_t ymin=0.0, ymax=0.0;
1782
1783 if (fLegAvgPerDataSet.get()) {
1784 fLegAvgPerDataSet->Clear();
1785 }
1786
1787 switch (fCurrentPlotView) {
1788 case FOURIER_PLOT_REAL:
1789 fFourierAverage[0].dataFourierRe->GetXaxis()->SetRangeUser(xmin, xmax);
1790 ymin = GetMinimum(fFourierAverage[0].dataFourierRe, xmin, xmax);
1791 ymax = GetMaximum(fFourierAverage[0].dataFourierRe, xmin, xmax);
1792 for (UInt_t i=1; i<fFourierAverage.size(); i++) {
1793 if (GetMaximum(fFourierAverage[i].dataFourierRe, xmin, xmax) > ymax)
1794 ymax = GetMaximum(fFourierAverage[i].dataFourierRe, xmin, xmax);
1795 if (GetMinimum(fFourierAverage[i].dataFourierRe, xmin, xmax) < ymin)
1796 ymin = GetMinimum(fFourierAverage[i].dataFourierRe, xmin, xmax);
1797 }
1798 fFourierAverage[0].dataFourierRe->GetYaxis()->SetRangeUser(1.03*ymin, 1.03*ymax);
1799 fFourierAverage[0].dataFourierRe->GetYaxis()->SetTitleOffset(1.3);
1800 fFourierAverage[0].dataFourierRe->GetYaxis()->SetDecimals(kTRUE);
1801 fFourierAverage[0].dataFourierRe->GetYaxis()->SetTitle("<Real>");
1802 fFourierAverage[0].dataFourierRe->GetXaxis()->SetTitle(fXaxisTitle.Data());
1803 fFourierAverage[0].dataFourierRe->GetXaxis()->SetRangeUser(xmin, xmax);
1804 fFourierAverage[0].dataFourierRe->Draw("p");
1805 break;
1806 case FOURIER_PLOT_IMAG:
1807 fFourierAverage[0].dataFourierIm->GetXaxis()->SetRangeUser(xmin, xmax);
1808 ymin = GetMinimum(fFourierAverage[0].dataFourierIm, xmin, xmax);
1809 ymax = GetMaximum(fFourierAverage[0].dataFourierIm, xmin, xmax);
1810 for (UInt_t i=1; i<fFourierAverage.size(); i++) {
1811 if (GetMaximum(fFourierAverage[i].dataFourierIm, xmin, xmax) > ymax)
1812 ymax = GetMaximum(fFourierAverage[i].dataFourierIm, xmin, xmax);
1813 if (GetMinimum(fFourierAverage[i].dataFourierIm, xmin, xmax) < ymin)
1814 ymin = GetMinimum(fFourierAverage[i].dataFourierIm, xmin, xmax);
1815 }
1816 fFourierAverage[0].dataFourierIm->GetYaxis()->SetRangeUser(1.03*ymin, 1.03*ymax);
1817 fFourierAverage[0].dataFourierIm->GetYaxis()->SetTitleOffset(1.3);
1818 fFourierAverage[0].dataFourierIm->GetYaxis()->SetDecimals(kTRUE);
1819 fFourierAverage[0].dataFourierIm->GetYaxis()->SetTitle("<Imag>");
1820 fFourierAverage[0].dataFourierIm->GetXaxis()->SetTitle(fXaxisTitle.Data());
1821 fFourierAverage[0].dataFourierIm->GetXaxis()->SetRangeUser(xmin, xmax);
1822 fFourierAverage[0].dataFourierIm->Draw("p");
1823 break;
1825 fFourierAverage[0].dataFourierRe->GetXaxis()->SetRangeUser(xmin, xmax);
1826 ymin = GetMinimum(fFourierAverage[0].dataFourierRe, xmin, xmax);
1827 ymax = GetMaximum(fFourierAverage[0].dataFourierRe, xmin, xmax);
1828 for (UInt_t i=1; i<fFourierAverage.size(); i++) {
1829 if (GetMaximum(fFourierAverage[i].dataFourierRe, xmin, xmax) > ymax)
1830 ymax = GetMaximum(fFourierAverage[i].dataFourierRe, xmin, xmax);
1831 if (GetMinimum(fFourierAverage[i].dataFourierRe, xmin, xmax) < ymin)
1832 ymin = GetMinimum(fFourierAverage[i].dataFourierRe, xmin, xmax);
1833 }
1834 fFourierAverage[0].dataFourierRe->GetYaxis()->SetRangeUser(1.03*ymin, 1.03*ymax);
1835 fFourierAverage[0].dataFourierRe->GetYaxis()->SetTitleOffset(1.3);
1836 fFourierAverage[0].dataFourierRe->GetYaxis()->SetDecimals(kTRUE);
1837 fFourierAverage[0].dataFourierRe->GetYaxis()->SetTitle("<Real+Imag>");
1838 fFourierAverage[0].dataFourierRe->GetXaxis()->SetTitle(fXaxisTitle.Data());
1839 fFourierAverage[0].dataFourierRe->GetXaxis()->SetRangeUser(xmin, xmax);
1840 fFourierAverage[0].dataFourierRe->Draw("p");
1841 fFourierAverage[0].dataFourierIm->Draw("psame");
1842 break;
1843 case FOURIER_PLOT_POWER:
1844 // get maximum of Fourier data in the range
1845 fFourierAverage[0].dataFourierPwr->GetXaxis()->SetRangeUser(xmin, xmax);
1846 ymin = 0.0;
1847 ymax = GetMaximum(fFourierAverage[0].dataFourierPwr, xmin, xmax);
1848 for (UInt_t i=1; i<fFourierAverage.size(); i++) {
1849 if (GetMaximum(fFourierAverage[i].dataFourierPwr, xmin, xmax) > ymax)
1850 ymax = GetMaximum(fFourierAverage[i].dataFourierPwr, xmin, xmax);
1851 }
1852 fFourierAverage[0].dataFourierPwr->GetYaxis()->SetRangeUser(ymin, 1.03*ymax);
1853 fFourierAverage[0].dataFourierPwr->GetYaxis()->SetTitleOffset(1.3);
1854 fFourierAverage[0].dataFourierPwr->GetYaxis()->SetDecimals(kTRUE);
1855 fFourierAverage[0].dataFourierPwr->GetYaxis()->SetTitle("<Power>");
1856 fFourierAverage[0].dataFourierPwr->GetXaxis()->SetTitle(fXaxisTitle.Data());
1857 fFourierAverage[0].dataFourierPwr->Draw("p");
1858 break;
1859 case FOURIER_PLOT_PHASE:
1860 fFourierAverage[0].dataFourierPhase->GetXaxis()->SetRangeUser(xmin, xmax);
1861 ymin = GetMinimum(fFourierAverage[0].dataFourierPhase, xmin, xmax);
1862 ymax = GetMaximum(fFourierAverage[0].dataFourierPhase, xmin, xmax);
1863 for (UInt_t i=1; i<fFourierAverage.size(); i++) {
1864 if (GetMaximum(fFourierAverage[i].dataFourierPhase, xmin, xmax) > ymax)
1865 ymax = GetMaximum(fFourierAverage[i].dataFourierPhase, xmin, xmax);
1866 if (GetMinimum(fFourierAverage[i].dataFourierPhase, xmin, xmax) < ymin)
1867 ymin = GetMinimum(fFourierAverage[i].dataFourierPhase, xmin, xmax);
1868 }
1869 fFourierAverage[0].dataFourierPhase->GetYaxis()->SetRangeUser(1.03*ymin, 1.03*ymax);
1870 fFourierAverage[0].dataFourierPhase->GetYaxis()->SetTitleOffset(1.3);
1871 fFourierAverage[0].dataFourierPhase->GetYaxis()->SetDecimals(kTRUE);
1872 fFourierAverage[0].dataFourierPhase->GetYaxis()->SetTitle("<Phase>");
1873 fFourierAverage[0].dataFourierPhase->GetXaxis()->SetTitle(fXaxisTitle.Data());
1874 fFourierAverage[0].dataFourierPhase->GetXaxis()->SetRangeUser(xmin, xmax);
1875 fFourierAverage[0].dataFourierPhase->Draw("p");
1876 break;
1878 if (fFourierHistos[0].dataFourierPhaseOptReal == nullptr) {
1879 std::cout << "debug> need to calculate phase opt. average first ..." << std::endl;
1881 HandleAverage();
1882 }
1883 fFourierAverage[0].dataFourierPhaseOptReal->GetXaxis()->SetRangeUser(xmin, xmax);
1884 ymin = GetMinimum(fFourierAverage[0].dataFourierPhaseOptReal, xmin, xmax);
1885 ymax = GetMaximum(fFourierAverage[0].dataFourierPhaseOptReal, xmin, xmax);
1886 for (UInt_t i=1; i<fFourierAverage.size(); i++) {
1887 if (GetMaximum(fFourierAverage[i].dataFourierPhaseOptReal, xmin, xmax) > ymax)
1888 ymax = GetMaximum(fFourierAverage[i].dataFourierPhaseOptReal, xmin, xmax);
1889 if (GetMinimum(fFourierAverage[i].dataFourierPhaseOptReal, xmin, xmax) < ymin)
1890 ymin = GetMinimum(fFourierAverage[i].dataFourierPhaseOptReal, xmin, xmax);
1891 }
1892 fFourierAverage[0].dataFourierPhaseOptReal->GetYaxis()->SetRangeUser(ymin, 1.03*ymax);
1893 fFourierAverage[0].dataFourierPhaseOptReal->GetYaxis()->SetTitleOffset(1.3);
1894 fFourierAverage[0].dataFourierPhaseOptReal->GetYaxis()->SetDecimals(kTRUE);
1895 fFourierAverage[0].dataFourierPhaseOptReal->GetYaxis()->SetTitle("<Phase Opt. Real>");
1896 fFourierAverage[0].dataFourierPhaseOptReal->GetXaxis()->SetTitle(fXaxisTitle.Data());
1897 fFourierAverage[0].dataFourierPhaseOptReal->GetXaxis()->SetRangeUser(xmin, xmax);
1898 fFourierAverage[0].dataFourierPhaseOptReal->Draw("p");
1899 break;
1900 default:
1901 break;
1902 }
1903
1904 if (fAveragedViewPerDataSet) { // plot all the rest
1905 fLegAvgPerDataSet = std::make_unique<TLegend>(0.55, 0.4, 0.85, 0.6);
1906 TString str = GetDataSetName(fFourierAverage[0].dataFourierPwr->GetTitle());
1907 TString label = TString::Format("<%s>", str.Data());
1908 fLegAvgPerDataSet->AddEntry(fFourierAverage[0].dataFourierPwr, label.Data());
1909 for (UInt_t i=1; i<fFourierAverage.size(); i++) {
1910 switch (fCurrentPlotView) {
1911 case FOURIER_PLOT_REAL:
1912 fFourierAverage[i].dataFourierRe->Draw("psame");
1913 break;
1914 case FOURIER_PLOT_IMAG:
1915 fFourierAverage[i].dataFourierIm->Draw("psame");
1916 break;
1918 fFourierAverage[i].dataFourierRe->Draw("psame");
1919 fFourierAverage[i].dataFourierIm->Draw("psame");
1920 break;
1921 case FOURIER_PLOT_POWER:
1922 fFourierAverage[i].dataFourierPwr->Draw("psame");
1923 break;
1924 case FOURIER_PLOT_PHASE:
1925 fFourierAverage[i].dataFourierPhase->Draw("psame");
1926 break;
1928 fFourierAverage[i].dataFourierPhaseOptReal->Draw("psame");
1929 break;
1930 default:
1931 break;
1932 }
1933 // add legend ?!?!
1934 str = GetDataSetName(fFourierAverage[i].dataFourierPwr->GetTitle());
1935 label = TString::Format("<%s>", str.Data());
1936 fLegAvgPerDataSet->AddEntry(fFourierAverage[i].dataFourierPwr, label.Data());
1937 }
1938 fLegAvgPerDataSet->Draw();
1939 }
1940
1941 fFourierPad->Update();
1942
1943 fMainCanvas->cd();
1944 fMainCanvas->Update();
1945}
1946
1947//--------------------------------------------------------------------------
1948// IncrementFourierPhase (private)
1949//--------------------------------------------------------------------------
1954{
1956 return;
1957
1958 Double_t re, im;
1959 Double_t inc = 1.0;
1960 const Double_t cp = TMath::Cos(inc/180.0*TMath::Pi());
1961 const Double_t sp = TMath::Sin(inc/180.0*TMath::Pi());
1962
1963 fCurrentFourierPhase += inc;
1965
1966 for (UInt_t i=0; i<fFourierHistos.size(); i++) { // loop over all data sets
1967 if ((fFourierHistos[i].dataFourierRe != nullptr) && (fFourierHistos[i].dataFourierIm != nullptr)) {
1968 for (Int_t j=0; j<fFourierHistos[i].dataFourierRe->GetNbinsX(); j++) { // loop over a fourier data set
1969 // calculate new fourier data set value
1970 re = fFourierHistos[i].dataFourierRe->GetBinContent(j) * cp + fFourierHistos[i].dataFourierIm->GetBinContent(j) * sp;
1971 im = fFourierHistos[i].dataFourierIm->GetBinContent(j) * cp - fFourierHistos[i].dataFourierRe->GetBinContent(j) * sp;
1972 // overwrite fourier data set value
1973 fFourierHistos[i].dataFourierRe->SetBinContent(j, re);
1974 fFourierHistos[i].dataFourierIm->SetBinContent(j, im);
1975 }
1976 }
1977 }
1978}
1979
1980//--------------------------------------------------------------------------
1981// DecrementFourierPhase (private)
1982//--------------------------------------------------------------------------
1987{
1989 return;
1990
1991 Double_t re, im;
1992 Double_t inc = 1.0;
1993 const Double_t cp = TMath::Cos(inc/180.0*TMath::Pi());
1994 const Double_t sp = TMath::Sin(inc/180.0*TMath::Pi());
1995
1996 fCurrentFourierPhase -= inc;
1998
1999 for (UInt_t i=0; i<fFourierHistos.size(); i++) { // loop over all data sets
2000 if ((fFourierHistos[i].dataFourierRe != nullptr) && (fFourierHistos[i].dataFourierIm != nullptr)) {
2001 for (Int_t j=0; j<fFourierHistos[i].dataFourierRe->GetNbinsX(); j++) { // loop over a fourier data set
2002 // calculate new fourier data set value
2003 re = fFourierHistos[i].dataFourierRe->GetBinContent(j) * cp - fFourierHistos[i].dataFourierIm->GetBinContent(j) * sp;
2004 im = fFourierHistos[i].dataFourierIm->GetBinContent(j) * cp + fFourierHistos[i].dataFourierRe->GetBinContent(j) * sp;
2005 // overwrite fourier data set value
2006 fFourierHistos[i].dataFourierRe->SetBinContent(j, re);
2007 fFourierHistos[i].dataFourierIm->SetBinContent(j, im);
2008 }
2009 }
2010 }
2011}
2012
2013//--------------------------------------------------------------------------
2014// GetMaximum (private)
2015//--------------------------------------------------------------------------
2027Double_t PFourierCanvas::GetMaximum(TH1F* histo, Double_t xmin, Double_t xmax)
2028{
2029 if (histo == nullptr)
2030 return 0.0;
2031
2032 Int_t start=0, end=0;
2033 if (xmin == xmax) {
2034 start = 1;
2035 end = histo->GetNbinsX();
2036 } else {
2037 start = histo->FindBin(xmin);
2038 if ((start==0) || (start==histo->GetNbinsX()+1)) // underflow/overflow
2039 start = 1;
2040 end = histo->FindBin(xmax);
2041 if ((end==0) || (end==histo->GetNbinsX()+1)) // underflow/overflow
2042 end = histo->GetNbinsX();
2043 }
2044
2045 Double_t max = histo->GetBinContent(start);
2046 Double_t binContent;
2047 for (Int_t i=start; i<end; i++) {
2048 binContent = histo->GetBinContent(i);
2049 if (max < binContent)
2050 max = binContent;
2051 }
2052
2053 return max;
2054}
2055
2056//--------------------------------------------------------------------------
2057// GetMinimum (private)
2058//--------------------------------------------------------------------------
2070Double_t PFourierCanvas::GetMinimum(TH1F* histo, Double_t xmin, Double_t xmax)
2071{
2072 if (histo == nullptr)
2073 return 0.0;
2074
2075 Int_t start=0, end=0;
2076 if (xmin == xmax) {
2077 start = 1;
2078 end = histo->GetNbinsX();
2079 } else {
2080 start = histo->FindBin(xmin);
2081 if ((start==0) || (start==histo->GetNbinsX()+1)) // underflow/overflow
2082 start = 1;
2083 end = histo->FindBin(xmax);
2084 if ((end==0) || (end==histo->GetNbinsX()+1)) // underflow/overflow
2085 end = histo->GetNbinsX();
2086 }
2087
2088 Double_t min = histo->GetBinContent(start);
2089 Double_t binContent;
2090 for (Int_t i=start; i<end; i++) {
2091 binContent = histo->GetBinContent(i);
2092 if (min > binContent)
2093 min = binContent;
2094 }
2095
2096 return min;
2097}
2098
2099//--------------------------------------------------------------------------
2100// GetInterpolatedValue (private)
2101//--------------------------------------------------------------------------
2112Double_t PFourierCanvas::GetInterpolatedValue(TH1F* histo, Double_t xVal)
2113{
2114 if (histo == nullptr)
2115 return 0.0;
2116
2117 Int_t idx = histo->FindBin(xVal);
2118
2119 // make sure idx is within range
2120 if ((idx < 1) || (idx > histo->GetNbinsX()))
2121 return 0.0;
2122
2123 // make sure the lower bound idx is found. This is needed since
2124 // FindBin rounds towards the closer idx.
2125 if (histo->GetBinCenter(idx) > xVal)
2126 --idx;
2127
2128 Double_t x0, x1, y0, y1;
2129 x0 = histo->GetBinCenter(idx);
2130 x1 = histo->GetBinCenter(idx+1);
2131 y0 = histo->GetBinContent(idx);
2132 y1 = histo->GetBinContent(idx+1);
2133
2134 return (y1-y0)*(xVal-x0)/(x1-x0)+y0;
2135}
2136
2137//--------------------------------------------------------------------------
2138// GetDataSetName (private)
2139//--------------------------------------------------------------------------
2149{
2150 TString str(title);
2151
2152 Ssiz_t idx = str.First(':');
2153 str.Remove(0, idx+1);
2154 idx = str.First(',');
2155 str.Remove(idx);
2156
2157 return str;
2158}
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