Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2026-07-16 08:11:27

0001 #include <algorithm>
0002 #include <cmath>
0003 #include <cctype>
0004 #include <iomanip>
0005 #include <iostream>
0006 #include <memory>
0007 #include <sstream>
0008 #include <string>
0009 #include <vector>
0010 
0011 #include <RooArgList.h>
0012 #include <RooFitResult.h>
0013 #include <RooRealVar.h>
0014 #include <TCanvas.h>
0015 #include <TFile.h>
0016 #include <TGaxis.h>
0017 #include <TH1.h>
0018 #include <TH1D.h>
0019 #include <TLatex.h>
0020 #include <TSystem.h>
0021 
0022 struct V0Config
0023 {
0024     std::string name;
0025     std::string input_dir;
0026     std::string cut_prefix;
0027     std::string output_prefix;
0028     std::string plot_label;
0029 };
0030 
0031 void draw1Dhistogram(TH1 *hist, bool logx, bool logy, std::string xtitle, std::string ytitle, std::vector<std::string> addinfo, std::string filename)
0032 {
0033     TCanvas *c = new TCanvas("c", "c", 800, 700);
0034     gPad->SetTopMargin(0.07);
0035     c->cd();
0036     c->SetLogx(logx);
0037     c->SetLogy(logy);
0038     hist->GetXaxis()->SetTitle(xtitle.c_str());
0039     hist->GetYaxis()->SetTitle(ytitle.c_str());
0040     hist->GetYaxis()->SetTitleOffset(1.6);
0041     hist->GetYaxis()->SetRangeUser((logy) ? hist->GetMinimum(0) * 0.5 : 0, (logy) ? hist->GetMaximum() * 50 : hist->GetMaximum() * 1.4);
0042     hist->Draw("e1");
0043 
0044     TLatex *latex = new TLatex();
0045     latex->SetTextSize(0.04);
0046     latex->SetTextAlign(12);
0047     latex->SetNDC();
0048     for (size_t i = 0; i < addinfo.size(); ++i)
0049     {
0050         latex->DrawLatex(0.2, 0.88 - i * 0.05, addinfo[i].c_str());
0051     }
0052     c->SaveAs(Form("%s.png", filename.c_str()));
0053     c->SaveAs(Form("%s.pdf", filename.c_str()));
0054     delete latex;
0055     delete c;
0056 }
0057 
0058 void replace_all(std::string &s, const std::string &from, const std::string &to)
0059 {
0060     size_t pos = 0;
0061     while ((pos = s.find(from, pos)) != std::string::npos)
0062     {
0063         s.replace(pos, from.size(), to);
0064         pos += to.size();
0065     }
0066 }
0067 
0068 std::string cut_to_dir_tag(std::string cut)
0069 {
0070     replace_all(cut, ">=", "geq");
0071     replace_all(cut, "<=", "leq");
0072     replace_all(cut, "==", "eq");
0073     replace_all(cut, "&&", "AND");
0074     replace_all(cut, "||", "OR");
0075     replace_all(cut, ">", "gt");
0076     replace_all(cut, "<", "lt");
0077 
0078     std::replace(cut.begin(), cut.end(), '.', 'p');
0079     std::replace(cut.begin(), cut.end(), '-', 'm');
0080     std::replace(cut.begin(), cut.end(), '+', 'p');
0081     return cut;
0082 }
0083 
0084 std::string pt_cut(const std::string &cut_prefix, double pt_min, double pt_max)
0085 {
0086     std::ostringstream oss;
0087     oss << std::fixed << std::setprecision(2)
0088         << cut_prefix << "_pT>=" << pt_min << "&&" << cut_prefix << "_pT<" << pt_max;
0089     return oss.str();
0090 }
0091 
0092 bool read_nsig(const std::string &filename, double &yield, double &error)
0093 {
0094     std::unique_ptr<TFile> file(TFile::Open(filename.c_str(), "READ"));
0095     if (!file || file->IsZombie())
0096     {
0097         std::cerr << "WARNING: cannot open " << filename << std::endl;
0098         return false;
0099     }
0100 
0101     RooFitResult *fitres = dynamic_cast<RooFitResult *>(file->Get("fitres"));
0102     if (!fitres)
0103     {
0104         std::cerr << "WARNING: fitres not found in " << filename << std::endl;
0105         return false;
0106     }
0107 
0108     const RooRealVar *nSig = dynamic_cast<const RooRealVar *>(fitres->floatParsFinal().find("nSig"));
0109     if (!nSig)
0110         nSig = dynamic_cast<const RooRealVar *>(fitres->constPars().find("nSig"));
0111     if (!nSig)
0112     {
0113         std::cerr << "WARNING: nSig not found in " << filename << std::endl;
0114         return false;
0115     }
0116 
0117     yield = nSig->getVal();
0118     error = nSig->getError();
0119     return true;
0120 }
0121 
0122 bool make_v0_config(std::string v0, V0Config &config)
0123 {
0124     std::transform(v0.begin(), v0.end(), v0.begin(), [](unsigned char c) { return std::tolower(c); });
0125 
0126     if (v0 == "lambda" || v0 == "lambda0")
0127     {
0128         config = {"lambda", "./figure_lambda_crosscheck", "Lambda0", "lambda", "#Lambda^{0}"};
0129         return true;
0130     }
0131     if (v0 == "kshort" || v0 == "ks" || v0 == "ks0" || v0 == "k_s0")
0132     {
0133         config = {"kshort", "./figure_kshort_crosscheck", "K_S0", "kshort", "K_{S}^{0}"};
0134         return true;
0135     }
0136 
0137     std::cerr << "ERROR: unsupported V0 species \"" << v0 << "\". Use \"lambda\", \"kshort\", or \"both\"." << std::endl;
0138     return false;
0139 }
0140 
0141 void get_one_v0_raw_yield(const V0Config &config)
0142 {
0143     const std::vector<double> pt_bins = {0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1.2, 1.3, 1.4, 1.5, 1.8, 2.1, 2.4, 2.7, 3.0, 4.0};
0144 
0145     std::vector<std::string> subdirs;
0146     void *dir = gSystem->OpenDirectory(config.input_dir.c_str());
0147     if (!dir)
0148     {
0149         std::cerr << "ERROR: cannot open " << config.input_dir << std::endl;
0150         return;
0151     }
0152 
0153     const char *entry = nullptr;
0154     while ((entry = gSystem->GetDirEntry(dir)))
0155     {
0156         const std::string dirname = entry;
0157         if (dirname == "." || dirname == "..")
0158             continue;
0159 
0160         const std::string rootfile = config.input_dir + "/" + dirname + "/fitresults.root";
0161         if (!gSystem->AccessPathName(rootfile.c_str()))
0162             subdirs.push_back(dirname);
0163     }
0164     gSystem->FreeDirectory(dir);
0165     std::sort(subdirs.begin(), subdirs.end());
0166 
0167     TGaxis::SetMaxDigits(3);
0168     TH1D *hYield = new TH1D(Form("h%sRawYieldPt", config.output_prefix.c_str()), Form(";%s p_{T} [GeV];Raw %s yield", config.plot_label.c_str(), config.plot_label.c_str()), pt_bins.size() - 1, pt_bins.data());
0169     hYield->Sumw2();
0170     std::vector<int> fit_counts(pt_bins.size() - 1, 0);
0171 
0172     std::cout << "\nRaw-yield summary for " << config.name << std::endl;
0173     for (size_t i = 0; i < pt_bins.size() - 1; ++i)
0174     {
0175         const double pt_min = pt_bins[i];
0176         const double pt_max = pt_bins[i + 1];
0177         const std::string pt_tag = cut_to_dir_tag(pt_cut(config.cut_prefix, pt_min, pt_max));
0178 
0179         std::vector<std::string> matching_phi_dirs;
0180         std::vector<std::string> matching_pt_dirs;
0181         for (const std::string &dirname : subdirs)
0182         {
0183             if (dirname.find(pt_tag) != 0)
0184                 continue;
0185 
0186             if (dirname.find(config.cut_prefix + "_phi") != std::string::npos)
0187                 matching_phi_dirs.push_back(dirname);
0188             else
0189                 matching_pt_dirs.push_back(dirname);
0190         }
0191 
0192         const std::vector<std::string> &dirs_to_sum = matching_phi_dirs.empty() ? matching_pt_dirs : matching_phi_dirs;
0193         double yield_sum = 0.0;
0194         double error2_sum = 0.0;
0195 
0196         for (const std::string &dirname : dirs_to_sum)
0197         {
0198             double yield = 0.0;
0199             double error = 0.0;
0200             const std::string rootfile = config.input_dir + "/" + dirname + "/fitresults.root";
0201             if (!read_nsig(rootfile, yield, error))
0202                 continue;
0203 
0204             yield_sum += yield;
0205             error2_sum += error * error;
0206         }
0207 
0208         hYield->SetBinContent(i + 1, yield_sum);
0209         hYield->SetBinError(i + 1, std::sqrt(error2_sum));
0210         fit_counts[i] = dirs_to_sum.size();
0211 
0212         std::cout << std::fixed << std::setprecision(2)
0213                   << pt_min << " <= pT < " << pt_max << ": "
0214                   << yield_sum << " +/- " << std::sqrt(error2_sum)
0215                   << " from " << dirs_to_sum.size() << " fit result file(s)" << std::endl;
0216     }
0217 
0218     std::cout << "\n| V0 | pT bin [GeV] | Raw yield | Fit uncertainty |\n"
0219               << "|---|---:|---:|---:|\n";
0220     for (size_t i = 0; i < pt_bins.size() - 1; ++i)
0221     {
0222         std::cout << std::fixed << std::setprecision(2)
0223                   << "| " << config.name << " | [" << pt_bins[i] << ", " << pt_bins[i + 1] << ") | "
0224                   << hYield->GetBinContent(i + 1) << " | "
0225                   << hYield->GetBinError(i + 1) << " |\n ";
0226     }
0227     std::cout << std::endl;
0228 
0229     const std::string output_name = config.output_prefix + "_yield_pt";
0230     TFile outfile((config.input_dir + "/" + output_name + ".root").c_str(), "RECREATE");
0231     hYield->Write();
0232     outfile.Close();
0233 
0234     draw1Dhistogram(hYield, false, false, config.plot_label + " p_{T} [GeV]", "Raw " + config.plot_label + " yield", {}, config.input_dir + "/" + output_name);
0235 }
0236 
0237 void getV0RawYield(std::string v0 = "lambda")
0238 {
0239     std::transform(v0.begin(), v0.end(), v0.begin(), [](unsigned char c) { return std::tolower(c); });
0240     if (v0 == "both" || v0 == "all")
0241     {
0242         V0Config lambda_config;
0243         V0Config kshort_config;
0244         if (make_v0_config("lambda", lambda_config))
0245             get_one_v0_raw_yield(lambda_config);
0246         if (make_v0_config("kshort", kshort_config))
0247             get_one_v0_raw_yield(kshort_config);
0248         return;
0249     }
0250 
0251     V0Config config;
0252     if (!make_v0_config(v0, config))
0253         return;
0254 
0255     get_one_v0_raw_yield(config);
0256 }