musrfit  1.9.2
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-2023 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 
45 static const Char_t *gFiletypes[] = { "Data files", "*.dat",
46  "All files", "*",
47  nullptr, nullptr };
48 
50 
51 //---------------------------------------------------------------------------
56 {
57  fTimeout = 0;
58 
59  fBatchMode = false;
60  fValid = false;
61  fAveragedView = false;
64  fInitialXRange[0] = 0.0;
65  fInitialXRange[1] = 0.0;
66 
67  fTitle = TString("");
68  fXaxisTitle = TString("");
69 
71 
72  fImp = nullptr;
73  fBar = nullptr;
74  fPopupMain = nullptr;
75 }
76 
77 //---------------------------------------------------------------------------
93 PFourierCanvas::PFourierCanvas(std::vector<PFourier*> &fourier, PIntVector dataSetTag, const Char_t* title,
94  const Bool_t showAverage, const Bool_t showAveragePerDataSet,
95  const Int_t fourierPlotOpt, Double_t fourierXrange[], Double_t phase,
96  Int_t wtopx, Int_t wtopy, Int_t ww, Int_t wh,
97  const Bool_t batch) :
98  fBatchMode(batch), fAveragedView(showAverage), fAveragedViewPerDataSet(showAveragePerDataSet),
99  fDataSetTag(dataSetTag), fCurrentPlotView(fourierPlotOpt), fTitle(title), fFourier(fourier),
100  fCurrentFourierPhase(phase)
101 {
102  fInitialXRange[0] = fourierXrange[0];
103  fInitialXRange[1] = fourierXrange[1];
104 
105  fTimeout = 0;
106 
107  fValid = false;
108 
109  // generate fMarkerList and fColorList, since they are not provided
110  TRandom rand;
111  Int_t style, color;
112  for (UInt_t i=0; i<fourier.size(); i++) {
113  rand.SetSeed(i);
114  style = 20+static_cast<Int_t>(rand.Integer(10));
115  fMarkerList.push_back(style);
116  color = TColor::GetColor(static_cast<Int_t>(rand.Integer(255)), static_cast<Int_t>(rand.Integer(255)), static_cast<Int_t>(rand.Integer(255)));
117  fColorList.push_back(color);
118  }
119 
120  CreateXaxisTitle();
121  CreateStyle();
122  InitFourierDataSets();
123  InitFourierCanvas(fTitle, wtopx, wtopy, ww, wh);
124 
125  gStyle->SetHistMinimumZero(kTRUE); // needed to enforce proper bar option handling
126 }
127 
128 //---------------------------------------------------------------------------
146 PFourierCanvas::PFourierCanvas(std::vector<PFourier*> &fourier, PIntVector dataSetTag, const Char_t* title,
147  const Bool_t showAverage, const Bool_t showAveragePerDataSet,
148  const Int_t fourierPlotOpt, Double_t fourierXrange[], Double_t phase,
149  Int_t wtopx, Int_t wtopy, Int_t ww, Int_t wh,
150  const PIntVector markerList, const PIntVector colorList, const Bool_t batch) :
151  fBatchMode(batch), fAveragedView(showAverage), fAveragedViewPerDataSet(showAveragePerDataSet),
152  fDataSetTag(dataSetTag), fCurrentPlotView(fourierPlotOpt), fTitle(title), fFourier(fourier),
153  fCurrentFourierPhase(phase), fMarkerList(markerList), fColorList(colorList)
154 {
155  fInitialXRange[0] = fourierXrange[0];
156  fInitialXRange[1] = fourierXrange[1];
157 
158  fTimeout = 0;
159 
160  fValid = false;
161 
162  // generate fMarkerList and fColorList, since they are not provided
163  TRandom rand;
164  Int_t style, color;
165  for (UInt_t i=static_cast<UInt_t>(fMarkerList.size()); i<fourier.size(); i++) {
166  rand.SetSeed(i);
167  style = 20+static_cast<Int_t>(rand.Integer(10));
168  fMarkerList.push_back(style);
169  }
170  for (UInt_t i=static_cast<UInt_t>(fColorList.size()); i<fourier.size(); i++) {
171  rand.SetSeed(i);
172  color = TColor::GetColor(static_cast<Int_t>(rand.Integer(255)), static_cast<Int_t>(rand.Integer(255)), static_cast<Int_t>(rand.Integer(255)));
173  fColorList.push_back(color);
174  }
175 
176  CreateXaxisTitle();
177  CreateStyle();
178  InitFourierDataSets();
179  InitFourierCanvas(fTitle, wtopx, wtopy, ww, wh);
180 
181  gStyle->SetHistMinimumZero(kTRUE); // needed to enforce proper bar option handling
182 }
183 
184 //--------------------------------------------------------------------------
185 // Done (SIGNAL)
186 //--------------------------------------------------------------------------
193 {
194  Emit("Done(Int_t)", status);
195 }
196 
197 //--------------------------------------------------------------------------
198 // HandleCmdKey (SLOT)
199 //--------------------------------------------------------------------------
215 void PFourierCanvas::HandleCmdKey(Int_t event, Int_t x, Int_t y, TObject *selected)
216 {
217  if (event != kKeyPress)
218  return;
219 
220  if (fBatchMode)
221  return;
222 
223  if (x == 'q') { // quit
224  Done(0);
225  } else if (x == 'u') { // unzoom
227  PlotAverage();
228  else
229  PlotFourier();
230  } else if (x == 'a') { // toggle between average view and single histo view
231  // toggle average view flag
233  // unset average per data set view flag
234  fAveragedViewPerDataSet = false;
235  // update menu
236  if (fAveragedView) {
237  fPopupMain->CheckEntry(P_MENU_ID_AVERAGE);
239  HandleAverage();
240  PlotAverage();
241  } else {
242  fPopupMain->UnCheckEntry(P_MENU_ID_AVERAGE);
244  CleanupAverage();
245  PlotFourier();
246  }
247  } else if (x == 'd') { // toggle between average view per data set and single histo view
248  // toggle average per data set view flag
250  // unset average view flag
251  fAveragedView = false;
252  // update menu
255  fPopupMain->UnCheckEntry(P_MENU_ID_AVERAGE);
256  HandleAverage();
257  PlotAverage();
258  } else {
260  fPopupMain->UnCheckEntry(P_MENU_ID_AVERAGE);
261  CleanupAverage();
262  PlotFourier();
263  }
264  } else if (x == 'c') {
265  Int_t state = fFourierPad->GetCrosshair();
266  if (state == 0) {
267  fMainCanvas->ToggleEventStatus();
268  fFourierPad->SetCrosshair(2);
269  } else {
270  fMainCanvas->ToggleEventStatus();
271  fFourierPad->SetCrosshair(0);
272  }
273  fMainCanvas->Update();
274  } else if (x == '+') { // increment phase (Fourier real/imag)
276  } else if (x == '-') { // decrement phase (Fourier real/imag)
278  }
279 }
280 
281 //--------------------------------------------------------------------------
282 // HandleMenuPopup (SLOT)
283 //--------------------------------------------------------------------------
290 {
291  if (fBatchMode)
292  return;
293 
295  // uncheck fourier popup items
296  fPopupFourier->UnCheckEntries();
299  if (!fAveragedView) {
300  PlotFourier();
301  } else {
302  HandleAverage();
303  PlotAverage();
304  }
305  } else if (id == P_MENU_ID_FOURIER+P_MENU_ID_FOURIER_IMAG) {
306  fPopupFourier->UnCheckEntries();
309  if (!fAveragedView) {
310  PlotFourier();
311  } else {
312  HandleAverage();
313  PlotAverage();
314  }
316  fPopupFourier->UnCheckEntries();
319  if (!fAveragedView) {
320  PlotFourier();
321  } else {
322  HandleAverage();
323  PlotAverage();
324  }
325  } else if (id == P_MENU_ID_FOURIER+P_MENU_ID_FOURIER_PWR) {
326  fPopupFourier->UnCheckEntries();
329  if (!fAveragedView) {
330  PlotFourier();
331  } else {
332  HandleAverage();
333  PlotAverage();
334  }
335  } else if (id == P_MENU_ID_FOURIER+P_MENU_ID_FOURIER_PHASE) {
336  fPopupFourier->UnCheckEntries();
339  if (!fAveragedView) {
340  PlotFourier();
341  } else {
342  HandleAverage();
343  PlotAverage();
344  }
346  fPopupFourier->UnCheckEntries();
349  if (!fAveragedView) {
350  PlotFourier();
351  } else {
352  HandleAverage();
353  PlotAverage();
354  }
359  } else if (id == P_MENU_ID_AVERAGE) {
360  // toggle average view flag
362  // unset average per data set view flag
363  fAveragedViewPerDataSet = false;
364  // update menu
365  if (fAveragedView) {
366  fPopupMain->CheckEntry(P_MENU_ID_AVERAGE);
368  HandleAverage();
369  PlotAverage();
370  } else {
371  fPopupMain->UnCheckEntry(P_MENU_ID_AVERAGE);
373  CleanupAverage();
374  PlotFourier();
375  }
376  } else if (id == P_MENU_ID_AVERAGE_PER_DATA_SET) {
377  // toggle average per data set view flag
379  // unset average view flag
380  fAveragedView = false;
381  // update menu
384  fPopupMain->UnCheckEntry(P_MENU_ID_AVERAGE);
385  HandleAverage();
386  PlotAverage();
387  } else {
389  fPopupMain->UnCheckEntry(P_MENU_ID_AVERAGE);
390  CleanupAverage();
391  PlotFourier();
392  }
393  } else if (id == P_MENU_ID_EXPORT_DATA) {
394  static TString dir(".");
395  TGFileInfo fi;
396  fi.fFileTypes = gFiletypes;
397  fi.fIniDir = StrDup(dir);
398  fi.fOverwrite = true;
399  new TGFileDialog(nullptr, fImp, kFDSave, &fi);
400  if (fi.fFilename && strlen(fi.fFilename)) {
401  ExportData(fi.fFilename);
402  }
403  }
404 }
405 
406 //--------------------------------------------------------------------------
407 // LastCanvasClosed (SLOT)
408 //--------------------------------------------------------------------------
414 {
415  if (gROOT->GetListOfCanvases()->IsEmpty()) {
416  Done(0);
417  }
418 }
419 
420 //--------------------------------------------------------------------------
421 // UpdateFourierPad (public)
422 //--------------------------------------------------------------------------
427 {
428  if (!fValid)
429  return;
430 
432  PlotAverage();
433  else
434  PlotFourier();
435 
436  fFourierPad->Draw();
437  fMainCanvas->cd();
438  fMainCanvas->Update();
439 }
440 
441 //--------------------------------------------------------------------------
442 // UpdateInfoPad (public)
443 //--------------------------------------------------------------------------
448 {
449  if (!fValid)
450  return;
451 
452  // write header line
453  TDatime dt;
454  Char_t dtStr[128];
455  strncpy(dtStr, dt.AsSQLString(), sizeof(dtStr));
456  TString str("musrFT: ");
457  str += dtStr;
458  fInfoPad->SetHeader(str);
459 
460  Char_t title[1024];
461  for (UInt_t i=0; i<fFourier.size(); i++) {
462  strncpy(title, fFourier[i]->GetDataTitle(), sizeof(title));
463  // add entry
464  fInfoPad->AddEntry(fFourierHistos[i].dataFourierRe, title, "p");
465  }
466 
467  fInfoPad->Draw();
468  fMainCanvas->cd();
469  fMainCanvas->Update();
470 }
471 
472 //--------------------------------------------------------------------------
473 // SetTimeout (public)
474 //--------------------------------------------------------------------------
481 {
482  fTimeout = timeout;
483 
484  if (fTimeout <= 0)
485  return;
486 
487  fTimeoutTimer.reset(new TTimer());
488 
489  fTimeoutTimer->Connect("Timeout()", "PFourierCanvas", this, "Done()");
490 
491  fTimeoutTimer->Start(1000*fTimeout, kTRUE);
492 }
493 
494 //--------------------------------------------------------------------------
495 // SaveGraphicsAndQuit
496 //--------------------------------------------------------------------------
502 void PFourierCanvas::SaveGraphicsAndQuit(const Char_t *fileName)
503 {
504  std::cout << std::endl << ">> SaveGraphicsAndQuit: will dump the canvas into a graphics output file: " << fileName << " ..." << std::endl;
505 
506  fMainCanvas->SaveAs(fileName);
507 
508  Done(0);
509 }
510 
511 //--------------------------------------------------------------------------
512 // ExportData
513 //--------------------------------------------------------------------------
517 void PFourierCanvas::ExportData(const Char_t *pathFileName)
518 {
519  TString pfn("");
520 
521  if (pathFileName) { // path file name provided
522  pfn = TString(pathFileName);
523  } else { // path file name NOT provided, generate a default path file name
524  std::cerr << std::endl << ">> PFourierCanvas::ExportData **ERROR** NO path file name provided. Will do nothing." << std::endl;
525  return;
526  }
527 
528  TString xAxis(""), yAxis("");
529  Int_t xMinBin, xMaxBin;
530  if (fAveragedView) {
531  switch (fCurrentPlotView) {
532  case FOURIER_PLOT_REAL:
533  xAxis = fFourierHistos[0].dataFourierRe->GetXaxis()->GetTitle();
534  yAxis = TString("<Real>");
535  xMinBin = fFourierHistos[0].dataFourierRe->GetXaxis()->GetFirst();
536  xMaxBin = fFourierHistos[0].dataFourierRe->GetXaxis()->GetLast();
537  break;
538  case FOURIER_PLOT_IMAG:
539  xAxis = fFourierHistos[0].dataFourierIm->GetXaxis()->GetTitle();
540  yAxis = TString("<Imag>");
541  xMinBin = fFourierHistos[0].dataFourierIm->GetXaxis()->GetFirst();
542  xMaxBin = fFourierHistos[0].dataFourierIm->GetXaxis()->GetLast();
543  break;
544  case FOURIER_PLOT_POWER:
545  xAxis = fFourierHistos[0].dataFourierPwr->GetXaxis()->GetTitle();
546  yAxis = TString("<Power>");
547  xMinBin = fFourierHistos[0].dataFourierPwr->GetXaxis()->GetFirst();
548  xMaxBin = fFourierHistos[0].dataFourierPwr->GetXaxis()->GetLast();
549  break;
550  case FOURIER_PLOT_PHASE:
551  xAxis = fFourierHistos[0].dataFourierPhase->GetXaxis()->GetTitle();
552  yAxis = TString("<Phase>");
553  xMinBin = fFourierHistos[0].dataFourierPhase->GetXaxis()->GetFirst();
554  xMaxBin = fFourierHistos[0].dataFourierPhase->GetXaxis()->GetLast();
555  break;
557  xAxis = fFourierHistos[0].dataFourierPhaseOptReal->GetXaxis()->GetTitle();
558  yAxis = TString("<Phase>");
559  xMinBin = fFourierHistos[0].dataFourierPhaseOptReal->GetXaxis()->GetFirst();
560  xMaxBin = fFourierHistos[0].dataFourierPhaseOptReal->GetXaxis()->GetLast();
561  break;
562  default:
563  xAxis = TString("??");
564  yAxis = TString("??");
565  xMinBin = 0;
566  xMaxBin = 0;
567  break;
568  }
569  } else {
570  switch (fCurrentPlotView) {
571  case FOURIER_PLOT_REAL:
572  xAxis = fFourierHistos[0].dataFourierRe->GetXaxis()->GetTitle();
573  yAxis = TString("Real");
574  xMinBin = fFourierHistos[0].dataFourierRe->GetXaxis()->GetFirst();
575  xMaxBin = fFourierHistos[0].dataFourierRe->GetXaxis()->GetLast();
576  break;
577  case FOURIER_PLOT_IMAG:
578  xAxis = fFourierHistos[0].dataFourierIm->GetXaxis()->GetTitle();
579  yAxis = TString("Imag");
580  xMinBin = fFourierHistos[0].dataFourierIm->GetXaxis()->GetFirst();
581  xMaxBin = fFourierHistos[0].dataFourierIm->GetXaxis()->GetLast();
582  break;
584  xAxis = fFourierHistos[0].dataFourierRe->GetXaxis()->GetTitle();
585  yAxis = TString("Real+Imag");
586  xMinBin = fFourierHistos[0].dataFourierRe->GetXaxis()->GetFirst();
587  xMaxBin = fFourierHistos[0].dataFourierRe->GetXaxis()->GetLast();
588  break;
589  case FOURIER_PLOT_POWER:
590  xAxis = fFourierHistos[0].dataFourierPwr->GetXaxis()->GetTitle();
591  yAxis = TString("Power");
592  xMinBin = fFourierHistos[0].dataFourierPwr->GetXaxis()->GetFirst();
593  xMaxBin = fFourierHistos[0].dataFourierPwr->GetXaxis()->GetLast();
594  break;
595  case FOURIER_PLOT_PHASE:
596  xAxis = fFourierHistos[0].dataFourierPhase->GetXaxis()->GetTitle();
597  yAxis = TString("Phase");
598  xMinBin = fFourierHistos[0].dataFourierPhase->GetXaxis()->GetFirst();
599  xMaxBin = fFourierHistos[0].dataFourierPhase->GetXaxis()->GetLast();
600  break;
602  xAxis = fFourierHistos[0].dataFourierPhaseOptReal->GetXaxis()->GetTitle();
603  yAxis = TString("Phase");
604  xMinBin = fFourierHistos[0].dataFourierPhaseOptReal->GetXaxis()->GetFirst();
605  xMaxBin = fFourierHistos[0].dataFourierPhaseOptReal->GetXaxis()->GetLast();
606  break;
607  default:
608  xAxis = TString("??");
609  yAxis = TString("??");
610  xMinBin = 0;
611  xMaxBin = 0;
612  break;
613  }
614  }
615 
616  // write data to file
617  std::ofstream fout(pfn.Data(), std::ofstream::out);
618 
619  if (fAveragedView) {
620  // write header
621  fout << "% " << pfn << std::endl;
622  fout << "% averaged data of:" << std::endl;
623  for (UInt_t i=0; i<fFourierHistos.size(); i++) {
624  fout << "% " << fFourierHistos[i].dataFourierRe->GetTitle() << std::endl;
625  }
626  fout << "%------------" << std::endl;
627  fout << "% " << xAxis << ", " << yAxis << std::endl;
628  for (Int_t i=xMinBin; i<xMaxBin; i++) {
629  switch (fCurrentPlotView) {
630  case FOURIER_PLOT_REAL:
631  fout << fFourierAverage[0].dataFourierRe->GetBinCenter(i) << ", " << fFourierAverage[0].dataFourierRe->GetBinContent(i) << std::endl;
632  break;
633  case FOURIER_PLOT_IMAG:
634  fout << fFourierAverage[0].dataFourierIm->GetBinCenter(i) << ", " << fFourierAverage[0].dataFourierIm->GetBinContent(i) << std::endl;
635  break;
636  case FOURIER_PLOT_POWER:
637  fout << fFourierAverage[0].dataFourierPwr->GetBinCenter(i) << ", " << fFourierAverage[0].dataFourierPwr->GetBinContent(i) << std::endl;
638  break;
639  case FOURIER_PLOT_PHASE:
640  fout << fFourierAverage[0].dataFourierPhase->GetBinCenter(i) << ", " << fFourierAverage[0].dataFourierPhase->GetBinContent(i) << std::endl;
641  break;
643  fout << fFourierAverage[0].dataFourierPhaseOptReal->GetBinCenter(i) << ", " << fFourierAverage[0].dataFourierPhaseOptReal->GetBinContent(i) << std::endl;
644  break;
645  default:
646  break;
647  }
648  }
649  } else {
650  // write header
651  fout << "% " << pfn << std::endl;
652  fout << "% data of:" << std::endl;
653  for (UInt_t i=0; i<fFourierHistos.size(); i++) {
654  fout << "% " << fFourierHistos[i].dataFourierRe->GetTitle() << std::endl;
655  }
656  fout << "%------------" << std::endl;
657  fout << "% ";
658  for (UInt_t i=0; i<fFourierHistos.size()-1; i++) {
659  fout << xAxis << i << ", " << yAxis << i << ", ";
660  }
661  fout << xAxis << fFourierHistos.size()-1 << ", " << yAxis << fFourierHistos.size()-1 << std::endl;
662 
663  // write data
664  for (Int_t i=xMinBin; i<xMaxBin; i++) {
665  for (UInt_t j=0; j<fFourierHistos.size()-1; j++) {
666  switch (fCurrentPlotView) {
667  case FOURIER_PLOT_REAL:
668  fout << fFourierHistos[j].dataFourierRe->GetBinCenter(i) << ", " << fFourierHistos[j].dataFourierRe->GetBinContent(i) << ", ";
669  break;
670  case FOURIER_PLOT_IMAG:
671  fout << fFourierHistos[j].dataFourierIm->GetBinCenter(i) << ", " << fFourierHistos[j].dataFourierIm->GetBinContent(i) << ", ";
672  break;
674  break;
675  case FOURIER_PLOT_POWER:
676  fout << fFourierHistos[j].dataFourierPwr->GetBinCenter(i) << ", " << fFourierHistos[j].dataFourierPwr->GetBinContent(i) << ", ";
677  break;
678  case FOURIER_PLOT_PHASE:
679  fout << fFourierHistos[j].dataFourierPhase->GetBinCenter(i) << ", " << fFourierHistos[j].dataFourierPhase->GetBinContent(i) << ", ";
680  break;
682  fout << fFourierHistos[j].dataFourierPhaseOptReal->GetBinCenter(i) << ", " << fFourierHistos[j].dataFourierPhaseOptReal->GetBinContent(i) << ", ";
683  break;
684  default:
685  break;
686  }
687  }
688  switch (fCurrentPlotView) {
689  case FOURIER_PLOT_REAL:
690  fout << fFourierHistos[fFourierHistos.size()-1].dataFourierRe->GetBinCenter(i) << ", " << fFourierHistos[fFourierHistos.size()-1].dataFourierRe->GetBinContent(i) << std::endl;
691  break;
692  case FOURIER_PLOT_IMAG:
693  fout << fFourierHistos[fFourierHistos.size()-1].dataFourierIm->GetBinCenter(i) << ", " << fFourierHistos[fFourierHistos.size()-1].dataFourierIm->GetBinContent(i) << std::endl;
694  break;
696  break;
697  case FOURIER_PLOT_POWER:
698  fout << fFourierHistos[fFourierHistos.size()-1].dataFourierPwr->GetBinCenter(i) << ", " << fFourierHistos[fFourierHistos.size()-1].dataFourierPwr->GetBinContent(i) << std::endl;
699  break;
700  case FOURIER_PLOT_PHASE:
701  fout << fFourierHistos[fFourierHistos.size()-1].dataFourierPhase->GetBinCenter(i) << ", " << fFourierHistos[fFourierHistos.size()-1].dataFourierPhase->GetBinContent(i) << std::endl;
702  break;
704  fout << fFourierHistos[fFourierHistos.size()-1].dataFourierPhaseOptReal->GetBinCenter(i) << ", " << fFourierHistos[fFourierHistos.size()-1].dataFourierPhaseOptReal->GetBinContent(i) << std::endl;
705  break;
706  default:
707  break;
708  }
709  }
710  }
711 
712  fout.close();
713 }
714 
715 //--------------------------------------------------------------------------
716 // CreateXaxisTitle (private)
717 //--------------------------------------------------------------------------
722 {
723  switch (fFourier[0]->GetUnitTag()) {
724  case FOURIER_UNIT_GAUSS:
725  fXaxisTitle = TString("Field (Gauss)");
726  break;
727  case FOURIER_UNIT_TESLA:
728  fXaxisTitle = TString("Field (Tesla)");
729  break;
730  case FOURIER_UNIT_FREQ:
731  fXaxisTitle = TString("Frequency (MHz)");
732  break;
733  case FOURIER_UNIT_CYCLES:
734  fXaxisTitle = TString("Angular Frequency (Mc/s)");
735  break;
736  default:
737  fXaxisTitle = TString("??");
738  break;
739  }
740 }
741 
742 //--------------------------------------------------------------------------
743 // CreateStyle (private)
744 //--------------------------------------------------------------------------
749 {
750  TString musrFTStyle("musrFTStyle");
751  fStyle = std::make_unique<TStyle>(musrFTStyle, musrFTStyle);
752  fStyle->SetOptStat(0); // no statistics options
753  fStyle->SetOptTitle(0); // no title
754  fStyle->cd();
755 }
756 
757 //--------------------------------------------------------------------------
758 // InitFourierDataSets (private)
759 //--------------------------------------------------------------------------
765 {
766  // get all the Fourier histos
767  fFourierHistos.resize(fFourier.size());
768  for (UInt_t i=0; i<fFourierHistos.size(); i++) {
769  fFourierHistos[i].dataFourierRe = fFourier[i]->GetRealFourier();
770  fFourierHistos[i].dataFourierIm = fFourier[i]->GetImaginaryFourier();
771  fFourierHistos[i].dataFourierPwr = fFourier[i]->GetPowerFourier();
772  fFourierHistos[i].dataFourierPhase = fFourier[i]->GetPhaseFourier();
774  fFourierHistos[i].dataFourierPhaseOptReal = fFourier[i]->GetPhaseOptRealFourier(fFourierHistos[i].dataFourierRe,
775  fFourierHistos[i].dataFourierIm, fFourierHistos[i].optPhase, 1.0, fInitialXRange[0], fInitialXRange[1]);
776  }
777  }
778 
779  // rescale histo to abs(maximum) == 1
780  Double_t max = 0.0, dval = 0.0;
781  Int_t start = fFourierHistos[0].dataFourierRe->FindBin(fInitialXRange[0]);
782  Int_t end = fFourierHistos[0].dataFourierRe->FindBin(fInitialXRange[1]);
783  // real
784  for (UInt_t i=0; i<fFourierHistos.size(); i++) {
785  for (Int_t j=start; j<=end; j++) {
786  dval = fFourierHistos[i].dataFourierRe->GetBinContent(j);
787  if (fabs(dval) > max)
788  max = dval;
789  }
790  }
791  for (UInt_t i=0; i<fFourierHistos.size(); i++) {
792  for (Int_t j=1; j<fFourierHistos[i].dataFourierRe->GetNbinsX(); j++) {
793  fFourierHistos[i].dataFourierRe->SetBinContent(j, fFourierHistos[i].dataFourierRe->GetBinContent(j)/fabs(max));
794  }
795  }
796 
797  // imaginary
798  for (UInt_t i=0; i<fFourierHistos.size(); i++) {
799  for (Int_t j=start; j<=end; j++) {
800  dval = fFourierHistos[i].dataFourierIm->GetBinContent(j);
801  if (fabs(dval) > max)
802  max = dval;
803  }
804  }
805  for (UInt_t i=0; i<fFourierHistos.size(); i++) {
806  for (Int_t j=1; j<fFourierHistos[i].dataFourierIm->GetNbinsX(); j++) {
807  fFourierHistos[i].dataFourierIm->SetBinContent(j, fFourierHistos[i].dataFourierIm->GetBinContent(j)/fabs(max));
808  }
809  }
810 
811  // power
812  max = 0.0;
813  for (UInt_t i=0; i<fFourierHistos.size(); i++) {
814  for (Int_t j=start; j<=end; j++) {
815  dval = fFourierHistos[i].dataFourierPwr->GetBinContent(j);
816  if (fabs(dval) > max)
817  max = dval;
818  }
819  }
820  for (UInt_t i=0; i<fFourierHistos.size(); i++) {
821  for (Int_t j=1; j<fFourierHistos[i].dataFourierPwr->GetNbinsX(); j++) {
822  fFourierHistos[i].dataFourierPwr->SetBinContent(j, fFourierHistos[i].dataFourierPwr->GetBinContent(j)/fabs(max));
823  }
824  }
825 
826  // phase
827  max = 0.0;
828  for (UInt_t i=0; i<fFourierHistos.size(); i++) {
829  for (Int_t j=start; j<=end; j++) {
830  dval = fFourierHistos[i].dataFourierPhase->GetBinContent(j);
831  if (fabs(dval) > max)
832  max = dval;
833  }
834  }
835  for (UInt_t i=0; i<fFourierHistos.size(); i++) {
836  for (Int_t j=1; j<fFourierHistos[i].dataFourierPhase->GetNbinsX(); j++) {
837  fFourierHistos[i].dataFourierPhase->SetBinContent(j, fFourierHistos[i].dataFourierPhase->GetBinContent(j)/fabs(max));
838  }
839  }
840 
842  // phase opt real
843  for (UInt_t i=0; i<fFourierHistos.size(); i++) {
844  for (Int_t j=start; j<=end; j++) {
845  dval = fFourierHistos[i].dataFourierPhaseOptReal->GetBinContent(j);
846  if (fabs(dval) > max)
847  max = dval;
848  }
849  }
850  for (UInt_t i=0; i<fFourierHistos.size(); i++) {
851  for (Int_t j=1; j<fFourierHistos[i].dataFourierPhaseOptReal->GetNbinsX(); j++) {
852  fFourierHistos[i].dataFourierPhaseOptReal->SetBinContent(j, fFourierHistos[i].dataFourierPhaseOptReal->GetBinContent(j)/fabs(max));
853  }
854  }
855  }
856 
857  // set the marker and line color
858  for (UInt_t i=0; i<fFourierHistos.size(); i++) {
859  fFourierHistos[i].dataFourierRe->SetMarkerColor(fColorList[i]);
860  fFourierHistos[i].dataFourierRe->SetLineColor(fColorList[i]);
861  fFourierHistos[i].dataFourierIm->SetMarkerColor(fColorList[i]);
862  fFourierHistos[i].dataFourierIm->SetLineColor(fColorList[i]);
863  fFourierHistos[i].dataFourierPwr->SetMarkerColor(fColorList[i]);
864  fFourierHistos[i].dataFourierPwr->SetLineColor(fColorList[i]);
865  fFourierHistos[i].dataFourierPhase->SetMarkerColor(fColorList[i]);
866  fFourierHistos[i].dataFourierPhase->SetLineColor(fColorList[i]);
868  fFourierHistos[i].dataFourierPhaseOptReal->SetMarkerColor(fColorList[i]);
869  fFourierHistos[i].dataFourierPhaseOptReal->SetLineColor(fColorList[i]);
870  }
871  }
872 
873  // set the marker symbol and size
874  for (UInt_t i=0; i<fFourierHistos.size(); i++) {
875  fFourierHistos[i].dataFourierRe->SetMarkerStyle(fMarkerList[i]);
876  fFourierHistos[i].dataFourierRe->SetMarkerSize(0.7);
877  fFourierHistos[i].dataFourierIm->SetMarkerStyle(fMarkerList[i]);
878  fFourierHistos[i].dataFourierIm->SetMarkerSize(0.7);
879  fFourierHistos[i].dataFourierPwr->SetMarkerStyle(fMarkerList[i]);
880  fFourierHistos[i].dataFourierPwr->SetMarkerSize(0.7);
881  fFourierHistos[i].dataFourierPhase->SetMarkerStyle(fMarkerList[i]);
882  fFourierHistos[i].dataFourierPhase->SetMarkerSize(0.7);
884  fFourierHistos[i].dataFourierPhaseOptReal->SetMarkerStyle(fMarkerList[i]);
885  fFourierHistos[i].dataFourierPhaseOptReal->SetMarkerSize(0.7);
886  }
887  }
888 
889  // initialize average histos
890  CleanupAverage();
891 }
892 
893 //--------------------------------------------------------------------------
894 // InitFourierCanvas (private)
895 //--------------------------------------------------------------------------
905 void PFourierCanvas::InitFourierCanvas(const Char_t* title, Int_t wtopx, Int_t wtopy, Int_t ww, Int_t wh)
906 {
907  fImp = nullptr;
908  fBar = nullptr;
909  fPopupMain = nullptr;
910 
911  // invoke canvas
912  TString canvasName = TString("fMainCanvas");
913  fMainCanvas = std::make_unique<TCanvas>(canvasName.Data(), title, wtopx, wtopy, ww, wh);
914 
915  // add canvas menu if not in batch mode
916  if (!fBatchMode) {
917  fImp = static_cast<TRootCanvas*>(fMainCanvas->GetCanvasImp());
918  fBar = fImp->GetMenuBar();
919  fPopupMain = fBar->AddPopup("MusrFT");
920 
921  fPopupFourier = std::make_unique<TGPopupMenu>();
922 
923  fPopupMain->AddPopup("&Fourier", fPopupFourier.get());
927  fPopupFourier->AddEntry("Show Power", P_MENU_ID_FOURIER+P_MENU_ID_FOURIER_PWR);
929  fPopupFourier->AddEntry("Show Phase Opt Fourier", P_MENU_ID_FOURIER+P_MENU_ID_FOURIER_PHASE_OPT_REAL);
930  fPopupFourier->AddSeparator();
935 
936  switch (fCurrentPlotView) {
937  case FOURIER_PLOT_REAL:
939  break;
940  case FOURIER_PLOT_IMAG:
942  break;
945  break;
946  case FOURIER_PLOT_POWER:
948  break;
949  case FOURIER_PLOT_PHASE:
951  break;
954  break;
955  default:
956  break;
957  }
958 
959  fPopupMain->AddEntry("Average", P_MENU_ID_AVERAGE);
960  if (fAveragedView)
961  fPopupMain->CheckEntry(P_MENU_ID_AVERAGE);
962  fPopupMain->AddEntry("Average per Data Set", P_MENU_ID_AVERAGE_PER_DATA_SET);
965  fPopupMain->AddSeparator();
966 
967  fPopupMain->AddEntry("Export Data", P_MENU_ID_EXPORT_DATA);
968  fBar->MapSubwindows();
969  fBar->Layout();
970 
971  fPopupMain->Connect("TGPopupMenu", "Activated(Int_t)", "PFourierCanvas", this, "HandleMenuPopup(Int_t)");
972  }
973 
974  // divide the canvas into sub pads
975  // title pad
976  fTitlePad = std::make_unique<TPaveText>(0.0, YTITLE, 1.0, 1.0, "NDC");
977 
978  fTitlePad->SetFillColor(TColor::GetColor(255,255,255));
979  fTitlePad->SetTextAlign(12); // middle, left
980  fTitlePad->AddText(title);
981  fTitlePad->Draw();
982 
983  // fourier pad
984  fFourierPad = std::make_unique<TPad>("fFourierPad", "fFourierPad", 0.0, YINFO, 1.0, YTITLE);
985 
986  fFourierPad->SetFillColor(TColor::GetColor(255,255,255));
987  fFourierPad->Draw();
988 
989  // info pad
990  fInfoPad = std::make_unique<TLegend>(0.0, 0.0, 1.0, YINFO, "NDC");
991 
992  fInfoPad->SetFillColor(TColor::GetColor(255,255,255));
993  fInfoPad->SetTextAlign(12); // middle, left
994 
995  fValid = true;
996 
997  if ((fFourier.size() != fDataSetTag.size()) && fAveragedViewPerDataSet) {
998  fValid = false;
999  std::cerr << std::endl << "PFourierCanvas::PFourierCanvas: **PANIC ERROR**: # Fourier != # Data Set Tags." << std::endl;
1000  }
1001 
1002  fMainCanvas->cd();
1003 
1004  fMainCanvas->Show();
1005 
1006  fMainCanvas->Connect("ProcessedEvent(Int_t,Int_t,Int_t,TObject*)", "PFourierCanvas",
1007  this, "HandleCmdKey(Int_t,Int_t,Int_t,TObject*)");
1008 }
1009 
1010 //--------------------------------------------------------------------------
1011 // CleanupAverage (private)
1012 //--------------------------------------------------------------------------
1017 {
1018  for (UInt_t i=0; i<fFourierAverage.size(); i++) {
1019  if (fFourierAverage[i].dataFourierRe != nullptr) {
1020  delete fFourierAverage[i].dataFourierRe;
1021  fFourierAverage[i].dataFourierRe = nullptr;
1022  }
1023  if (fFourierAverage[i].dataFourierIm) {
1024  delete fFourierAverage[i].dataFourierIm;
1025  fFourierAverage[i].dataFourierIm = nullptr;
1026  }
1027  if (fFourierAverage[i].dataFourierPwr) {
1028  delete fFourierAverage[i].dataFourierPwr;
1029  fFourierAverage[i].dataFourierPwr = nullptr;
1030  }
1031  if (fFourierAverage[i].dataFourierPhase) {
1032  delete fFourierAverage[i].dataFourierPhase;
1033  fFourierAverage[i].dataFourierPhase = nullptr;
1034  }
1035  if (fFourierAverage[i].dataFourierPhaseOptReal) {
1036  delete fFourierAverage[i].dataFourierPhaseOptReal;
1037  fFourierAverage[i].dataFourierPhaseOptReal = nullptr;
1038  }
1039  }
1040  fFourierAverage.clear();
1041 }
1042 
1043 //--------------------------------------------------------------------------
1044 // HandleAverage (private)
1045 //--------------------------------------------------------------------------
1050 {
1051  if (fFourierHistos.size() == 0)
1052  return;
1053 
1054  CleanupAverage();
1055 
1056  TString name("");
1057  Double_t dval=0.0;
1058 
1059  Bool_t phaseOptRealPresent = false;
1060  if (fFourierHistos[0].dataFourierPhaseOptReal != nullptr)
1061  phaseOptRealPresent = true;
1062 
1063  // check if ALL data shall be averaged
1064  if (fAveragedView) {
1065  fFourierAverage.resize(1);
1066 
1067  // create average histograms
1068  name = TString(fFourierHistos[0].dataFourierRe->GetTitle()) + "_avg";
1069  fFourierAverage[0].dataFourierRe = new TH1F(name, name, fFourierHistos[0].dataFourierRe->GetNbinsX(),
1070  fFourierHistos[0].dataFourierRe->GetXaxis()->GetXmin(),
1071  fFourierHistos[0].dataFourierRe->GetXaxis()->GetXmax());
1072 
1073  name = TString(fFourierHistos[0].dataFourierIm->GetTitle()) + "_avg";
1074  fFourierAverage[0].dataFourierIm = new TH1F(name, name, fFourierHistos[0].dataFourierIm->GetNbinsX(),
1075  fFourierHistos[0].dataFourierIm->GetXaxis()->GetXmin(),
1076  fFourierHistos[0].dataFourierIm->GetXaxis()->GetXmax());
1077 
1078  name = TString(fFourierHistos[0].dataFourierPwr->GetTitle()) + "_avg";
1079  fFourierAverage[0].dataFourierPwr = new TH1F(name, name, fFourierHistos[0].dataFourierPwr->GetNbinsX(),
1080  fFourierHistos[0].dataFourierPwr->GetXaxis()->GetXmin(),
1081  fFourierHistos[0].dataFourierPwr->GetXaxis()->GetXmax());
1082 
1083  name = TString(fFourierHistos[0].dataFourierPhase->GetTitle()) + "_avg";
1084  fFourierAverage[0].dataFourierPhase = new TH1F(name, name, fFourierHistos[0].dataFourierPhase->GetNbinsX(),
1085  fFourierHistos[0].dataFourierPhase->GetXaxis()->GetXmin(),
1086  fFourierHistos[0].dataFourierPhase->GetXaxis()->GetXmax());
1087 
1088  if (phaseOptRealPresent) {
1089  name = TString(fFourierHistos[0].dataFourierPhaseOptReal->GetTitle()) + "_avg";
1090  fFourierAverage[0].dataFourierPhaseOptReal = new TH1F(name, name, fFourierHistos[0].dataFourierPhaseOptReal->GetNbinsX(),
1091  fFourierHistos[0].dataFourierPhaseOptReal->GetXaxis()->GetXmin(),
1092  fFourierHistos[0].dataFourierPhaseOptReal->GetXaxis()->GetXmax());
1093  }
1094 
1095  // real average
1096  for (Int_t j=0; j<fFourierHistos[0].dataFourierRe->GetNbinsX(); j++) {
1097  dval = 0.0;
1098  for (UInt_t i=0; i<fFourierHistos.size(); i++) {
1099  if (j < fFourierHistos[i].dataFourierRe->GetNbinsX())
1100  dval += GetInterpolatedValue(fFourierHistos[i].dataFourierRe, fFourierHistos[0].dataFourierRe->GetBinCenter(j));
1101  }
1102  fFourierAverage[0].dataFourierRe->SetBinContent(j, dval/fFourierHistos.size());
1103  }
1104  // set marker color, line color, maker size, marker type
1105  fFourierAverage[0].dataFourierRe->SetMarkerColor(kBlack);
1106  fFourierAverage[0].dataFourierRe->SetLineColor(kBlack);
1107  fFourierAverage[0].dataFourierRe->SetMarkerSize(0.8);
1108  fFourierAverage[0].dataFourierRe->SetMarkerStyle(22); // closed up triangle
1109 
1110  // imaginary average
1111  for (Int_t j=0; j<fFourierHistos[0].dataFourierIm->GetNbinsX(); j++) {
1112  dval = 0.0;
1113  for (UInt_t i=0; i<fFourierHistos.size(); i++) {
1114  if (j < fFourierHistos[i].dataFourierIm->GetNbinsX())
1115  dval += GetInterpolatedValue(fFourierHistos[i].dataFourierIm, fFourierHistos[0].dataFourierIm->GetBinCenter(j));
1116  }
1117  fFourierAverage[0].dataFourierIm->SetBinContent(j, dval/fFourierHistos.size());
1118  }
1119  // set marker color, line color, maker size, marker type
1120  fFourierAverage[0].dataFourierIm->SetMarkerColor(kBlack);
1121  fFourierAverage[0].dataFourierIm->SetLineColor(kBlack);
1122  fFourierAverage[0].dataFourierIm->SetMarkerSize(0.8);
1123  fFourierAverage[0].dataFourierIm->SetMarkerStyle(22); // closed up triangle
1124 
1125  // power average
1126  for (Int_t j=0; j<fFourierHistos[0].dataFourierPwr->GetNbinsX(); j++) {
1127  dval = 0.0;
1128  for (UInt_t i=0; i<fFourierHistos.size(); i++) {
1129  if (j < fFourierHistos[i].dataFourierPwr->GetNbinsX())
1130  dval += GetInterpolatedValue(fFourierHistos[i].dataFourierPwr, fFourierHistos[0].dataFourierPwr->GetBinCenter(j));
1131  }
1132  fFourierAverage[0].dataFourierPwr->SetBinContent(j, dval/fFourierHistos.size());
1133  }
1134  // set marker color, line color, maker size, marker type
1135  fFourierAverage[0].dataFourierPwr->SetMarkerColor(kBlack);
1136  fFourierAverage[0].dataFourierPwr->SetLineColor(kBlack);
1137  fFourierAverage[0].dataFourierPwr->SetMarkerSize(0.8);
1138  fFourierAverage[0].dataFourierPwr->SetMarkerStyle(22); // closed up triangle
1139 
1140  // phase average
1141  for (Int_t j=0; j<fFourierHistos[0].dataFourierPhase->GetNbinsX(); j++) {
1142  dval = 0.0;
1143  for (UInt_t i=0; i<fFourierHistos.size(); i++) {
1144  if (j < fFourierHistos[i].dataFourierPhase->GetNbinsX())
1145  dval += GetInterpolatedValue(fFourierHistos[i].dataFourierPhase, fFourierHistos[0].dataFourierPhase->GetBinCenter(j));
1146  }
1147  fFourierAverage[0].dataFourierPhase->SetBinContent(j, dval/fFourierHistos.size());
1148  }
1149  // set marker color, line color, maker size, marker type
1150  fFourierAverage[0].dataFourierPhase->SetMarkerColor(kBlack);
1151  fFourierAverage[0].dataFourierPhase->SetLineColor(kBlack);
1152  fFourierAverage[0].dataFourierPhase->SetMarkerSize(0.8);
1153  fFourierAverage[0].dataFourierPhase->SetMarkerStyle(22);
1154 
1155  if (phaseOptRealPresent) {
1156  // phase optimised real average
1157  for (Int_t j=0; j<fFourierHistos[0].dataFourierPhaseOptReal->GetNbinsX(); j++) {
1158  dval = 0.0;
1159  for (UInt_t i=0; i<fFourierHistos.size(); i++) {
1160  if (j < fFourierHistos[i].dataFourierPhaseOptReal->GetNbinsX())
1161  dval += GetInterpolatedValue(fFourierHistos[i].dataFourierPhaseOptReal, fFourierHistos[0].dataFourierPhaseOptReal->GetBinCenter(j));
1162  }
1163  fFourierAverage[0].dataFourierPhaseOptReal->SetBinContent(j, dval/fFourierHistos.size());
1164  }
1165  // set marker color, line color, maker size, marker type
1166  fFourierAverage[0].dataFourierPhaseOptReal->SetMarkerColor(kBlack);
1167  fFourierAverage[0].dataFourierPhaseOptReal->SetLineColor(kBlack);
1168  fFourierAverage[0].dataFourierPhaseOptReal->SetMarkerSize(0.8);
1169  fFourierAverage[0].dataFourierPhaseOptReal->SetMarkerStyle(22);
1170  }
1171  }
1172 
1173  // check if per data set shall be averaged
1175  // check what size is required
1176  UInt_t count = 1;
1177  Int_t currentTag = fDataSetTag[0];
1178  for (UInt_t i=1; i<fDataSetTag.size(); i++) {
1179  if (fDataSetTag[i] != currentTag) {
1180  currentTag = fDataSetTag[i];
1181  count++;
1182  }
1183  }
1184  fFourierAverage.resize(count);
1185 
1186  Int_t start=0, end=0;
1187  for (UInt_t i=0; i<fFourierAverage.size(); i++) {
1188  // get data set range
1189  count = 0;
1190  currentTag = fDataSetTag[0];
1191  start = -1, end = -1;
1192  for (UInt_t j=0; j<fDataSetTag.size(); j++) {
1193  if ((count == i) && (start == -1)) {
1194  if (j > 0)
1195  start = j-1;
1196  else
1197  start = 0;
1198  }
1199  if (currentTag != fDataSetTag[j]) {
1200  if (count == i) {
1201  end = j-1;
1202  break;
1203  }
1204  count++;
1205  currentTag = fDataSetTag[j];
1206  }
1207  }
1208  if (start == -1)
1209  start = fDataSetTag.size()-1;
1210  if (end == -1)
1211  end = fDataSetTag.size()-1;
1212 
1213  // create average histograms
1214  name = TString(fFourierHistos[start].dataFourierRe->GetTitle()) + "_avg";
1215  fFourierAverage[i].dataFourierRe = new TH1F(name, name, fFourierHistos[0].dataFourierRe->GetNbinsX(),
1216  fFourierHistos[0].dataFourierRe->GetXaxis()->GetXmin(),
1217  fFourierHistos[0].dataFourierRe->GetXaxis()->GetXmax());
1218 
1219  name = TString(fFourierHistos[start].dataFourierIm->GetTitle()) + "_avg";
1220  fFourierAverage[i].dataFourierIm = new TH1F(name, name, fFourierHistos[0].dataFourierIm->GetNbinsX(),
1221  fFourierHistos[0].dataFourierIm->GetXaxis()->GetXmin(),
1222  fFourierHistos[0].dataFourierIm->GetXaxis()->GetXmax());
1223 
1224  name = TString(fFourierHistos[start].dataFourierPwr->GetTitle()) + "_avg";
1225  fFourierAverage[i].dataFourierPwr = new TH1F(name, name, fFourierHistos[0].dataFourierPwr->GetNbinsX(),
1226  fFourierHistos[0].dataFourierPwr->GetXaxis()->GetXmin(),
1227  fFourierHistos[0].dataFourierPwr->GetXaxis()->GetXmax());
1228 
1229  name = TString(fFourierHistos[start].dataFourierPhase->GetTitle()) + "_avg";
1230  fFourierAverage[i].dataFourierPhase = new TH1F(name, name, fFourierHistos[0].dataFourierPhase->GetNbinsX(),
1231  fFourierHistos[0].dataFourierPhase->GetXaxis()->GetXmin(),
1232  fFourierHistos[0].dataFourierPhase->GetXaxis()->GetXmax());
1233 
1234  if (phaseOptRealPresent) {
1235  name = TString(fFourierHistos[start].dataFourierPhaseOptReal->GetTitle()) + "_avg";
1236  fFourierAverage[i].dataFourierPhaseOptReal = new TH1F(name, name, fFourierHistos[0].dataFourierPhaseOptReal->GetNbinsX(),
1237  fFourierHistos[0].dataFourierPhaseOptReal->GetXaxis()->GetXmin(),
1238  fFourierHistos[0].dataFourierPhaseOptReal->GetXaxis()->GetXmax());
1239  }
1240 
1241  // real average
1242  for (Int_t j=0; j<fFourierHistos[0].dataFourierRe->GetNbinsX(); j++) {
1243  dval = 0.0;
1244  for (Int_t k=start; k<=end; k++) {
1245  if (j < fFourierHistos[k].dataFourierRe->GetNbinsX())
1246  dval += GetInterpolatedValue(fFourierHistos[k].dataFourierRe, fFourierHistos[0].dataFourierRe->GetBinCenter(j));
1247  }
1248  fFourierAverage[i].dataFourierRe->SetBinContent(j, dval/(end-start+1));
1249  }
1250  // set marker color, line color, maker size, marker type
1251  fFourierAverage[i].dataFourierRe->SetMarkerColor(fColorList[i]);
1252  fFourierAverage[i].dataFourierRe->SetLineColor(fColorList[i]);
1253  fFourierAverage[i].dataFourierRe->SetMarkerSize(0.8);
1254  fFourierAverage[i].dataFourierRe->SetMarkerStyle(22); // closed up triangle
1255 
1256  // imaginary average
1257  for (Int_t j=0; j<fFourierHistos[0].dataFourierIm->GetNbinsX(); j++) {
1258  dval = 0.0;
1259  for (Int_t k=start; k<=end; k++) {
1260  if (j < fFourierHistos[k].dataFourierIm->GetNbinsX())
1261  dval += GetInterpolatedValue(fFourierHistos[k].dataFourierIm, fFourierHistos[0].dataFourierIm->GetBinCenter(j));
1262  }
1263  fFourierAverage[i].dataFourierIm->SetBinContent(j, dval/(end-start+1));
1264  }
1265  // set marker color, line color, maker size, marker type
1266  fFourierAverage[i].dataFourierIm->SetMarkerColor(fColorList[i]);
1267  fFourierAverage[i].dataFourierIm->SetLineColor(fColorList[i]);
1268  fFourierAverage[i].dataFourierIm->SetMarkerSize(0.8);
1269  fFourierAverage[i].dataFourierIm->SetMarkerStyle(22); // closed up triangle
1270 
1271  // power average
1272  for (Int_t j=0; j<fFourierHistos[0].dataFourierPwr->GetNbinsX(); j++) {
1273  dval = 0.0;
1274  for (Int_t k=start; k<=end; k++) {
1275  if (j < fFourierHistos[k].dataFourierPwr->GetNbinsX())
1276  dval += GetInterpolatedValue(fFourierHistos[k].dataFourierPwr, fFourierHistos[0].dataFourierPwr->GetBinCenter(j));
1277  }
1278  fFourierAverage[i].dataFourierPwr->SetBinContent(j, dval/(end-start+1));
1279  }
1280  // set marker color, line color, maker size, marker type
1281  fFourierAverage[i].dataFourierPwr->SetMarkerColor(fColorList[i]);
1282  fFourierAverage[i].dataFourierPwr->SetLineColor(fColorList[i]);
1283  fFourierAverage[i].dataFourierPwr->SetMarkerSize(0.8);
1284  fFourierAverage[i].dataFourierPwr->SetMarkerStyle(22); // closed up triangle
1285 
1286  // phase average
1287  for (Int_t j=0; j<fFourierHistos[0].dataFourierPhase->GetNbinsX(); j++) {
1288  dval = 0.0;
1289  for (Int_t k=start; k<=end; k++) {
1290  if (j < fFourierHistos[k].dataFourierPhase->GetNbinsX())
1291  dval += GetInterpolatedValue(fFourierHistos[k].dataFourierPhase, fFourierHistos[0].dataFourierPhase->GetBinCenter(j));
1292  }
1293  fFourierAverage[i].dataFourierPhase->SetBinContent(j, dval/(end-start+1));
1294  }
1295  // set marker color, line color, maker size, marker type
1296  fFourierAverage[i].dataFourierPhase->SetMarkerColor(fColorList[i]);
1297  fFourierAverage[i].dataFourierPhase->SetLineColor(fColorList[i]);
1298  fFourierAverage[i].dataFourierPhase->SetMarkerSize(0.8);
1299  fFourierAverage[i].dataFourierPhase->SetMarkerStyle(22); // closed up triangle
1300 
1301  if (phaseOptRealPresent) {
1302  // phase optimised real average
1303  for (Int_t j=0; j<fFourierHistos[0].dataFourierPhaseOptReal->GetNbinsX(); j++) {
1304  dval = 0.0;
1305  for (Int_t k=start; k<=end; k++) {
1306  if (j < fFourierHistos[k].dataFourierPhaseOptReal->GetNbinsX())
1307  dval += GetInterpolatedValue(fFourierHistos[k].dataFourierPhaseOptReal, fFourierHistos[0].dataFourierPhaseOptReal->GetBinCenter(j));
1308  }
1309  fFourierAverage[i].dataFourierPhaseOptReal->SetBinContent(j, dval/(end-start+1));
1310  }
1311  // set marker color, line color, maker size, marker type
1312  fFourierAverage[i].dataFourierPhaseOptReal->SetMarkerColor(fColorList[i]);
1313  fFourierAverage[i].dataFourierPhaseOptReal->SetLineColor(fColorList[i]);
1314  fFourierAverage[i].dataFourierPhaseOptReal->SetMarkerSize(0.8);
1315  fFourierAverage[i].dataFourierPhaseOptReal->SetMarkerStyle(22); // closed up triangle
1316  }
1317  }
1318  }
1319 }
1320 
1321 //--------------------------------------------------------------------------
1322 // CalcPhaseOptReal (private)
1323 //--------------------------------------------------------------------------
1328 {
1329  Int_t start = fFourierHistos[0].dataFourierRe->FindFixBin(fInitialXRange[0]);
1330  Int_t end = fFourierHistos[0].dataFourierRe->FindFixBin(fInitialXRange[1]);
1331 
1332  Double_t dval=0.0, max=0.0;
1333  for (UInt_t i=0; i<fFourierHistos.size(); i++) {
1334  fFourierHistos[i].dataFourierPhaseOptReal = fFourier[i]->GetPhaseOptRealFourier(fFourierHistos[i].dataFourierRe,
1335  fFourierHistos[i].dataFourierIm, fFourierHistos[i].optPhase, 1.0, fInitialXRange[0], fInitialXRange[1]);
1336  // normalize it
1337  max = 0.0;
1338  for (Int_t j=start; j<=end; j++) {
1339  dval = fFourierHistos[i].dataFourierPhaseOptReal->GetBinContent(j);
1340  if (fabs(dval) > max)
1341  max = dval;
1342  }
1343  for (Int_t j=1; j<fFourierHistos[i].dataFourierPhaseOptReal->GetNbinsX(); j++) {
1344  fFourierHistos[i].dataFourierPhaseOptReal->SetBinContent(j, fFourierHistos[i].dataFourierPhaseOptReal->GetBinContent(j)/fabs(max));
1345  }
1346  // set the marker and line color
1347  fFourierHistos[i].dataFourierPhaseOptReal->SetMarkerColor(fColorList[i]);
1348  fFourierHistos[i].dataFourierPhaseOptReal->SetLineColor(fColorList[i]);
1349 
1350  // set the marker symbol and size
1351  fFourierHistos[i].dataFourierPhaseOptReal->SetMarkerStyle(fMarkerList[i]);
1352  fFourierHistos[i].dataFourierPhaseOptReal->SetMarkerSize(0.7);
1353  }
1354 }
1355 
1356 //--------------------------------------------------------------------------
1357 // PlotFourier (private)
1358 //--------------------------------------------------------------------------
1363 {
1364  // check if phase opt real Fourier spectra already exists if requested,
1365  // and if not calculate them first
1367  if (fFourierHistos[0].dataFourierPhaseOptReal == nullptr) { // not yet calculated
1368  CalcPhaseOptReal();
1369  }
1370  }
1371 
1372  fFourierPad->cd();
1373 
1374  Double_t xmin=0, xmax=0;
1375  xmin = fInitialXRange[0];
1376  xmax = fInitialXRange[1];
1377 
1378  Double_t ymin=0, ymax=0;
1379  switch (fCurrentPlotView) {
1380  case FOURIER_PLOT_REAL:
1381  fFourierHistos[0].dataFourierRe->GetXaxis()->SetRangeUser(xmin, xmax);
1382  ymin = GetMinimum(fFourierHistos[0].dataFourierRe, xmin, xmax);
1383  ymax = GetMaximum(fFourierHistos[0].dataFourierRe, xmin, xmax);
1384  for (UInt_t i=1; i<fFourierHistos.size(); i++) {
1385  if (GetMaximum(fFourierHistos[i].dataFourierRe, xmin, xmax) > ymax)
1386  ymax = GetMaximum(fFourierHistos[i].dataFourierRe, xmin, xmax);
1387  if (GetMinimum(fFourierHistos[i].dataFourierRe, xmin, xmax) < ymin)
1388  ymin = GetMinimum(fFourierHistos[i].dataFourierRe, xmin, xmax);
1389  }
1390  fFourierHistos[0].dataFourierRe->GetYaxis()->SetRangeUser(1.05*ymin, 1.05*ymax);
1391  fFourierHistos[0].dataFourierRe->GetYaxis()->SetTitle("Real");
1392  fFourierHistos[0].dataFourierRe->GetYaxis()->SetTitleOffset(1.3);
1393  fFourierHistos[0].dataFourierRe->GetYaxis()->SetDecimals(kTRUE);
1394  fFourierHistos[0].dataFourierRe->GetXaxis()->SetTitle(fXaxisTitle.Data());
1395  fFourierHistos[0].dataFourierRe->Draw("p");
1396  for (UInt_t i=1; i<fFourierHistos.size(); i++) {
1397  fFourierHistos[i].dataFourierRe->Draw("psame");
1398  }
1399  break;
1400  case FOURIER_PLOT_IMAG:
1401  fFourierHistos[0].dataFourierIm->GetXaxis()->SetRangeUser(xmin, xmax);
1402  ymin = GetMinimum(fFourierHistos[0].dataFourierIm, xmin, xmax);
1403  ymax = GetMaximum(fFourierHistos[0].dataFourierIm, xmin, xmax);
1404  for (UInt_t i=1; i<fFourierHistos.size(); i++) {
1405  if (GetMaximum(fFourierHistos[i].dataFourierIm, xmin, xmax) > ymax)
1406  ymax = GetMaximum(fFourierHistos[i].dataFourierIm, xmin, xmax);
1407  if (GetMinimum(fFourierHistos[i].dataFourierIm, xmin, xmax) < ymin)
1408  ymin = GetMinimum(fFourierHistos[i].dataFourierIm, xmin, xmax);
1409  }
1410  fFourierHistos[0].dataFourierIm->GetYaxis()->SetRangeUser(1.05*ymin, 1.05*ymax);
1411  fFourierHistos[0].dataFourierIm->GetYaxis()->SetTitleOffset(1.3);
1412  fFourierHistos[0].dataFourierIm->GetYaxis()->SetDecimals(kTRUE);
1413  fFourierHistos[0].dataFourierIm->GetYaxis()->SetTitle("Imag");
1414  fFourierHistos[0].dataFourierIm->GetXaxis()->SetTitle(fXaxisTitle.Data());
1415  fFourierHistos[0].dataFourierIm->Draw("p");
1416  for (UInt_t i=1; i<fFourierHistos.size(); i++) {
1417  fFourierHistos[i].dataFourierIm->Draw("psame");
1418  }
1419  break;
1421  fFourierHistos[0].dataFourierRe->GetXaxis()->SetRangeUser(xmin, xmax);
1422  ymin = GetMinimum(fFourierHistos[0].dataFourierRe, xmin, xmax);
1423  ymax = GetMaximum(fFourierHistos[0].dataFourierRe, xmin, xmax);
1424  for (UInt_t i=1; i<fFourierHistos.size(); i++) {
1425  if (GetMaximum(fFourierHistos[i].dataFourierRe, xmin, xmax) > ymax)
1426  ymax = GetMaximum(fFourierHistos[i].dataFourierRe, xmin, xmax);
1427  if (GetMaximum(fFourierHistos[i].dataFourierIm, xmin, xmax) > ymax)
1428  ymax = GetMaximum(fFourierHistos[i].dataFourierIm, xmin, xmax);
1429  if (GetMinimum(fFourierHistos[i].dataFourierRe, xmin, xmax) < ymin)
1430  ymin = GetMinimum(fFourierHistos[i].dataFourierRe, xmin, xmax);
1431  if (GetMinimum(fFourierHistos[i].dataFourierIm, xmin, xmax) < ymin)
1432  ymin = GetMinimum(fFourierHistos[i].dataFourierIm, xmin, xmax);
1433  }
1434  fFourierHistos[0].dataFourierRe->GetYaxis()->SetRangeUser(1.05*ymin, 1.05*ymax);
1435  fFourierHistos[0].dataFourierRe->GetYaxis()->SetTitleOffset(1.3);
1436  fFourierHistos[0].dataFourierRe->GetYaxis()->SetDecimals(kTRUE);
1437  fFourierHistos[0].dataFourierRe->GetYaxis()->SetTitle("Real");
1438  fFourierHistos[0].dataFourierRe->GetXaxis()->SetTitle(fXaxisTitle.Data());
1439  fFourierHistos[0].dataFourierRe->Draw("p");
1440  for (UInt_t i=1; i<fFourierHistos.size(); i++) {
1441  fFourierHistos[i].dataFourierRe->Draw("psame");
1442  }
1443  for (UInt_t i=0; i<fFourierHistos.size(); i++) {
1444  fFourierHistos[i].dataFourierIm->Draw("psame");
1445  }
1446  break;
1447  case FOURIER_PLOT_POWER:
1448  // get maximum of Fourier data in the range
1449  fFourierHistos[0].dataFourierPwr->GetXaxis()->SetRangeUser(xmin, xmax);
1450  ymin = 0.0;
1451  ymax = GetMaximum(fFourierHistos[0].dataFourierPwr, xmin, xmax);
1452  for (UInt_t i=1; i<fFourierHistos.size(); i++) {
1453  if (GetMaximum(fFourierHistos[i].dataFourierPwr, xmin, xmax) > ymax)
1454  ymax = GetMaximum(fFourierHistos[i].dataFourierPwr, xmin, xmax);
1455  }
1456  fFourierHistos[0].dataFourierPwr->GetYaxis()->SetRangeUser(ymin, 1.03*ymax);
1457  fFourierHistos[0].dataFourierPwr->GetYaxis()->SetTitle("Power");
1458  fFourierHistos[0].dataFourierPwr->GetYaxis()->SetTitleOffset(1.3);
1459  fFourierHistos[0].dataFourierPwr->GetYaxis()->SetDecimals(kTRUE);
1460  fFourierHistos[0].dataFourierPwr->GetXaxis()->SetTitle(fXaxisTitle.Data());
1461  fFourierHistos[0].dataFourierPwr->Draw("p");
1462  for (UInt_t i=1; i<fFourierHistos.size(); i++) {
1463  fFourierHistos[i].dataFourierPwr->Draw("psame");
1464  }
1465  break;
1466  case FOURIER_PLOT_PHASE:
1467  fFourierHistos[0].dataFourierPhase->GetXaxis()->SetRangeUser(xmin, xmax);
1468  ymin = GetMinimum(fFourierHistos[0].dataFourierPhase, xmin, xmax);
1469  ymax = GetMaximum(fFourierHistos[0].dataFourierPhase, xmin, xmax);
1470  for (UInt_t i=1; i<fFourierHistos.size(); i++) {
1471  if (GetMaximum(fFourierHistos[i].dataFourierPhase, xmin, xmax) > ymax)
1472  ymax = GetMaximum(fFourierHistos[i].dataFourierPhase, xmin, xmax);
1473  if (GetMinimum(fFourierHistos[i].dataFourierPhase, xmin, xmax) < ymin)
1474  ymin = GetMinimum(fFourierHistos[i].dataFourierPhase, xmin, xmax);
1475  }
1476  fFourierHistos[0].dataFourierPhase->GetYaxis()->SetRangeUser(1.05*ymin, 1.05*ymax);
1477  fFourierHistos[0].dataFourierPhase->GetYaxis()->SetTitleOffset(1.3);
1478  fFourierHistos[0].dataFourierPhase->GetYaxis()->SetDecimals(kTRUE);
1479  fFourierHistos[0].dataFourierPhase->GetYaxis()->SetTitle("Phase");
1480  fFourierHistos[0].dataFourierPhase->GetXaxis()->SetTitle(fXaxisTitle.Data());
1481  fFourierHistos[0].dataFourierPhase->Draw("p");
1482  for (UInt_t i=1; i<fFourierHistos.size(); i++) {
1483  fFourierHistos[i].dataFourierPhase->Draw("psame");
1484  }
1485  break;
1487  fFourierHistos[0].dataFourierPhaseOptReal->GetXaxis()->SetRangeUser(xmin, xmax);
1488  ymin = GetMinimum(fFourierHistos[0].dataFourierPhaseOptReal, xmin, xmax);
1489  ymax = GetMaximum(fFourierHistos[0].dataFourierPhaseOptReal, xmin, xmax);
1490  for (UInt_t i=1; i<fFourierHistos.size(); i++) {
1491  if (GetMaximum(fFourierHistos[i].dataFourierPhaseOptReal, xmin, xmax) > ymax)
1492  ymax = GetMaximum(fFourierHistos[i].dataFourierPhaseOptReal, xmin, xmax);
1493  if (GetMinimum(fFourierHistos[i].dataFourierPhaseOptReal, xmin, xmax) < ymin)
1494  ymin = GetMinimum(fFourierHistos[i].dataFourierPhaseOptReal, xmin, xmax);
1495  }
1496  fFourierHistos[0].dataFourierPhaseOptReal->GetYaxis()->SetRangeUser(ymin, 1.05*ymax);
1497  fFourierHistos[0].dataFourierPhaseOptReal->GetYaxis()->SetTitleOffset(1.3);
1498  fFourierHistos[0].dataFourierPhaseOptReal->GetYaxis()->SetDecimals(kTRUE);
1499  fFourierHistos[0].dataFourierPhaseOptReal->GetYaxis()->SetTitle("Phase Opt. Real");
1500  fFourierHistos[0].dataFourierPhaseOptReal->GetXaxis()->SetTitle(fXaxisTitle.Data());
1501  fFourierHistos[0].dataFourierPhaseOptReal->Draw("p");
1502  for (UInt_t i=1; i<fFourierHistos.size(); i++) {
1503  fFourierHistos[i].dataFourierPhaseOptReal->Draw("psame");
1504  }
1505  break;
1506  default:
1507  break;
1508  }
1509 
1510  fFourierPad->Update();
1511 
1512  fMainCanvas->cd();
1513  fMainCanvas->Update();
1514 }
1515 
1516 //--------------------------------------------------------------------------
1517 // PlotFourierPhaseValue (private)
1518 //--------------------------------------------------------------------------
1523 {
1524  Double_t x, y;
1525  TString str;
1526 
1527  // plot Fourier phase
1528  str = TString("phase = ");
1529  str += fCurrentFourierPhase;
1530  x = 0.7;
1531  y = 0.85;
1532  fCurrentFourierPhaseText.reset(new TLatex());
1533  fCurrentFourierPhaseText->SetNDC(kTRUE);
1534  fCurrentFourierPhaseText->SetText(x, y, str.Data());
1535  fCurrentFourierPhaseText->SetTextFont(62);
1536  fCurrentFourierPhaseText->SetTextSize(0.03);
1537 
1538  fFourierPad->cd();
1539 
1540  fCurrentFourierPhaseText->Draw();
1541 
1542  fFourierPad->Update();
1543 }
1544 
1545 //--------------------------------------------------------------------------
1546 // PlotAverage (private)
1547 //--------------------------------------------------------------------------
1552 {
1553  fFourierPad->cd();
1554 
1555  if (fFourierAverage.size() == 0) { // ups, HandleAverage never called!
1556  HandleAverage();
1557  }
1558 
1559  Double_t xmin=0.0, xmax=0.0;
1560  xmin = fInitialXRange[0];
1561  xmax = fInitialXRange[1];
1562  Double_t ymin=0.0, ymax=0.0;
1563 
1564  if (fLegAvgPerDataSet.get()) {
1565  fLegAvgPerDataSet->Clear();
1566  }
1567 
1568  switch (fCurrentPlotView) {
1569  case FOURIER_PLOT_REAL:
1570  fFourierAverage[0].dataFourierRe->GetXaxis()->SetRangeUser(xmin, xmax);
1571  ymin = GetMinimum(fFourierAverage[0].dataFourierRe, xmin, xmax);
1572  ymax = GetMaximum(fFourierAverage[0].dataFourierRe, xmin, xmax);
1573  for (UInt_t i=1; i<fFourierAverage.size(); i++) {
1574  if (GetMaximum(fFourierAverage[i].dataFourierRe, xmin, xmax) > ymax)
1575  ymax = GetMaximum(fFourierAverage[i].dataFourierRe, xmin, xmax);
1576  if (GetMinimum(fFourierAverage[i].dataFourierRe, xmin, xmax) < ymin)
1577  ymin = GetMinimum(fFourierAverage[i].dataFourierRe, xmin, xmax);
1578  }
1579  fFourierAverage[0].dataFourierRe->GetYaxis()->SetRangeUser(1.03*ymin, 1.03*ymax);
1580  fFourierAverage[0].dataFourierRe->GetYaxis()->SetTitleOffset(1.3);
1581  fFourierAverage[0].dataFourierRe->GetYaxis()->SetDecimals(kTRUE);
1582  fFourierAverage[0].dataFourierRe->GetYaxis()->SetTitle("<Real>");
1583  fFourierAverage[0].dataFourierRe->GetXaxis()->SetTitle(fXaxisTitle.Data());
1584  fFourierAverage[0].dataFourierRe->GetXaxis()->SetRangeUser(xmin, xmax);
1585  fFourierAverage[0].dataFourierRe->Draw("p");
1586  break;
1587  case FOURIER_PLOT_IMAG:
1588  fFourierAverage[0].dataFourierIm->GetXaxis()->SetRangeUser(xmin, xmax);
1589  ymin = GetMinimum(fFourierAverage[0].dataFourierIm, xmin, xmax);
1590  ymax = GetMaximum(fFourierAverage[0].dataFourierIm, xmin, xmax);
1591  for (UInt_t i=1; i<fFourierAverage.size(); i++) {
1592  if (GetMaximum(fFourierAverage[i].dataFourierIm, xmin, xmax) > ymax)
1593  ymax = GetMaximum(fFourierAverage[i].dataFourierIm, xmin, xmax);
1594  if (GetMinimum(fFourierAverage[i].dataFourierIm, xmin, xmax) < ymin)
1595  ymin = GetMinimum(fFourierAverage[i].dataFourierIm, xmin, xmax);
1596  }
1597  fFourierAverage[0].dataFourierIm->GetYaxis()->SetRangeUser(1.03*ymin, 1.03*ymax);
1598  fFourierAverage[0].dataFourierIm->GetYaxis()->SetTitleOffset(1.3);
1599  fFourierAverage[0].dataFourierIm->GetYaxis()->SetDecimals(kTRUE);
1600  fFourierAverage[0].dataFourierIm->GetYaxis()->SetTitle("<Imag>");
1601  fFourierAverage[0].dataFourierIm->GetXaxis()->SetTitle(fXaxisTitle.Data());
1602  fFourierAverage[0].dataFourierIm->GetXaxis()->SetRangeUser(xmin, xmax);
1603  fFourierAverage[0].dataFourierIm->Draw("p");
1604  break;
1606  fFourierAverage[0].dataFourierRe->GetXaxis()->SetRangeUser(xmin, xmax);
1607  ymin = GetMinimum(fFourierAverage[0].dataFourierRe, xmin, xmax);
1608  ymax = GetMaximum(fFourierAverage[0].dataFourierRe, xmin, xmax);
1609  for (UInt_t i=1; i<fFourierAverage.size(); i++) {
1610  if (GetMaximum(fFourierAverage[i].dataFourierRe, xmin, xmax) > ymax)
1611  ymax = GetMaximum(fFourierAverage[i].dataFourierRe, xmin, xmax);
1612  if (GetMinimum(fFourierAverage[i].dataFourierRe, xmin, xmax) < ymin)
1613  ymin = GetMinimum(fFourierAverage[i].dataFourierRe, xmin, xmax);
1614  }
1615  fFourierAverage[0].dataFourierRe->GetYaxis()->SetRangeUser(1.03*ymin, 1.03*ymax);
1616  fFourierAverage[0].dataFourierRe->GetYaxis()->SetTitleOffset(1.3);
1617  fFourierAverage[0].dataFourierRe->GetYaxis()->SetDecimals(kTRUE);
1618  fFourierAverage[0].dataFourierRe->GetYaxis()->SetTitle("<Real+Imag>");
1619  fFourierAverage[0].dataFourierRe->GetXaxis()->SetTitle(fXaxisTitle.Data());
1620  fFourierAverage[0].dataFourierRe->GetXaxis()->SetRangeUser(xmin, xmax);
1621  fFourierAverage[0].dataFourierRe->Draw("p");
1622  fFourierAverage[0].dataFourierIm->Draw("psame");
1623  break;
1624  case FOURIER_PLOT_POWER:
1625  // get maximum of Fourier data in the range
1626  fFourierAverage[0].dataFourierPwr->GetXaxis()->SetRangeUser(xmin, xmax);
1627  ymin = 0.0;
1628  ymax = GetMaximum(fFourierAverage[0].dataFourierPwr, xmin, xmax);
1629  for (UInt_t i=1; i<fFourierAverage.size(); i++) {
1630  if (GetMaximum(fFourierAverage[i].dataFourierPwr, xmin, xmax) > ymax)
1631  ymax = GetMaximum(fFourierAverage[i].dataFourierPwr, xmin, xmax);
1632  }
1633  fFourierAverage[0].dataFourierPwr->GetYaxis()->SetRangeUser(ymin, 1.03*ymax);
1634  fFourierAverage[0].dataFourierPwr->GetYaxis()->SetTitleOffset(1.3);
1635  fFourierAverage[0].dataFourierPwr->GetYaxis()->SetDecimals(kTRUE);
1636  fFourierAverage[0].dataFourierPwr->GetYaxis()->SetTitle("<Power>");
1637  fFourierAverage[0].dataFourierPwr->GetXaxis()->SetTitle(fXaxisTitle.Data());
1638  fFourierAverage[0].dataFourierPwr->Draw("p");
1639  break;
1640  case FOURIER_PLOT_PHASE:
1641  fFourierAverage[0].dataFourierPhase->GetXaxis()->SetRangeUser(xmin, xmax);
1642  ymin = GetMinimum(fFourierAverage[0].dataFourierPhase, xmin, xmax);
1643  ymax = GetMaximum(fFourierAverage[0].dataFourierPhase, xmin, xmax);
1644  for (UInt_t i=1; i<fFourierAverage.size(); i++) {
1645  if (GetMaximum(fFourierAverage[i].dataFourierPhase, xmin, xmax) > ymax)
1646  ymax = GetMaximum(fFourierAverage[i].dataFourierPhase, xmin, xmax);
1647  if (GetMinimum(fFourierAverage[i].dataFourierPhase, xmin, xmax) < ymin)
1648  ymin = GetMinimum(fFourierAverage[i].dataFourierPhase, xmin, xmax);
1649  }
1650  fFourierAverage[0].dataFourierPhase->GetYaxis()->SetRangeUser(1.03*ymin, 1.03*ymax);
1651  fFourierAverage[0].dataFourierPhase->GetYaxis()->SetTitleOffset(1.3);
1652  fFourierAverage[0].dataFourierPhase->GetYaxis()->SetDecimals(kTRUE);
1653  fFourierAverage[0].dataFourierPhase->GetYaxis()->SetTitle("<Phase>");
1654  fFourierAverage[0].dataFourierPhase->GetXaxis()->SetTitle(fXaxisTitle.Data());
1655  fFourierAverage[0].dataFourierPhase->GetXaxis()->SetRangeUser(xmin, xmax);
1656  fFourierAverage[0].dataFourierPhase->Draw("p");
1657  break;
1659  if (fFourierHistos[0].dataFourierPhaseOptReal == nullptr) {
1660  std::cout << "debug> need to calculate phase opt. average first ..." << std::endl;
1661  CalcPhaseOptReal();
1662  HandleAverage();
1663  }
1664  fFourierAverage[0].dataFourierPhaseOptReal->GetXaxis()->SetRangeUser(xmin, xmax);
1665  ymin = GetMinimum(fFourierAverage[0].dataFourierPhaseOptReal, xmin, xmax);
1666  ymax = GetMaximum(fFourierAverage[0].dataFourierPhaseOptReal, xmin, xmax);
1667  for (UInt_t i=1; i<fFourierAverage.size(); i++) {
1668  if (GetMaximum(fFourierAverage[i].dataFourierPhaseOptReal, xmin, xmax) > ymax)
1669  ymax = GetMaximum(fFourierAverage[i].dataFourierPhaseOptReal, xmin, xmax);
1670  if (GetMinimum(fFourierAverage[i].dataFourierPhaseOptReal, xmin, xmax) < ymin)
1671  ymin = GetMinimum(fFourierAverage[i].dataFourierPhaseOptReal, xmin, xmax);
1672  }
1673  fFourierAverage[0].dataFourierPhaseOptReal->GetYaxis()->SetRangeUser(ymin, 1.03*ymax);
1674  fFourierAverage[0].dataFourierPhaseOptReal->GetYaxis()->SetTitleOffset(1.3);
1675  fFourierAverage[0].dataFourierPhaseOptReal->GetYaxis()->SetDecimals(kTRUE);
1676  fFourierAverage[0].dataFourierPhaseOptReal->GetYaxis()->SetTitle("<Phase Opt. Real>");
1677  fFourierAverage[0].dataFourierPhaseOptReal->GetXaxis()->SetTitle(fXaxisTitle.Data());
1678  fFourierAverage[0].dataFourierPhaseOptReal->GetXaxis()->SetRangeUser(xmin, xmax);
1679  fFourierAverage[0].dataFourierPhaseOptReal->Draw("p");
1680  break;
1681  default:
1682  break;
1683  }
1684 
1685  if (fAveragedViewPerDataSet) { // plot all the rest
1686  fLegAvgPerDataSet = std::make_unique<TLegend>(0.55, 0.4, 0.85, 0.6);
1687  TString str = GetDataSetName(fFourierAverage[0].dataFourierPwr->GetTitle());
1688  TString label = TString::Format("<%s>", str.Data());
1689  fLegAvgPerDataSet->AddEntry(fFourierAverage[0].dataFourierPwr, label.Data());
1690  for (UInt_t i=1; i<fFourierAverage.size(); i++) {
1691  switch (fCurrentPlotView) {
1692  case FOURIER_PLOT_REAL:
1693  fFourierAverage[i].dataFourierRe->Draw("psame");
1694  break;
1695  case FOURIER_PLOT_IMAG:
1696  fFourierAverage[i].dataFourierIm->Draw("psame");
1697  break;
1699  fFourierAverage[i].dataFourierRe->Draw("psame");
1700  fFourierAverage[i].dataFourierIm->Draw("psame");
1701  break;
1702  case FOURIER_PLOT_POWER:
1703  fFourierAverage[i].dataFourierPwr->Draw("psame");
1704  break;
1705  case FOURIER_PLOT_PHASE:
1706  fFourierAverage[i].dataFourierPhase->Draw("psame");
1707  break;
1709  fFourierAverage[i].dataFourierPhaseOptReal->Draw("psame");
1710  break;
1711  default:
1712  break;
1713  }
1714  // add legend ?!?!
1715  str = GetDataSetName(fFourierAverage[i].dataFourierPwr->GetTitle());
1716  label = TString::Format("<%s>", str.Data());
1717  fLegAvgPerDataSet->AddEntry(fFourierAverage[i].dataFourierPwr, label.Data());
1718  }
1719  fLegAvgPerDataSet->Draw();
1720  }
1721 
1722  fFourierPad->Update();
1723 
1724  fMainCanvas->cd();
1725  fMainCanvas->Update();
1726 }
1727 
1728 //--------------------------------------------------------------------------
1729 // IncrementFourierPhase (private)
1730 //--------------------------------------------------------------------------
1735 {
1737  return;
1738 
1739  Double_t re, im;
1740  Double_t inc = 1.0;
1741  const Double_t cp = TMath::Cos(inc/180.0*TMath::Pi());
1742  const Double_t sp = TMath::Sin(inc/180.0*TMath::Pi());
1743 
1744  fCurrentFourierPhase += inc;
1746 
1747  for (UInt_t i=0; i<fFourierHistos.size(); i++) { // loop over all data sets
1748  if ((fFourierHistos[i].dataFourierRe != nullptr) && (fFourierHistos[i].dataFourierIm != nullptr)) {
1749  for (Int_t j=0; j<fFourierHistos[i].dataFourierRe->GetNbinsX(); j++) { // loop over a fourier data set
1750  // calculate new fourier data set value
1751  re = fFourierHistos[i].dataFourierRe->GetBinContent(j) * cp + fFourierHistos[i].dataFourierIm->GetBinContent(j) * sp;
1752  im = fFourierHistos[i].dataFourierIm->GetBinContent(j) * cp - fFourierHistos[i].dataFourierRe->GetBinContent(j) * sp;
1753  // overwrite fourier data set value
1754  fFourierHistos[i].dataFourierRe->SetBinContent(j, re);
1755  fFourierHistos[i].dataFourierIm->SetBinContent(j, im);
1756  }
1757  }
1758  }
1759 }
1760 
1761 //--------------------------------------------------------------------------
1762 // DecrementFourierPhase (private)
1763 //--------------------------------------------------------------------------
1768 {
1770  return;
1771 
1772  Double_t re, im;
1773  Double_t inc = 1.0;
1774  const Double_t cp = TMath::Cos(inc/180.0*TMath::Pi());
1775  const Double_t sp = TMath::Sin(inc/180.0*TMath::Pi());
1776 
1777  fCurrentFourierPhase -= inc;
1779 
1780  for (UInt_t i=0; i<fFourierHistos.size(); i++) { // loop over all data sets
1781  if ((fFourierHistos[i].dataFourierRe != nullptr) && (fFourierHistos[i].dataFourierIm != nullptr)) {
1782  for (Int_t j=0; j<fFourierHistos[i].dataFourierRe->GetNbinsX(); j++) { // loop over a fourier data set
1783  // calculate new fourier data set value
1784  re = fFourierHistos[i].dataFourierRe->GetBinContent(j) * cp - fFourierHistos[i].dataFourierIm->GetBinContent(j) * sp;
1785  im = fFourierHistos[i].dataFourierIm->GetBinContent(j) * cp + fFourierHistos[i].dataFourierRe->GetBinContent(j) * sp;
1786  // overwrite fourier data set value
1787  fFourierHistos[i].dataFourierRe->SetBinContent(j, re);
1788  fFourierHistos[i].dataFourierIm->SetBinContent(j, im);
1789  }
1790  }
1791  }
1792 }
1793 
1794 //--------------------------------------------------------------------------
1795 // GetMaximum (private)
1796 //--------------------------------------------------------------------------
1808 Double_t PFourierCanvas::GetMaximum(TH1F* histo, Double_t xmin, Double_t xmax)
1809 {
1810  if (histo == nullptr)
1811  return 0.0;
1812 
1813  Int_t start=0, end=0;
1814  if (xmin == xmax) {
1815  start = 1;
1816  end = histo->GetNbinsX();
1817  } else {
1818  start = histo->FindBin(xmin);
1819  if ((start==0) || (start==histo->GetNbinsX()+1)) // underflow/overflow
1820  start = 1;
1821  end = histo->FindBin(xmax);
1822  if ((end==0) || (end==histo->GetNbinsX()+1)) // underflow/overflow
1823  end = histo->GetNbinsX();
1824  }
1825 
1826  Double_t max = histo->GetBinContent(start);
1827  Double_t binContent;
1828  for (Int_t i=start; i<end; i++) {
1829  binContent = histo->GetBinContent(i);
1830  if (max < binContent)
1831  max = binContent;
1832  }
1833 
1834  return max;
1835 }
1836 
1837 //--------------------------------------------------------------------------
1838 // GetMinimum (private)
1839 //--------------------------------------------------------------------------
1851 Double_t PFourierCanvas::GetMinimum(TH1F* histo, Double_t xmin, Double_t xmax)
1852 {
1853  if (histo == nullptr)
1854  return 0.0;
1855 
1856  Int_t start=0, end=0;
1857  if (xmin == xmax) {
1858  start = 1;
1859  end = histo->GetNbinsX();
1860  } else {
1861  start = histo->FindBin(xmin);
1862  if ((start==0) || (start==histo->GetNbinsX()+1)) // underflow/overflow
1863  start = 1;
1864  end = histo->FindBin(xmax);
1865  if ((end==0) || (end==histo->GetNbinsX()+1)) // underflow/overflow
1866  end = histo->GetNbinsX();
1867  }
1868 
1869  Double_t min = histo->GetBinContent(start);
1870  Double_t binContent;
1871  for (Int_t i=start; i<end; i++) {
1872  binContent = histo->GetBinContent(i);
1873  if (min > binContent)
1874  min = binContent;
1875  }
1876 
1877  return min;
1878 }
1879 
1880 //--------------------------------------------------------------------------
1881 // GetInterpolatedValue (private)
1882 //--------------------------------------------------------------------------
1893 Double_t PFourierCanvas::GetInterpolatedValue(TH1F* histo, Double_t xVal)
1894 {
1895  if (histo == nullptr)
1896  return 0.0;
1897 
1898  Int_t idx = histo->FindBin(xVal);
1899 
1900  // make sure idx is within range
1901  if ((idx < 1) || (idx > histo->GetNbinsX()))
1902  return 0.0;
1903 
1904  // make sure the lower bound idx is found. This is needed since
1905  // FindBin rounds towards the closer idx.
1906  if (histo->GetBinCenter(idx) > xVal)
1907  --idx;
1908 
1909  Double_t x0, x1, y0, y1;
1910  x0 = histo->GetBinCenter(idx);
1911  x1 = histo->GetBinCenter(idx+1);
1912  y0 = histo->GetBinContent(idx);
1913  y1 = histo->GetBinContent(idx+1);
1914 
1915  return (y1-y0)*(xVal-x0)/(x1-x0)+y0;
1916 }
1917 
1918 //--------------------------------------------------------------------------
1919 // GetDataSetName (private)
1920 //--------------------------------------------------------------------------
1929 TString PFourierCanvas::GetDataSetName(TString title)
1930 {
1931  TString str(title);
1932 
1933  Ssiz_t idx = str.First(':');
1934  str.Remove(0, idx+1);
1935  idx = str.First(',');
1936  str.Remove(idx);
1937 
1938  return str;
1939 }
std::unique_ptr< TLatex > fCurrentFourierPhaseText
used in Re/Im Fourier to show the current phase in the pad
Int_t fTimeout
timeout after which the Done signal should be emited. If timeout <= 0, no timeout is taking place ...
virtual void DecrementFourierPhase()
PIntVector fColorList
list of colors
std::unique_ptr< TTimer > fTimeoutTimer
timeout timer in order to terminate if no action is taking place for too long
#define P_MENU_ID_FOURIER_PHASE_MINUS
virtual void SaveGraphicsAndQuit(const Char_t *fileName)
virtual void PlotAverage()
PFourierCanvasDataList fFourierHistos
keeps all the Fourier histos
#define P_MENU_ID_FOURIER_PHASE_PLUS
PIntVector fDataSetTag
vector holding the data set tags
std::unique_ptr< TPaveText > fTitlePad
title pad used to display a title
#define FOURIER_PLOT_POWER
Definition: PMusr.h:147
#define YTITLE
#define P_MENU_ID_FOURIER
Int_t fCurrentPlotView
tag showing what the current plot view is: real, imag, power, phase, ...
virtual void LastCanvasClosed()
virtual void Done(Int_t status=0)
virtual void PlotFourierPhaseValue()
virtual void PlotFourier()
Bool_t fAveragedViewPerDataSet
tag showing that the averaged view for individual data sets or normal view should be presented...
Bool_t fValid
if true, everything looks OK
virtual void CleanupAverage()
#define FOURIER_PLOT_IMAG
Definition: PMusr.h:145
TRootCanvas * fImp
ROOT native GUI version of main window with menubar and drawing area.
#define FOURIER_PLOT_REAL
Definition: PMusr.h:144
std::vector< Int_t > PIntVector
Definition: PMusr.h:178
virtual void SetTimeout(Int_t ival)
std::unique_ptr< TPad > fFourierPad
fourier pad used to display the fourier
#define FOURIER_UNIT_CYCLES
Definition: PMusr.h:135
virtual void UpdateInfoPad()
std::unique_ptr< TLegend > fInfoPad
info pad used to display a legend of the data plotted
#define FOURIER_PLOT_REAL_AND_IMAG
Definition: PMusr.h:146
#define P_MENU_ID_FOURIER_PWR
virtual void CalcPhaseOptReal()
#define FOURIER_UNIT_FREQ
Definition: PMusr.h:134
#define P_MENU_ID_EXPORT_DATA
#define YINFO
virtual void CreateXaxisTitle()
virtual void InitFourierDataSets()
static int timeout
Definition: musrfit.cpp:71
std::unique_ptr< TLegend > fLegAvgPerDataSet
legend used for averaged per data set view
Double_t fInitialXRange[2]
keeps the initial x-range
Bool_t fAveragedView
tag showing that the averaged view for ALL data or normal view should be presented.
static const Char_t * gFiletypes[]
std::unique_ptr< TGPopupMenu > fPopupFourier
popup menu of the MusrFT/Fourier sub menu
Bool_t fBatchMode
musrview in ROOT batch mode
PFourierCanvasDataList fFourierAverage
keeps the average of the Fourier histos
virtual void HandleMenuPopup(Int_t id)
#define P_MENU_ID_AVERAGE_PER_DATA_SET
#define P_MENU_ID_FOURIER_PHASE
TGMenuBar * fBar
menu bar
#define FOURIER_PLOT_PHASE
Definition: PMusr.h:148
virtual TString GetDataSetName(TString title)
#define FOURIER_UNIT_GAUSS
Definition: PMusr.h:132
virtual void IncrementFourierPhase()
ClassImpQ(PFourierCanvas) PFourierCanvas
virtual void HandleCmdKey(Int_t event, Int_t x, Int_t y, TObject *selected)
virtual Double_t GetInterpolatedValue(TH1F *histo, Double_t xVal)
#define FOURIER_UNIT_TESLA
Definition: PMusr.h:133
std::vector< PFourier * > fFourier
keeps all the Fourier data, ownership is with the caller
#define FOURIER_PLOT_PHASE_OPT_REAL
Definition: PMusr.h:149
#define FOURIER_PLOT_NOT_GIVEN
Definition: PMusr.h:143
virtual Double_t GetMinimum(TH1F *histo, Double_t xmin=-1.0, Double_t xmax=-1.0)
#define P_MENU_ID_FOURIER_REAL
#define P_MENU_ID_FOURIER_PHASE_OPT_REAL
TGPopupMenu * fPopupMain
popup menu MusrFT in the main menu bar
#define P_MENU_ID_AVERAGE
std::unique_ptr< TStyle > fStyle
A collection of all graphics attributes.
virtual void HandleAverage()
return status
#define P_MENU_ID_FOURIER_REAL_AND_IMAG
#define P_MENU_ID_FOURIER_IMAG
virtual void UpdateFourierPad()
PIntVector fMarkerList
list of markers
virtual void ExportData(const Char_t *pathFileName)
virtual void InitFourierCanvas(const Char_t *title, Int_t wtopx, Int_t wtopy, Int_t ww, Int_t wh)
std::unique_ptr< TCanvas > fMainCanvas
main canvas
virtual Double_t GetMaximum(TH1F *histo, Double_t xmin=-1.0, Double_t xmax=-1.0)
virtual void CreateStyle()
Double_t fCurrentFourierPhase
keeps the current Fourier phase (real/imag)