File indexing completed on 2025-12-16 09:28:13
0001 #include "waveform_fit_base.h"
0002 #include "crystal_ball_fit.h"
0003
0004 #include <map>
0005 #include <vector>
0006 #include <iostream>
0007
0008 #include <TF1.h>
0009 #include <TGraph.h>
0010 #include <TMath.h>
0011
0012 crystal_ball_fit::crystal_ball_fit() : waveform_fit_base{} {
0013 parameters[0] = 0;
0014 parameters[1] = 0;
0015 parameters[2] = 0;
0016 parameters[3] = 0;
0017 parameters[4] = 0;
0018 parameters[5] = 0;
0019
0020 saturated = false;
0021
0022 crystal_ball_function = new TF1("crystal_ball_function", this, &crystal_ball_fit::crystal_ball, 0, 10, 6);
0023 linear_function = new TF1("constant", "[0]", 0, 10);
0024 crystal_ball_graph = new TGraph();
0025 }
0026
0027 crystal_ball_fit::~crystal_ball_fit() {
0028 delete crystal_ball_function;
0029 delete crystal_ball_graph;
0030 }
0031
0032 void crystal_ball_fit::fit() {
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048 if (waveform.size() == 0) {
0049 std::cerr << "Waveform has not been set" << std::endl;
0050 return;
0051 }
0052 crystal_ball_function->SetRange(0, waveform.size());
0053
0054
0055 for (int i = 0; i < waveform.size(); i++) {
0056 crystal_ball_graph->SetPoint(i, i, waveform[i]);
0057 if (waveform[i] > 1000) {
0058 saturated = true;
0059 }
0060 }
0061
0062
0063 linear_function->SetParameter(0, parameters[5]);
0064 if (parameters.count(15) && parameters.count(25)) {
0065 linear_function->SetParLimits(0, parameters[15], parameters[25]);
0066 }
0067 crystal_ball_graph->Fit(linear_function, "Q");
0068 if (linear_function->GetChisquare() < 500) {
0069 E = 0;
0070 fit_ndf = linear_function->GetNDF();
0071 fit_chi2 = linear_function->GetChisquare();
0072 stale = false;
0073 return;
0074 }
0075
0076
0077 for (int i = 0; i < 6; i++) {
0078 crystal_ball_function->SetParameter(i, parameters[i]);
0079 if (parameters.count(i + 10) && parameters.count(i + 20)) {
0080 crystal_ball_function->SetParLimits(i, parameters[i + 10], parameters[i + 20]);
0081 }
0082 }
0083
0084 crystal_ball_graph->Fit(crystal_ball_function, "Q");
0085
0086
0087 E = crystal_ball_function->GetParameter(4);
0088 fit_ndf = crystal_ball_function->GetNDF();
0089 fit_chi2 = crystal_ball_function->GetChisquare();
0090
0091 stale = false;
0092 }
0093
0094 int crystal_ball_fit::get_pedestal() {
0095 if (stale) {
0096 return -1;
0097 }
0098 return crystal_ball_function->GetParameter(5);
0099 }
0100
0101 double crystal_ball_fit::crystal_ball(double *inputs, double *parameters) {
0102
0103
0104
0105
0106
0107
0108
0109
0110 double x = inputs[0];
0111
0112 double alpha = parameters[0];
0113 double n = parameters[1];
0114 double x_bar = parameters[2];
0115 double sigma = parameters[3];
0116 double N = parameters[4];
0117 double offset = parameters[5];
0118
0119 double A = pow(n / fabs(alpha), n) * exp(-0.5 * alpha * alpha);
0120 double B = n / fabs(alpha) - fabs(alpha);
0121
0122
0123
0124
0125 double ret_val;
0126 if ((x - x_bar) / sigma < alpha) {
0127
0128 ret_val = exp(-0.5 * (x - x_bar) * (x - x_bar) / (sigma * sigma));
0129 } else {
0130
0131 ret_val = A * pow(B + (x - x_bar) / sigma, -1 * n);
0132 }
0133 ret_val = N * ret_val + offset;
0134
0135 return ret_val;
0136 }