AveragePowerSpectrum.cxx
1 #include "AveragePowerSpectrum.h"
2 
3 ClassImp(AveragePowerSpectrum);
4 
5 
6 
7 
8 
9 //---------------------------------------------------------------------------------------------------------
16  // Don't use this.
17  for(Int_t freqInd=0; freqInd<NUM_FREQS; freqInd++){
18  hRayleighs[freqInd] = NULL;
19  // hRayleighFits[freqInd] = NULL;
20  }
21 }
22 
23 
24 
25 
26 
27 //---------------------------------------------------------------------------------------------------------
34 AveragePowerSpectrum::AveragePowerSpectrum(TString name, TString title){
35 
36 
37  deltaFMHz = 1e3/(NOMINAL_SAMPLING_DELTAT*NUM_SAMPLES);
38 
39  count=0;
40  SetName(name);
41  SetTitle(title);
42 
43  // Default power spec histogram values.
44  // maxNumOutliers = 5;
45  // maxNumOutliers = 0;
46 
47  for(Int_t freqInd=0; freqInd<NUM_FREQS; freqInd++){
48  // psdOutliers[freqInd] = std::vector<Double_t>(0, 0);
49  summedPowSpec[freqInd] = 0;
50 
51  TString histName = name + TString::Format("_%d", freqInd);
52  TString histTitle = title + TString::Format(" Rayleigh Distribution for %4.2lf MHz bin",
53  deltaFMHz*freqInd);
54  histTitle += "; Amplitude (mV/MHz); Events/bin";
55  TH1D* hTemp = new TH1D(histName, histTitle,
56  NUM_AMPLITUDE_BINS,
57  INITIAL_MIN_AMPLITUDE,
58  INITIAL_MAX_AMPLITUDE);
59  hTemp->SetDirectory(0);
60  hTemp->Sumw2();
61 
62  // This prepocessor variable is defined in the Makefile and is (I hope)
63  // querying the ROOT major version number. At the moment it asks whether the
64  // ROOT major version number is >= 6, hence the name.
65  // It works for me, for now.
66 #ifdef IS_ROOT_6
67  hTemp->SetCanExtend(TH1::kAllAxes);
68 #else
69  hTemp->SetBit(TH1::kCanRebin);
70 #endif
71 
72  hRayleighs[freqInd] = hTemp;
73  // hRayleighFits[freqInd] = NULL;
74 
75  rayleighFitChiSquares[freqInd] = -1;
76  rayleighFitChiSquaresRisingEdge[freqInd] = -1;
78 
79  rayleighAmplitudes[freqInd] = -1;
80  rayleighAmplitudesRisingEdge[freqInd] = -1;
82 
83  rayleighNdf[freqInd] = -1;
84  rayleighNdfRisingEdge[freqInd] = -1;
86 
87  for(int i=0; i<MAX_NUM_OUTLIERS; i++){
88  outliers[freqInd][i] = -1;
89  }
90  numOutliers[freqInd] = 0;
91  }
92 }
93 
94 
95 
96 
97 
98 //---------------------------------------------------------------------------------------------------------
104 }
105 
106 
107 
108 
109 //---------------------------------------------------------------------------------------------------------
114  return "([0]*x/([1]*[1]))*exp(-x*x/(2*[1]*[1]))";
115 }
116 
117 
118 
119 
120 
121 //---------------------------------------------------------------------------------------------------------
129 TF1* AveragePowerSpectrum::makeRayleighFunction(TString name, Double_t xMin, Double_t xMax){
130  TF1* fRay = new TF1(name, getRayleighFunctionText(), xMin, xMax);
131  return fRay;
132 }
133 
134 
135 
136 
137 
138 //---------------------------------------------------------------------------------------------------------
145 
146  Double_t* ps = FancyFFTs::getPowerSpectrum(NUM_SAMPLES, gr->GetY(),
147  NOMINAL_SAMPLING_DELTAT, FancyFFTs::kSum);
148  for(Int_t freqInd=0; freqInd < NUM_FREQS; freqInd++){
149  // Double_t sqrtPSD = TMath::Sqrt(ps[freqInd]);
150  Double_t sqrtPSD = TMath::Sqrt(ps[freqInd])/(deltaFMHz);
151 
152  eventRayleighAmplitudes[freqInd] = sqrtPSD;
153  eventPowSpec[freqInd] = ps[freqInd];
154  }
155 
156  delete [] ps;
157 }
158 
159 
160 
161 
162 
163 //---------------------------------------------------------------------------------------------------------
172 size_t AveragePowerSpectrum::add(TGraph* gr){
173 
174  // Double_t* ps = FancyFFTs::getPowerSpectrum(numSamples, gr->GetY(), 1e-3*deltaT, FancyFFTs::kPowSpecDensity);
175  // Double_t* ps = FancyFFTs::getPowerSpectrum(numSamples, gr->GetY(), deltaT, FancyFFTs::kPowSpecDensity);
176 
178 
179  for(Int_t freqInd=0; freqInd < NUM_FREQS; freqInd++){
180  // Double_t sqrtPSD = TMath::Sqrt(ps[freqInd]);
181  Double_t sqrtPSD = eventRayleighAmplitudes[freqInd];
182 
183  TH1D* h = hRayleighs[freqInd];
184  Double_t histMaxVal = h->GetXaxis()->GetBinLowEdge(h->GetNbinsX()+1);
185  if(sqrtPSD < histMaxVal){
186  h->Fill(sqrtPSD);
187  }
188  else{
189  outliers[freqInd][numOutliers[freqInd]] = sqrtPSD;
190  numOutliers[freqInd]++;
191 
192 
193  if(numOutliers[freqInd]>=MAX_NUM_OUTLIERS){
194 
195  while(numOutliers[freqInd] >= MAX_NUM_OUTLIERS){
196  histMaxVal*=2;
197 
198  Double_t outliersTemp[MAX_NUM_OUTLIERS] = {0};
199  Int_t numOutliersTemp = 0;
200 
201  for(int i=0; i<MAX_NUM_OUTLIERS; i++){
202  if(outliers[freqInd][i] < histMaxVal){
203  h->Fill(outliers[freqInd][i]);
204  }
205  else{
206  outliersTemp[numOutliersTemp] = outliers[freqInd][i];
207  numOutliersTemp++;
208  }
209  }
210 
211  numOutliers[freqInd] = 0;
212  for(int i=0; i < numOutliersTemp; i++){
213  outliers[freqInd][i] = outliersTemp[i];
214  numOutliers[freqInd]++;
215  }
216  for(int i=numOutliersTemp; i < MAX_NUM_OUTLIERS; i++){
217  outliers[freqInd][i] = -1;
218  }
219  }
220  }
221  }
222  }
223 
224  for(Int_t freqInd=0; freqInd < NUM_FREQS; freqInd++){
225  summedPowSpec[freqInd] += eventPowSpec[freqInd];
226  }
227  count++;
228 
229  return count;
230 }
231 
232 
233 
234 
235 
236 //---------------------------------------------------------------------------------------------------------
243  for(Int_t freqInd=0; freqInd < NUM_FREQS; freqInd++){
244  TH1D* h = hRayleighs[freqInd];
245  h->Rebin(rebinFactor);
246  }
247 }
248 
249 
250 
251 
252 
253 //---------------------------------------------------------------------------------------------------------
261 
262  Int_t bestFreqInd=0;
263  Double_t bestFreqDiff = DBL_MAX;
264  for(Int_t freqInd=0; freqInd < NUM_FREQS-1; freqInd++){
265  Double_t freqDiff = TMath::Abs(freqInd*deltaFMHz - freqMHz);
266  if(freqDiff < bestFreqDiff){
267  bestFreqInd = freqInd;
268  bestFreqDiff = freqDiff;
269  }
270  }
271  return hRayleighs[bestFreqInd];
272 }
273 
274 
275 
276 
277 
278 //---------------------------------------------------------------------------------------------------------
286  return hRayleighs[freqInd];
287 }
288 
289 
290 
291 
292 
293 //---------------------------------------------------------------------------------------------------------
301  TH1D* h = hRayleighs[freqInd];
302  TString funcName = TString::Format("fit_%d", freqInd);
303  TF1* f = (TF1*) h->FindObject(funcName);
304  return f;
305 }
306 
307 
308 
309 
310 
311 
312 //---------------------------------------------------------------------------------------------------------
319 
320  Double_t maxVal = 0;
321  for(Int_t freqInd=0; freqInd < NUM_FREQS; freqInd++){
322  TH1D* h = getRayleighHistogram(freqInd);
323  Double_t xMax = h->GetXaxis()->GetBinLowEdge(h->GetNbinsX()+1);
324  if(xMax > maxVal){
325  maxVal = xMax;
326  }
327  }
328 
329 
330  TString name = TString::Format("h2D_%s", GetName());
331  TString title = TString::Format("%s Rayleigh Distribution Summary", GetTitle());
332 
333  TH2D* h2 = new TH2D(name, title, NUM_FREQS, 0, NUM_FREQS*deltaFMHz,
334  NUM_AMPLITUDE_BINS, 0, maxVal);
335 
336  h2->GetXaxis()->SetTitle("Frequency (MHz)");
337  h2->GetXaxis()->SetNoExponent(1);
338  h2->GetYaxis()->SetTitle("Amplitude (mV/MHz)");
339  h2->GetYaxis()->SetNoExponent(1);
340  h2->Sumw2();
341 
342  for(Int_t freqInd=0; freqInd < NUM_FREQS; freqInd++){
343  TH1D* h = getRayleighHistogram(freqInd);
344  for(Int_t binx=1; binx<=h->GetNbinsX(); binx++){
345  Double_t freqMHz = freqInd*deltaFMHz;
346  Double_t amplitude = h->GetBinCenter(binx);
347  Double_t weight = h->GetBinContent(binx);
348 
349  h2->Fill(freqMHz, amplitude, weight);
350  }
351  }
352 
353  return h2;
354 
355 }
356 
357 
358 
359 
360 
361 //---------------------------------------------------------------------------------------------------------
366  for(Int_t freqInd=0; freqInd < NUM_FREQS; freqInd++){
367  fitRayleighHistogram(freqInd);
368  }
369 }
370 
371 
372 
373 
374 
375 
376 //---------------------------------------------------------------------------------------------------------
381  for(Int_t freqInd=0; freqInd < NUM_FREQS; freqInd++){
383  }
384 }
385 
386 
387 
388 
389 
390 //---------------------------------------------------------------------------------------------------------
395  for(Int_t freqInd=0; freqInd < NUM_FREQS; freqInd++){
397  }
398 }
399 
400 
401 
402 
403 //---------------------------------------------------------------------------------------------------------
413 TF1* AveragePowerSpectrum::constructFitFromAmplitude(Int_t freqInd, Double_t amplitude){
414 
415  TH1D* h = getRayleighHistogram(freqInd);
416  TString fitName = TString::Format("fit_%d_%lf", freqInd, amplitude);
417  TF1* fit = makeRayleighFunction(fitName, 0, h->GetBinLowEdge(h->GetNbinsX()+1));
418  fit->SetParameter(1, amplitude);
419  fit->SetParameter(0, h->GetBinLowEdge(2)*h->Integral());
420  return fit;
421 }
422 
423 
424 
425 
426 
427 //---------------------------------------------------------------------------------------------------------
438  return constructFitFromAmplitude(freqInd, rayleighAmplitudes[freqInd]);
439 }
440 
441 
442 
443 
444 
445 //---------------------------------------------------------------------------------------------------------
457 }
458 
459 
460 
461 
462 
463 //---------------------------------------------------------------------------------------------------------
475 }
476 
477 
478 
479 
480 
481 //---------------------------------------------------------------------------------------------------------
488  // std::cout << __PRETTY_FUNCTION__ << std::endl;
489 
490  TH1D* h = getRayleighHistogram(freqInd);
491  xHigh[freqInd] = h->GetBinLowEdge(h->GetNbinsX()+1);
492 
493  fitRayleighHistogramOverRange(freqInd, h->GetBinLowEdge(1), xHigh[freqInd],
496  rayleighNdf,
499 }
500 
501 
502 
503 
504 
505 //---------------------------------------------------------------------------------------------------------
512  // std::cout << __PRETTY_FUNCTION__ << std::endl;
513 
514  TH1D* h = getRayleighHistogram(freqInd);
515  Int_t peakBin = RootTools::getPeakBinOfHistogram(h);
516 
517  xHighRisingEdge[freqInd] = h->GetBinCenter(peakBin);
518  fitRayleighHistogramOverRange(freqInd, h->GetBinLowEdge(1), xHighRisingEdge[freqInd],
524 }
525 
526 
527 
528 
529 
530 
531 //---------------------------------------------------------------------------------------------------------
538  // std::cout << __PRETTY_FUNCTION__ << std::endl;
539 
540  TH1D* h = getRayleighHistogram(freqInd);
541  Double_t xHighTemp = -1;
542  Int_t peakBin = RootTools::getPeakBinOfHistogram(h);
543  Double_t peakVal = h->GetBinContent(peakBin);
544 
545  for(Int_t binx=peakBin; binx<=h->GetNbinsX(); binx++){
546  Double_t binVal = h->GetBinContent(binx);
547  if(binVal < peakVal*0.5){
548  xHighTemp = h->GetBinCenter(binx);
549  // std::cout << fName << "\t" << freqInd << "\t" << binx << "\t" << xHigh << std::endl;
550  break;
551  }
552  }
553 
554  xHighRisingEdgeAndHalfFalling[freqInd] = xHighTemp;
555  fitRayleighHistogramOverRange(freqInd, h->GetBinLowEdge(1), xHighTemp,
561  // fitRayleighHistogramOverRange(freqInd, h->GetBinLowEdge(1), h->GetBinLowEdge(3));
562 }
563 
564 
565 
566 
567 
568 //---------------------------------------------------------------------------------------------------------
581 void AveragePowerSpectrum::fitRayleighHistogramOverRange(Int_t freqInd, Double_t xLowVal, Double_t xHighVal,
582  Double_t* rAmplitudes,
583  Double_t* rChiSquares,
584  Int_t* rNdf,
585  Double_t* rChiSquaresFullRange,
586  Int_t* rNdfFullRange){
587 
588 
589  TH1D* h = getRayleighHistogram(freqInd);
590 
591  if(h->Integral() > 0){ // Fit will fail with empty histogram
592 
593  TString fitName = TString::Format("fit_%d", freqInd);
594  TF1* fit = makeRayleighFunction(fitName, xLowVal, xHighVal);
595 
596  Double_t mean = h->GetMean();
597  // Mean of rayleigh distribution = sigma* (pi/2)^{0.5}
598  Double_t sigGuess = mean / TMath::Sqrt(0.5*TMath::Pi());
599 
600  fit->SetParameter(1, sigGuess);
601 
602  // Can't not set upper bound if setting lower bound..
603  // Therefore set the upper bound to be insanely high.
604  // fit->SetParLimits(1, 0, h->GetMean()*1e9);
605 
606  Double_t histArea = h->Integral() * h->GetBinLowEdge(2);
607  fit->FixParameter(0, histArea);
608 
609  h->Fit(fit, "RQ0");
610 
611  // h->GetFunction(fit->GetName())->ResetBit(TF1::kNotDraw);
612  rAmplitudes[freqInd] = h->GetFunction(fit->GetName())->GetParameter(1);
613  rChiSquares[freqInd] = h->GetFunction(fit->GetName())->GetChisquare();
614  rNdf[freqInd] = h->GetFunction(fit->GetName())->GetNDF();
615 
616  rChiSquaresFullRange[freqInd] = 0;
617  rNdfFullRange[freqInd] = 0;
618  for(int binx=1; binx<=h->GetNbinsX(); binx++){
619  Double_t binVal = h->GetBinContent(binx);
620  Double_t binError = h->GetBinError(binx);
621  Double_t fitVal = fit->Eval(h->GetBinCenter(binx));
622  if(binError > 0){
623  Double_t chi = (binVal - fitVal)/binError;
624  rChiSquaresFullRange[freqInd] += chi*chi;
625  rNdfFullRange[freqInd]++;
626  }
627  }
628 
629  delete fit;
630  }
631 }
632 
633 
634 
635 
636 
637 //---------------------------------------------------------------------------------------------------------
642  for(int freqInd=0; freqInd < NUM_FREQS; freqInd++){
643  if(hRayleighs[freqInd]!=NULL){
644  delete hRayleighs[freqInd];
645  hRayleighs[freqInd] = NULL;
646  }
647  }
648 }
649 
650 
651 
652 
653 
654 //---------------------------------------------------------------------------------------------------------
659 
660  TString name = TString::Format("gr_%s", GetName());
661  TString title = TString::Format("%s", GetTitle());
662 
663  std::vector<Double_t> avePowSpec(NUM_FREQS);
664 
665  for(Int_t freqInd=0; freqInd < NUM_FREQS; freqInd++){
666  if(count > 0){
667  avePowSpec[freqInd] = summedPowSpec[freqInd]/count;
668  }
669  }
670 
671  // Double_t termResOhms = 50;
672  for(Int_t freqInd=0; freqInd < NUM_FREQS; freqInd++){
673  avePowSpec[freqInd]/=(deltaFMHz);
674  }
675 
676  Double_t freqArray[NUM_FREQS];
677  for(int freqInd=0; freqInd < NUM_FREQS; freqInd++){
678  freqArray[freqInd] = deltaFMHz*freqInd;
679  }
680 
681  TGraph* gr = new TGraph(NUM_FREQS, freqArray, &avePowSpec[0]);
682  gr->SetName(name);
683  gr->SetTitle(title);
684  return gr;
685 }
686 
687 
688 
689 
690 
691 
692 //---------------------------------------------------------------------------------------------------------
697 
698  TGraph* gr = makeAvePowSpecTGraph();
699  TString name = TString::Format("%s_dB", gr->GetName());
700 
701  for(Int_t freqInd=0; freqInd < NUM_FREQS; freqInd++){
702  Double_t y = gr->GetY()[freqInd];
703  // gr->GetY()[freqInd] = 10*TMath::Log10(y);
704  gr->GetY()[freqInd] = 10*TMath::Log10(y);
705  }
706  return gr;
707 }
708 
709 
TH1D * getRayleighHistogramFromFrequencyMHz(Double_t freqMHz)
Get pointer to rayleigh distribution of frequency closest to a particular frequency.
void fitAllRayleighHistograms()
Fits all the Rayeligh distributions.
static TString getRayleighFunctionText()
Generates the text that defines the Rayleigh function for TF1.
Int_t count
Number of waveforms that have been added to the AveragePowerSpectrum.
TGraph * makeAvePowSpecTGraph()
Creates a TGraph of the average power spectrum.
TGraph * makeAvePowSpecTGraph_dB()
Creates a TGraph of the average power spectrum with a dB scale.
Double_t rayleighAmplitudesRisingEdge[NUM_FREQS]
Amplitudes from fits to the leading edge of the Rayleigh distributions.
Double_t rayleighFitChiSquares[NUM_FREQS]
Chi squares of the Rayleigh fits.
TF1 * constructFitFromAmplitude(Int_t freqInd, Double_t amplitude)
Create a Rayleigh fit with a particular Rayleigh amplitude.
void rebinAllRayleighHistograms(Int_t rebinFactor)
Rebins all the stored Rayleigh distributions.
Double_t rayleighFitChiSquaresRisingEdge[NUM_FREQS]
Chi squares of the fit to the rising egde of the Rayleigh distributions.
Int_t rayleighNdfFullRange[NUM_FREQS]
NDFs from Rayleigh fits extended over the full range.
static TF1 * makeRayleighFunction(TString name, Double_t xMin, Double_t xMax)
Creates a TF1 with to fit a Rayeligh distribution.
Double_t rayleighAmplitudes[NUM_FREQS]
Fitted Rayleigh amplitudes.
Int_t rayleighNdfRisingEdgeAndHalfFalling[NUM_FREQS]
NDFs from fits to the leading and half the falling edge of the Rayleigh distributions.
double * getPowerSpectrum(int len, double *input, double dt, conventionFlag normFlag, int threadInd=0)
Creates the power spectrum in an array of doubles of length (len/2 + 1).
Definition: FancyFFTs.cxx:77
Double_t summedPowSpec[NUM_FREQS]
Sum of all power spectrum.
TF1 * getRayleighHistogramFit(Int_t freqInd)
Get Rayleigh fit to Rayleigh distribution from frequency index.
Double_t eventPowSpec[NUM_FREQS]
Power spectra for the last added event.
size_t add(TGraph *gr)
Function for the user to add the voltage/time waveform to all the stored averages.
void fitRayleighHistogramRisingEdge(Int_t freqInd)
Fit a Rayleigh histogram, up to the peak bin.
Double_t rayleighAmplitudesRisingEdgeAndHalfFalling[NUM_FREQS]
Amplitudes from fits to the leading and half the falling edge of the Rayleigh distributions.
Double_t deltaFMHz
Difference between frequency bins in the power spectrums.
Int_t getPeakBinOfHistogram(TH1D *h)
Finds the bin containing the maximum value of a TH1D.
Definition: RootTools.cxx:1141
void fitAllRayleighHistogramsRisingEdgeAndHalfFallingEdge()
Fits all the Rayeligh distributions, as far as the bin which is half the value of the peak bin...
Double_t xHigh[NUM_FREQS]
High end of fitted range of Rayleigh histograms.
void deleteRayleighDistributions()
Deletes all the Rayleigh histograms.
TH1D * getRayleighHistogram(Int_t freqInd)
Get Rayleigh distribution from frequency index.
void fitRayleighHistogramOverRange(Int_t freqInd, Double_t xLowVal, Double_t xHighVal, Double_t *rAmplitudes, Double_t *rChiSquares, Int_t *rNdf, Double_t *rChiSquaresFullRange, Int_t *rNdfFullRange)
Worker function called by all the other fitting functions.
TF1 * constructFitFromRayleighAmplitudeRisingEdge(Int_t freqInd)
Create a Rayleigh fit with stored Rayleigh amplitude, fit up to the peak bin.
TF1 * constructFitFromRayleighAmplitudeRisingEdgeAndHalfFalling(Int_t freqInd)
Create a Rayleigh fit with stored Rayleigh amplitude, fit past the peak to half the maximum value...
AveragePowerSpectrum()
Constructor.
Int_t rayleighNdfRisingEdge[NUM_FREQS]
NDFs from fits to the leading edge of the Rayleigh distributions.
void fitRayleighHistogramRisingEdgeAndHalfFallingEdge(Int_t freqInd)
Fit a Rayleigh histogram, past the peak up to half the maximum value.
TF1 * constructFitFromRayleighAmplitude(Int_t freqInd)
Create a Rayleigh fit with stored Rayleigh amplitude.
Double_t outliers[NUM_FREQS][MAX_NUM_OUTLIERS]
Used to store values that are much greater than the current Rayliegh histogram content.
Double_t xHighRisingEdgeAndHalfFalling[NUM_FREQS]
High end of fitted range of Rayleigh histograms up to half the maximum value past the peak bin...
void fitRayleighHistogram(Int_t freqInd)
Fit a Rayleigh histogram.
Double_t xHighRisingEdge[NUM_FREQS]
High end of fitted range of Rayleigh histograms up to peak bin.
TH2D * makeRayleigh2DHistogram()
Combine all the 1D rayleigh distribution histograms to a 2D histogram.
Double_t eventRayleighAmplitudes[NUM_FREQS]
Rayleigh amplitudes for the last added event.
Double_t rayleighFitChiSquaresRisingEdgeAndHalfFallingFullRange[NUM_FREQS]
Amplitudes from fits to the leading and half the falling edge of the Rayleigh distributions extended ...
Takes in waveforms and averages averages their power spectra.
Int_t rayleighNdfRisingEdgeAndHalfFallingFullRange[NUM_FREQS]
NDFs from fits to the leading and half the falling edge of the Rayleigh distributions extended over t...
Double_t rayleighFitChiSquaresRisingEdgeFullRange[NUM_FREQS]
Chi squares of the fit to the rising egde of the Rayleigh distributions extended over the full range...
Double_t rayleighFitChiSquaresFullRange[NUM_FREQS]
Chi squares of the Rayleigh fits extended over the full range.
void getEventRayleighAmplitudes(TGraph *gr)
Converts the stored power spectrum for the events and stores it in internal memory.
Double_t rayleighFitChiSquaresRisingEdgeAndHalfFalling[NUM_FREQS]
Chi squares of the fit to the leading and half the falling edge of the Rayleigh distributions.
Int_t rayleighNdfRisingEdgeFullRange[NUM_FREQS]
NDFs from fits to the leading edge of the Rayleigh distributions extended over the full range...
Int_t rayleighNdf[NUM_FREQS]
NDFs from Rayleigh fits.
void fitAllRayleighHistogramsRisingEdge()
Fits all the Rayeligh distributions, but only up to the peak bin.
Int_t numOutliers[NUM_FREQS]
Count of number of outliers in outliers array.
TH1D * hRayleighs[NUM_FREQS]
Histograms for Rayleigh distributions.