File indexing completed on 2025-08-05 08:14:56
0001 #include <TFile.h>
0002 #include <TH1F.h>
0003 #include <TTree.h>
0004 #include <TSystem.h>
0005 #include <vector>
0006 #include <string>
0007 #include <regex>
0008
0009
0010 #include "RooRealVar.h"
0011 #include "RooDataHist.h"
0012 #include "RooLandau.h"
0013 #include "RooGaussian.h"
0014 #include "RooFFTConvPdf.h"
0015 #include "RooPlot.h"
0016 #include "RooFitResult.h"
0017
0018 using namespace RooFit;
0019
0020 const int NUM_CHANNELS = 744;
0021 const double MIN_ENTRIES = 50;
0022
0023 struct ChannelResult {
0024 TH1F* hist = nullptr;
0025 RooPlot* plot = nullptr;
0026 RooRealVar* x = nullptr;
0027 RooRealVar* ml = nullptr;
0028 RooRealVar* sl = nullptr;
0029 RooRealVar* mg = nullptr;
0030 RooRealVar* sg = nullptr;
0031 RooLandau* landau = nullptr;
0032 RooGaussian* gauss = nullptr;
0033 RooFFTConvPdf* pdf = nullptr;
0034 double mpv = -1.0;
0035 double gauss_sigma = -1.0;
0036 double chi2_ndf = -1.0;
0037 };
0038
0039 int extract_run_number(const std::string& filename) {
0040 std::regex pattern("run[_-]?(\\d+).*\\.root");
0041 std::smatch match;
0042 if (std::regex_search(filename, match, pattern)) {
0043 try {
0044 return std::stoi(match[1].str());
0045 } catch (...) {
0046 return -1;
0047 }
0048 }
0049 return -1;
0050 }
0051
0052 ChannelResult process_channel(TH1* hist, int ch) {
0053 ChannelResult result;
0054 if (!hist || hist->GetEntries() < MIN_ENTRIES) return result;
0055
0056
0057 int max_bin = -1;
0058 double max_content = -1;
0059 const double ADC_MIN = 40.0;
0060
0061 for(int bin = 1; bin <= hist->GetNbinsX(); bin++) {
0062 double center = hist->GetXaxis()->GetBinCenter(bin);
0063 double content = hist->GetBinContent(bin);
0064 if(center >= ADC_MIN && content > max_content) {
0065 max_content = content;
0066 max_bin = bin;
0067 }
0068 }
0069
0070 if(max_bin == -1) return result;
0071
0072 double x_peak = hist->GetXaxis()->GetBinCenter(max_bin);
0073 double y_peak = hist->GetBinContent(max_bin);
0074
0075
0076 double half_max = y_peak/2.0;
0077 double x_left = x_peak, x_right = x_peak;
0078
0079
0080 for(int bin = max_bin; bin >= 1; bin--) {
0081 double center = hist->GetXaxis()->GetBinCenter(bin);
0082 if(center < ADC_MIN) break;
0083
0084 if(hist->GetBinContent(bin) < half_max) {
0085 x_left = center;
0086 break;
0087 }
0088 }
0089
0090
0091
0092 for(int bin = max_bin; bin <= hist->GetNbinsX(); bin++) {
0093 if(hist->GetBinContent(bin) < half_max) {
0094 x_right = hist->GetXaxis()->GetBinCenter(bin);
0095 break;
0096 }
0097 }
0098
0099
0100 double fwhm = x_right - x_left;
0101 double sigma_est = fwhm/2.355;
0102
0103
0104 double fit_lo = x_peak - 2*sigma_est;
0105 double fit_hi = x_peak + 3*sigma_est;
0106
0107 fit_lo = std::max(fit_lo, ADC_MIN);
0108
0109
0110 double h_min = hist->GetXaxis()->GetXmin();
0111 double h_max = hist->GetXaxis()->GetXmax();
0112 fit_lo = std::max(fit_lo, h_min);
0113 fit_hi = std::min(fit_hi, h_max);
0114
0115
0116 if((fit_hi - fit_lo) < 20) {
0117 fit_lo = x_peak - 40;
0118 fit_hi = x_peak + 40;
0119 fit_lo = std::max(fit_lo, ADC_MIN);
0120 fit_lo = std::max(fit_lo, h_min);
0121 fit_hi = std::min(fit_hi, h_max);
0122 }
0123
0124
0125 result.x = new RooRealVar(Form("x_%d", ch), "ADC", fit_lo, fit_hi);
0126 result.ml = new RooRealVar(Form("ml_%d", ch), "Landau MPV", x_peak, fit_lo, fit_hi);
0127 result.sl = new RooRealVar(Form("sl_%d", ch), "Landau #sigma", 5, 0.1, 50);
0128 result.mg = new RooRealVar(Form("mg_%d", ch), "Gauss #mu", 0, -50, 50);
0129 result.sg = new RooRealVar(Form("sg_%d", ch), "Gauss #sigma", 3, 0.1, 20);
0130
0131 RooDataHist dataHist(Form("data_%d", ch), "Data", *result.x, hist);
0132 result.landau = new RooLandau(Form("landau_%d", ch), "", *result.x, *result.ml, *result.sl);
0133 result.gauss = new RooGaussian(Form("gauss_%d", ch), "", *result.x, *result.mg, *result.sg);
0134
0135 result.x->setBins(4000, "cache");
0136 result.pdf = new RooFFTConvPdf(Form("pdf_%d", ch), "Landau#otimesGauss",
0137 *result.x, *result.landau, *result.gauss);
0138
0139 RooFitResult* fit_res = result.pdf->fitTo(dataHist,
0140 Save(true),
0141 PrintLevel(-1),
0142 Range(fit_lo, fit_hi),
0143 NumCPU(4));
0144
0145 if (fit_res && fit_res->status() == 0) {
0146 result.plot = result.x->frame(Title("Pulse Height Spectrum"));
0147 dataHist.plotOn(result.plot);
0148 result.pdf->plotOn(result.plot);
0149
0150
0151 const int steps = 500;
0152 double step = (fit_hi - fit_lo)/steps;
0153 double best_x = fit_lo;
0154 double max_val = 0;
0155
0156 for(int i=0; i<steps; i++) {
0157 double x_val = fit_lo + i*step;
0158 result.x->setVal(x_val);
0159 double val = result.pdf->getVal();
0160
0161 if(val > max_val) {
0162 max_val = val;
0163 best_x = x_val;
0164 }
0165 }
0166
0167
0168
0169
0170 double fit_lo = result.x->getMin();
0171 double fit_hi = result.x->getMax();
0172
0173 int bin_lo = hist->FindBin(fit_lo);
0174 int bin_hi = hist->FindBin(fit_hi);
0175
0176 int nBins = bin_hi - bin_lo + 1;
0177
0178
0179 double chi2 = 0;
0180
0181 int nParams = fit_res->floatParsFinal().getSize();
0182
0183 for(int bin=bin_lo; bin<=bin_hi; bin++) {
0184 double x = hist->GetXaxis()->GetBinCenter(bin);
0185 double data = hist->GetBinContent(bin);
0186 double error = hist->GetBinError(bin);
0187 result.x->setVal(x);
0188 double model = result.pdf->getVal() * hist->GetBinWidth(x) * hist->GetEntries();
0189
0190 if(error > 0) {
0191 chi2 += pow(data - model, 2) / pow(error, 2);
0192 }
0193 }
0194
0195 int ndf = nBins - nParams;
0196 double chi2_ndf = (ndf > 0) ? chi2/ndf : -1;
0197
0198
0199 result.chi2_ndf = chi2_ndf;
0200
0201 result.mpv = best_x;
0202 result.gauss_sigma = result.sg->getVal();
0203 }
0204
0205 delete fit_res;
0206 return result;
0207 }
0208
0209 void analyze_single_run_FWHM(const char* input_file = "/sphenix/tg/tg01/bulk/ecroft/sEPD/spectra_zvtx_cut/run_47869/run_47869.root_histos.root", const char* output_file = "/sphenix/user/ecroft/sEPDChannelAnalysis/analyze_single_channel_test.root") {
0210 TFile* in_file = TFile::Open(input_file, "READ");
0211 if (!in_file || in_file->IsZombie()) return;
0212
0213 TFile out_file(output_file, "RECREATE");
0214 int run_number = extract_run_number(input_file);
0215
0216 if (run_number >= 0) {
0217 out_file.mkdir(Form("run_%d", run_number));
0218 out_file.cd(Form("run_%d", run_number));
0219
0220 for (int ch = 0; ch < NUM_CHANNELS; ch++) {
0221 TH1F* hist = dynamic_cast<TH1F*>(in_file->Get(Form("channel%d", ch)));
0222 if (!hist) continue;
0223
0224 ChannelResult result = process_channel(hist, ch);
0225 if (!result.plot) continue;
0226
0227 out_file.mkdir(Form("run_%d/ch_%04d", run_number, ch));
0228 out_file.cd(Form("run_%d/ch_%04d", run_number, ch));
0229
0230 hist->Write("original_hist");
0231 result.plot->Write("fit_plot");
0232
0233
0234 TVectorD params(3);
0235 params[0] = result.mpv;
0236 params[1] = result.gauss_sigma;
0237 params[2] = result.chi2_ndf;
0238 params.Write("fit_parameters");
0239
0240
0241 delete result.plot;
0242 delete result.x;
0243 delete result.ml;
0244 delete result.sl;
0245 delete result.mg;
0246 delete result.sg;
0247 delete result.landau;
0248 delete result.gauss;
0249 delete result.pdf;
0250 }
0251 }
0252
0253 std::cout << "Done!" << std::endl;
0254
0255 in_file->Close();
0256 delete in_file;
0257 out_file.Close();
0258 }