#include #include #include #include #include #include #include #include #include #include // ROOT #include "TFile.h" #include "TTree.h" #include "TH1D.h" #include "TH2D.h" #include "TCanvas.h" // Catima #include using namespace std; /* ========================= GLOBAL STRUCTURES ========================= */ struct Particle { int z; double mass_u; double emax; string name; }; map particles = { {"alpha", {2, 4.0026, 40, "alpha"}}, {"proton", {1, 1.0078, 20, "proton"}}, {"deuteron", {1, 2.0141, 30, "deuteron"}} }; /* ========================= INTERPOLATION STORAGE ========================= */ struct EnergyTable { vector x; vector E; }; map table_cache; /* Linear interpolation */ double interp(const vector& x, const vector& y, double xi) { if (xi <= x.front()) return y.front(); if (xi >= x.back()) return y.back(); auto it = upper_bound(x.begin(), x.end(), xi); int i = distance(x.begin(), it) - 1; double x0 = x[i], x1 = x[i+1]; double y0 = y[i], y1 = y[i+1]; return y0 + (y1 - y0) * (xi - x0) / (x1 - x0); } /* ========================= ENERGY TABLE GENERATION ========================= */ void make_E_vs_x(int z, double mass_u, double emax, string label, int npoints, double P_torr, double T) { double R = 8.3144; double p_pa = P_torr * 133.322; double molar_density = p_pa / (R * T); double m_he = 4.0026; double m_c = 12.0; double m_o = 15.9949; double m_mix = 0.96*m_he + 0.04*(m_c + 2*m_o); double rho = (molar_density * m_mix) / 1e6; catima::Material gas({ {m_he, 2, 0.96}, {m_c, 6, 0.04}, {m_o, 8, 0.08} }); gas.density(rho); catima::Projectile proj(mass_u, z); vector E(npoints); vector S(npoints); for (int i = 0; i < npoints; i++) { E[i] = 0.01 + i * (emax / npoints); proj.T(E[i] / mass_u); S[i] = catima::dedx(proj, gas) * rho; } reverse(E.begin(), E.end()); reverse(S.begin(), S.end()); vector x(npoints, 0.0); for (int i = 1; i < npoints; i++) { double invS = 1.0 / S[i]; x[i] = x[i-1] + 0.5 * (invS + 1.0/S[i-1]) * (E[i] - E[i-1]); } ofstream out("E_vs_x_" + label + ".dat"); for (int i = 0; i < npoints; i++) { out << x[i] << "\t" << E[i] << "\n"; } cout << "Saved E_vs_x_" << label << ".dat\n"; } /* ========================= LOAD TABLE ========================= */ EnergyTable load_table(string fname) { EnergyTable t; ifstream in(fname); double x, E; while (in >> x >> E) { t.x.push_back(x); t.E.push_back(E); } return t; } /* ========================= GET TABLE ========================= */ EnergyTable& get_table(string particle) { if (!table_cache.count(particle)) { table_cache[particle] = load_table("E_vs_x_" + particle + ".dat"); } return table_cache[particle]; } /* ========================= ENERGY FUNCTIONS ========================= */ double energy_loss(string p, double Ei, double dx) { auto &t = get_table(p); double xi = interp(t.E, t.x, Ei); double xf = xi + dx; double Ef = interp(t.x, t.E, xf); return max(Ef, 0.0); } double energy_reconstruction(string p, double Ef, double dx) { auto &t = get_table(p); double xf = interp(t.E, t.x, Ef); double xi = xf - dx; double Ei = interp(t.x, t.E, xi); return max(Ei, 0.0); } double energy_distance(string p, double Ei, double Ef) { auto &t = get_table(p); double xi = interp(t.E, t.x, Ei); double xf = interp(t.E, t.x, Ef); return fabs(xf - xi); } /* ========================= ROOT FILE ANALYSIS ========================= */ void process_file(string filename) { TFile f(filename.c_str()); TTree *tree = (TTree*)f.Get("tree"); double Tb, thetab, sx3Z; tree->SetBranchAddress("Tb", &Tb); tree->SetBranchAddress("thetab", &thetab); tree->SetBranchAddress("sx3Z", &sx3Z); vector Ei, theta, sx3; Long64_t n = tree->GetEntries(); for (Long64_t i = 0; i < n; i++) { tree->GetEntry(i); double th = thetab * M_PI / 180.0; if (sin(th) == 0) continue; Ei.push_back(Tb); theta.push_back(th); sx3.push_back(sx3Z); } cout << "Processed " << Ei.size() << " events\n"; } /* ========================= MAIN CLI (simplified) ========================= */ int main() { string cmd; cout << "C++ PCEnergy Shell\n"; while (true) { cout << ">> "; getline(cin, cmd); if (cmd == "exit") break; if (cmd.rfind("make table", 0) == 0) { string name = cmd.substr(11); auto p = particles[name]; make_E_vs_x(p.z, p.mass_u, p.emax, p.name, 500, 400, 293.15); } else if (cmd.rfind("energy loss", 0) == 0) { cout << "Use API call version in compiled mode\n"; } else { cout << "Unknown command\n"; } } return 0; }