yaml
This commit is contained in:
parent
729444bdcf
commit
30a1621023
|
|
@ -20,13 +20,18 @@
|
||||||
|
|
||||||
class EnergyLossTable {
|
class EnergyLossTable {
|
||||||
public:
|
public:
|
||||||
|
static std::string& TableDir() { static std::string dir = "../ELoss/"; return dir; }
|
||||||
|
static void SetTableDir(const std::string& dir) {
|
||||||
|
TableDir() = dir.empty() || dir.back() == '/' ? dir : dir + "/";
|
||||||
|
}
|
||||||
|
|
||||||
static EnergyLossTable& Get(const std::string& particle, const std::string& medium) {
|
static EnergyLossTable& Get(const std::string& particle, const std::string& medium) {
|
||||||
std::string key = medium + "_" + particle;
|
std::string key = medium + "_" + particle;
|
||||||
static std::map<std::string, EnergyLossTable*> cache;
|
static std::map<std::string, EnergyLossTable*> cache;
|
||||||
auto it = cache.find(key);
|
auto it = cache.find(key);
|
||||||
if (it != cache.end()) return *it->second;
|
if (it != cache.end()) return *it->second;
|
||||||
|
|
||||||
std::string path = "../ELoss/" + medium + "Loss/E_vs_x_" + particle + ".dat";
|
std::string path = TableDir() + medium + "Loss/E_vs_x_" + particle + ".dat";
|
||||||
EnergyLossTable* table = new EnergyLossTable(path);
|
EnergyLossTable* table = new EnergyLossTable(path);
|
||||||
cache[key] = table;
|
cache[key] = table;
|
||||||
return *table;
|
return *table;
|
||||||
|
|
|
||||||
|
|
@ -69,6 +69,6 @@ EventBuilder: EventBuilder.cpp ClassData.h fsuReader.h Hit.h
|
||||||
@echo "--------- making EventBuilder"
|
@echo "--------- making EventBuilder"
|
||||||
$(CXX) $(CXXFLAGS) EventBuilder.cpp -o EventBuilder $(LDFLAGS)
|
$(CXX) $(CXXFLAGS) EventBuilder.cpp -o EventBuilder $(LDFLAGS)
|
||||||
|
|
||||||
AnasenMS: anasenMS.cpp Kinematics.h constant.h Isotope.h ClassTransfer.h ClassSX3.h ClassQQQ.h ClassPW.h ClassAnasen.h EnergyLoss.h AutoHist2D.h anasen_anode_cathode_hyperboloids.h
|
AnasenMS: anasenMS.cpp SimConfig.h Kinematics.h constant.h Isotope.h ClassTransfer.h ClassSX3.h ClassQQQ.h ClassPW.h ClassAnasen.h EnergyLoss.h AutoHist2D.h anasen_anode_cathode_hyperboloids.h
|
||||||
@echo "--------- making ANASEN Monte Carlo"
|
@echo "--------- making ANASEN Monte Carlo"
|
||||||
$(CXX) $(CXXFLAGS) anasenMS.cpp -o AnasenMS $(LDFLAGS)
|
$(CXX) $(CXXFLAGS) anasenMS.cpp -o AnasenMS $(LDFLAGS)
|
||||||
142
Armory/SimConfig.h
Normal file
142
Armory/SimConfig.h
Normal file
|
|
@ -0,0 +1,142 @@
|
||||||
|
#ifndef SIMCONFIG_H
|
||||||
|
#define SIMCONFIG_H
|
||||||
|
|
||||||
|
// Minimal YAML-subset reader for simulation configs, plus dated history logging.
|
||||||
|
// Supported: nested maps by indentation, "key: value", inline lists "[a, b]", "#" comments.
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
|
#include <fstream>
|
||||||
|
#include <sstream>
|
||||||
|
#include <iostream>
|
||||||
|
#include <cstdlib>
|
||||||
|
#include <ctime>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
class SimConfig {
|
||||||
|
public:
|
||||||
|
std::string path; // file the config was loaded from
|
||||||
|
std::string rawText; // full file contents, used for history/ROOT embedding
|
||||||
|
bool loaded = false;
|
||||||
|
|
||||||
|
bool Load(const std::string& file) {
|
||||||
|
std::ifstream in(file);
|
||||||
|
if (!in) return false;
|
||||||
|
path = file;
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << in.rdbuf();
|
||||||
|
rawText = ss.str();
|
||||||
|
Parse(rawText);
|
||||||
|
loaded = true;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Has(const std::string& key) const { return values_.count(key) > 0; }
|
||||||
|
|
||||||
|
std::string Str(const std::string& key, const std::string& def) const {
|
||||||
|
auto it = values_.find(key);
|
||||||
|
return it == values_.end() ? def : it->second;
|
||||||
|
}
|
||||||
|
double Double(const std::string& key, double def) const {
|
||||||
|
auto it = values_.find(key);
|
||||||
|
return it == values_.end() ? def : std::atof(it->second.c_str());
|
||||||
|
}
|
||||||
|
int Int(const std::string& key, int def) const {
|
||||||
|
auto it = values_.find(key);
|
||||||
|
return it == values_.end() ? def : std::atoi(it->second.c_str());
|
||||||
|
}
|
||||||
|
bool Bool(const std::string& key, bool def) const {
|
||||||
|
auto it = values_.find(key);
|
||||||
|
if (it == values_.end()) return def;
|
||||||
|
return it->second == "true" || it->second == "yes" || it->second == "1";
|
||||||
|
}
|
||||||
|
std::vector<double> DoubleList(const std::string& key, const std::vector<double>& def) const {
|
||||||
|
auto it = values_.find(key);
|
||||||
|
if (it == values_.end()) return def;
|
||||||
|
std::vector<double> out;
|
||||||
|
for (auto& s : SplitList(it->second)) out.push_back(std::atof(s.c_str()));
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Saves a timestamped copy under historyDir and appends a line to historyDir/index.log.
|
||||||
|
// Returns the path of the saved copy ("" on failure).
|
||||||
|
std::string LogToHistory(const std::string& historyDir, int numEvents,
|
||||||
|
const std::string& outputFile) const {
|
||||||
|
mkdir(historyDir.c_str(), 0755);
|
||||||
|
char stamp[32];
|
||||||
|
std::time_t now = std::time(nullptr);
|
||||||
|
std::strftime(stamp, sizeof(stamp), "%Y-%m-%d_%H%M%S", std::localtime(&now));
|
||||||
|
std::string copy = historyDir + "/" + stamp + ".yaml";
|
||||||
|
std::ofstream out(copy);
|
||||||
|
if (!out) return "";
|
||||||
|
out << "# run: " << stamp << " events: " << numEvents << " output: " << outputFile
|
||||||
|
<< " source: " << (loaded ? path : "<built-in defaults>") << "\n"
|
||||||
|
<< rawText;
|
||||||
|
if (!rawText.empty() && rawText.back() != '\n') out << "\n";
|
||||||
|
std::ofstream idx(historyDir + "/index.log", std::ios::app);
|
||||||
|
idx << stamp << "\t" << numEvents << "\t" << outputFile << "\t" << copy << "\n";
|
||||||
|
return copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::map<std::string, std::string> values_; // dotted key -> raw scalar/list text
|
||||||
|
|
||||||
|
static std::string Trim(const std::string& s) {
|
||||||
|
size_t a = s.find_first_not_of(" \t\r");
|
||||||
|
if (a == std::string::npos) return "";
|
||||||
|
size_t b = s.find_last_not_of(" \t\r");
|
||||||
|
return s.substr(a, b - a + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string StripQuotes(const std::string& s) {
|
||||||
|
if (s.size() >= 2 && ((s.front() == '"' && s.back() == '"') || (s.front() == '\'' && s.back() == '\'')))
|
||||||
|
return s.substr(1, s.size() - 2);
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::vector<std::string> SplitList(const std::string& s) {
|
||||||
|
std::string t = Trim(s);
|
||||||
|
if (!t.empty() && t.front() == '[') t.erase(0, 1);
|
||||||
|
if (!t.empty() && t.back() == ']') t.pop_back();
|
||||||
|
std::vector<std::string> out;
|
||||||
|
std::stringstream ss(t);
|
||||||
|
std::string item;
|
||||||
|
while (std::getline(ss, item, ',')) {
|
||||||
|
item = Trim(item);
|
||||||
|
if (!item.empty()) out.push_back(StripQuotes(item));
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Parse(const std::string& text) {
|
||||||
|
std::vector<std::pair<int, std::string>> stack; // (indent, key)
|
||||||
|
std::stringstream ss(text);
|
||||||
|
std::string line;
|
||||||
|
while (std::getline(ss, line)) {
|
||||||
|
// drop comments (a '#' outside quotes)
|
||||||
|
bool inQ = false;
|
||||||
|
char q = 0;
|
||||||
|
for (size_t i = 0; i < line.size(); i++) {
|
||||||
|
char c = line[i];
|
||||||
|
if (inQ) { if (c == q) inQ = false; }
|
||||||
|
else if (c == '"' || c == '\'') { inQ = true; q = c; }
|
||||||
|
else if (c == '#') { line.erase(i); break; }
|
||||||
|
}
|
||||||
|
if (Trim(line).empty()) continue;
|
||||||
|
int indent = line.find_first_not_of(' ');
|
||||||
|
size_t colon = line.find(':', indent);
|
||||||
|
if (colon == std::string::npos) continue;
|
||||||
|
std::string key = Trim(line.substr(indent, colon - indent));
|
||||||
|
std::string val = Trim(line.substr(colon + 1));
|
||||||
|
while (!stack.empty() && stack.back().first >= indent) stack.pop_back();
|
||||||
|
std::string full;
|
||||||
|
for (auto& p : stack) full += p.second + ".";
|
||||||
|
full += key;
|
||||||
|
if (val.empty()) stack.push_back({indent, key});
|
||||||
|
else values_[full] = StripQuotes(val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -29,6 +29,8 @@
|
||||||
#include "TBranch.h"
|
#include "TBranch.h"
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include "TNamed.h"
|
||||||
|
#include "SimConfig.h" // YAML config + dated history
|
||||||
bool quit=false;
|
bool quit=false;
|
||||||
void handler(int sig){
|
void handler(int sig){
|
||||||
quit=true;
|
quit=true;
|
||||||
|
|
@ -149,30 +151,57 @@ int main(int argc, char **argv){
|
||||||
printf("=== ANASEN Monte Carlo ===\n");
|
printf("=== ANASEN Monte Carlo ===\n");
|
||||||
printf("=========================================\n");
|
printf("=========================================\n");
|
||||||
|
|
||||||
// number of events can be overridden from command line
|
// optional "--config file.yaml"; stripped from argv so positional args keep working
|
||||||
int numEvent = 1000000;
|
std::string configPath = "anasen_config.yaml";
|
||||||
if( argc >= 2 ) numEvent = atoi(argv[1]);
|
for( int a = 1; a < argc; a++ ){
|
||||||
|
if( strcmp(argv[a], "--config") == 0 && a + 1 < argc ){
|
||||||
|
configPath = argv[a+1];
|
||||||
|
for( int k = a; k + 2 < argc; k++ ) argv[k] = argv[k+2];
|
||||||
|
argc -= 2;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
SimConfig cfg;
|
||||||
|
if( cfg.Load(configPath) ) printf("Loaded configuration: %s\n", configPath.c_str());
|
||||||
|
else printf("Config %s not found, using built-in defaults\n", configPath.c_str());
|
||||||
|
|
||||||
|
// number of events: config value, overridden by first command-line argument
|
||||||
|
int numEvent = cfg.Int("simulation.events", 1000000);
|
||||||
|
if( argc >= 2 && atoi(argv[1]) > 0 ) numEvent = atoi(argv[1]);
|
||||||
|
if( cfg.Int("simulation.seed", -1) >= 0 ) gRandom->SetSeed(cfg.Int("simulation.seed", -1));
|
||||||
TransferReaction transfer;
|
TransferReaction transfer;
|
||||||
|
|
||||||
// Register signal handler
|
// Register signal handler
|
||||||
std::signal(SIGINT, handler);
|
std::signal(SIGINT, handler);
|
||||||
|
|
||||||
//To set beam energy loss, use energy loss app, and create table with target isotope, set Initial beam energy as max energy
|
//To set beam energy loss, use energy loss app, and create table with target isotope, set Initial beam energy as max energy
|
||||||
transfer.SetA(1, 1, 0); // 22Mg projectile
|
const auto rxA = cfg.DoubleList("reaction.projectile", {1, 1});
|
||||||
transfer.Seta(4, 2); // 4He target
|
const auto rxa = cfg.DoubleList("reaction.target", {4, 2});
|
||||||
transfer.Setb(4, 2); // outgoing proton from the primary transfer
|
const auto rxb = cfg.DoubleList("reaction.light_ejectile", {4, 2});
|
||||||
transfer.SetB(1, 1); // 30Si* heavy product
|
const auto rxB = cfg.DoubleList("reaction.heavy_recoil", {1, 1});
|
||||||
double beamE = 7; //56.1
|
transfer.SetA((int)rxA[0], (int)rxA[1], 0);
|
||||||
|
transfer.Seta((int)rxa[0], (int)rxa[1]);
|
||||||
|
transfer.Setb((int)rxb[0], (int)rxb[1]);
|
||||||
|
transfer.SetB((int)rxB[0], (int)rxB[1]);
|
||||||
|
double beamE = cfg.Double("beam.energy_MeV", 7);
|
||||||
|
const double beamEMin = cfg.Double("beam.min_energy_MeV", 6.56);
|
||||||
|
const std::string lightMedium = cfg.Str("eloss.light_medium", "He");
|
||||||
|
EnergyLossTable::SetTableDir(cfg.Str("eloss.table_dir", "../ELoss/"));
|
||||||
const ReactionConfig reactionConfig = transfer.GetRectionConfig();
|
const ReactionConfig reactionConfig = transfer.GetRectionConfig();
|
||||||
const double beamA = reactionConfig.beamA; // mass number of 14N beam
|
const double beamA = reactionConfig.beamA; // mass number of 14N beam
|
||||||
|
const double beamZ = reactionConfig.beamZ; // atomic number of 14N beam
|
||||||
|
const double targetA = reactionConfig.targetA; // mass number of target
|
||||||
|
const double targetZ = reactionConfig.targetZ; // atomic number of target
|
||||||
|
|
||||||
// Excited state lists (projectile and heavy-product excitation states)
|
// Excited state lists (projectile and heavy-product excitation states)
|
||||||
std::vector<float> ExAList = {0}; // Beam excited energy
|
const auto exAD = cfg.DoubleList("reaction.projectile_excitation_MeV", {0});
|
||||||
std::vector<float> ExList = {0};//{0, 2.235, 3.498, 3.774, 4.831, 4.809, 5.279, 5.614, 5.951, 6.550}; // a/p aluminum
|
const auto exBD = cfg.DoubleList("reaction.heavy_excitation_MeV", {0});
|
||||||
//std::vector<float> ExList = {0.84, 1.01, 2.21, 2.73, 2.98, 3};
|
std::vector<float> ExAList(exAD.begin(), exAD.end());
|
||||||
|
std::vector<float> ExList(exBD.begin(), exBD.end());
|
||||||
|
|
||||||
TGraph* elossBeam = LoadELoss("../ELoss/HeLoss/E_vs_x_proton.dat"); // x = path length (cm), y = beam energy (MeV)
|
const std::string beamTable = cfg.Str("eloss.beam_table", "../ELoss/HeLoss/E_vs_x_proton.dat");
|
||||||
TGraph* sigmaXBeam = LoadSigmaXVsEnergy("../ELoss/HeLoss/E_vs_x_proton.dat"); // x = beam energy (MeV), y = distance straggle sigma_x (cm)
|
TGraph* elossBeam = LoadELoss(beamTable); // x = path length (cm), y = beam energy (MeV)
|
||||||
|
TGraph* sigmaXBeam = LoadSigmaXVsEnergy(beamTable); // x = beam energy (MeV), y = distance straggle sigma_x (cm)
|
||||||
//TGraph* sigmaABeam = LoadSigmaAVsEnergy("../ELoss/HeLoss/E_vs_x_Al-27.dat"); // x = beam energy (MeV), y = distance straggle sigma_a (cm)
|
//TGraph* sigmaABeam = LoadSigmaAVsEnergy("../ELoss/HeLoss/E_vs_x_Al-27.dat"); // x = beam energy (MeV), y = distance straggle sigma_a (cm)
|
||||||
// Build a temporary inverse (energy -> path) to locate the path at beamE.
|
// Build a temporary inverse (energy -> path) to locate the path at beamE.
|
||||||
TGraph* elossBeamInverseRaw = new TGraph(elossBeam->GetN());
|
TGraph* elossBeamInverseRaw = new TGraph(elossBeam->GetN());
|
||||||
|
|
@ -210,7 +239,7 @@ int main(int argc, char **argv){
|
||||||
const int kMHeavy = reactionConfig.recoilHeavyA; // mass number of heavy product
|
const int kMHeavy = reactionConfig.recoilHeavyA; // mass number of heavy product
|
||||||
|
|
||||||
// Nuclear masses are in MeV/c^2; cache them rather than rereading mass20.txt per event.
|
// Nuclear masses are in MeV/c^2; cache them rather than rereading mass20.txt per event.
|
||||||
const Isotope al27Iso(27, 13);
|
const Isotope al27Iso(beamZ, beamA);
|
||||||
const Isotope alphaIso(4, 2);
|
const Isotope alphaIso(4, 2);
|
||||||
|
|
||||||
//const int kZBeam = reactionConfig.beamZ; // atomic number of beam
|
//const int kZBeam = reactionConfig.beamZ; // atomic number of beam
|
||||||
|
|
@ -236,18 +265,22 @@ int main(int argc, char **argv){
|
||||||
|
|
||||||
//TGraph* elossLight = LoadELoss("../ELoss/HeLoss/E_vs_x_" + b + ".dat");
|
//TGraph* elossLight = LoadELoss("../ELoss/HeLoss/E_vs_x_" + b + ".dat");
|
||||||
// define vertex position uniform distribution ranges (mm)
|
// define vertex position uniform distribution ranges (mm)
|
||||||
double vertexXRange[2] = { -1.75, 1.75}; // mm - 5, 5// 2.5
|
const auto vx = cfg.DoubleList("beam.vertex_x_mm", {-1.75, 1.75});
|
||||||
double vertexYRange[2] = { -1.75, 1.75}; // -5, 5
|
const auto vy = cfg.DoubleList("beam.vertex_y_mm", {-1.75, 1.75});
|
||||||
double vertexZRange[2] = { -174.3, 174.3}; // -174.3, 174.3 (full length of gas volume, centered at 0)
|
const auto vz = cfg.DoubleList("beam.vertex_z_mm", {-174.3, 174.3});
|
||||||
const double beamEntranceZ = -280 - 174.3; //vertexZRange[0]; // mm, assumed beam entrance into the gas
|
double vertexXRange[2] = { vx[0], vx[1] }; // mm
|
||||||
|
double vertexYRange[2] = { vy[0], vy[1] };
|
||||||
|
double vertexZRange[2] = { vz[0], vz[1] }; // full length of gas volume
|
||||||
|
const double beamEntranceZ = cfg.Double("beam.entrance_z_mm", -280 - 174.3); // mm, beam entrance into the gas
|
||||||
|
|
||||||
// detector resolution / uncertainty parameters
|
// detector resolution / uncertainty parameters
|
||||||
double sigmaSX3_W = -1; // mm, if < 0 use mid-point (no spread in SX3 horizontal dimension)
|
double sigmaSX3_W = cfg.Double("resolution.sx3_sigma_w_mm", 2); // mm
|
||||||
double sigmaSX3_L = -1; // mm, vertical spread for SX3
|
double sigmaSX3_L = cfg.Double("resolution.sx3_sigma_l_mm", 2); // mm
|
||||||
double sigmaPW_A = 0; // normalized anode uncertainty term (0-1)
|
double sigmaPW_A = cfg.Double("resolution.pw_anode_sigma", 0); // normalized anode uncertainty term (0-1)
|
||||||
double sigmaPW_C = 0; // normalized cathode uncertainty term (0-1)
|
double sigmaPW_C = cfg.Double("resolution.pw_cathode_sigma", 0); // normalized cathode uncertainty term (0-1)
|
||||||
|
const double anodeSigma = cfg.Double("resolution.anode_position_sigma_mm", 2.3);
|
||||||
|
const double qqqSigmaR = cfg.Double("resolution.qqq_sigma_r_mm", 2);
|
||||||
|
const double qqqSigmaPhi = cfg.Double("resolution.qqq_sigma_phi_mm", 2);
|
||||||
|
|
||||||
// status printout
|
// status printout
|
||||||
printf("------------ Vertex :\n");
|
printf("------------ Vertex :\n");
|
||||||
|
|
@ -285,9 +318,12 @@ int main(int argc, char **argv){
|
||||||
QQQ * qqq = anasen->GetQQQ(); // optional QQQ detector part, not used in this simulation but can be enabled for visualization
|
QQQ * qqq = anasen->GetQQQ(); // optional QQQ detector part, not used in this simulation but can be enabled for visualization
|
||||||
|
|
||||||
// output file + trees
|
// output file + trees
|
||||||
TString saveFileName = "SimAnasen1.root";
|
TString saveFileName = cfg.Str("simulation.output_file", "SimAnasen1.root").c_str();
|
||||||
|
const std::string histCopy = cfg.LogToHistory(cfg.Str("simulation.history_dir", "config_history"), numEvent, saveFileName.Data());
|
||||||
|
if( !histCopy.empty() ) printf("Configuration logged to %s\n", histCopy.c_str());
|
||||||
printf("\e[32m#################################### building Tree in %s\e[0m\n", saveFileName.Data());
|
printf("\e[32m#################################### building Tree in %s\e[0m\n", saveFileName.Data());
|
||||||
TFile * saveFile = new TFile(saveFileName, "recreate");
|
TFile * saveFile = new TFile(saveFileName, "recreate");
|
||||||
|
TNamed("simConfig", cfg.rawText.c_str()).Write(); // config used for this file
|
||||||
TTree * tree1 = new TTree("tree1", "tree1");
|
TTree * tree1 = new TTree("tree1", "tree1");
|
||||||
|
|
||||||
// beam and CM variables saved in tree
|
// beam and CM variables saved in tree
|
||||||
|
|
@ -542,7 +578,7 @@ int main(int argc, char **argv){
|
||||||
transfer.CalReactionConstant();
|
transfer.CalReactionConstant();
|
||||||
|
|
||||||
// vertex position in target volume
|
// vertex position in target volume
|
||||||
beamEnergy = gRandom->Uniform(6.56, beamE); // MeV, sample beam energy at vertex from uniform distribution between 0 and initial beam energy
|
beamEnergy = gRandom->Uniform(beamEMin, beamE); // MeV, uniform beam energy at the vertex
|
||||||
KEA = beamEnergy / beamA;
|
KEA = beamEnergy / beamA;
|
||||||
beamPath_cm = elossBeamInverse->Eval(beamEnergy); // beamE maps to x=0 after path shift
|
beamPath_cm = elossBeamInverse->Eval(beamEnergy); // beamE maps to x=0 after path shift
|
||||||
vertexZ = beamEntranceZ + beamPath_cm * 10.0; // cm -> mm
|
vertexZ = beamEntranceZ + beamPath_cm * 10.0; // cm -> mm
|
||||||
|
|
@ -696,7 +732,7 @@ int main(int argc, char **argv){
|
||||||
double distance_sx3;
|
double distance_sx3;
|
||||||
Esx3 = CalculateEnergyLoss(vertexX, vertexY, vertexZ,
|
Esx3 = CalculateEnergyLoss(vertexX, vertexY, vertexZ,
|
||||||
sx3X, sx3Y, sx3Z,
|
sx3X, sx3Y, sx3Z,
|
||||||
b, "He", Tb,
|
b, lightMedium, Tb,
|
||||||
distance_sx3);
|
distance_sx3);
|
||||||
dl = distance_sx3;
|
dl = distance_sx3;
|
||||||
|
|
||||||
|
|
@ -704,26 +740,26 @@ int main(int argc, char **argv){
|
||||||
//TVector3 hitSigma = sx3->GetHitPosWithSigma(sigmaSX3_W, sigmaSX3_L);
|
//TVector3 hitSigma = sx3->GetHitPosWithSigma(sigmaSX3_W, sigmaSX3_L);
|
||||||
|
|
||||||
//smudging
|
//smudging
|
||||||
TVector3 hitSigma = sx3->GetHitPosWithSigma(2, 2); // args are sigmaSX3_W, sigmaSX3_L, currently set to 0 for no smearing
|
TVector3 hitSigma = sx3->GetHitPosWithSigma(sigmaSX3_W, sigmaSX3_L);
|
||||||
|
|
||||||
double hitX = hitSigma.X();
|
double hitX = hitSigma.X();
|
||||||
double hitY = hitSigma.Y();
|
double hitY = hitSigma.Y();
|
||||||
double hitZ = hitSigma.Z();
|
double hitZ = hitSigma.Z();
|
||||||
|
|
||||||
double aX_sigma = gRandom->Gaus(aX, 2.3);
|
double aX_sigma = gRandom->Gaus(aX, anodeSigma);
|
||||||
double aY_sigma = gRandom->Gaus(aY, 2.3);
|
double aY_sigma = gRandom->Gaus(aY, anodeSigma);
|
||||||
double aZ_sigma = gRandom->Gaus(aZ, 2.3);
|
double aZ_sigma = gRandom->Gaus(aZ, anodeSigma);
|
||||||
|
|
||||||
double distance_A;
|
double distance_A;
|
||||||
Eanode = CalculateEnergyLoss(vertexX, vertexY, vertexZ,
|
Eanode = CalculateEnergyLoss(vertexX, vertexY, vertexZ,
|
||||||
aX, aY, aZ,
|
aX, aY, aZ,
|
||||||
b, "He", Tb,
|
b, lightMedium, Tb,
|
||||||
distance_A);
|
distance_A);
|
||||||
|
|
||||||
double distance_C;
|
double distance_C;
|
||||||
Ecathode = CalculateEnergyLoss(vertexX, vertexY, vertexZ,
|
Ecathode = CalculateEnergyLoss(vertexX, vertexY, vertexZ,
|
||||||
cX, cY, cZ,
|
cX, cY, cZ,
|
||||||
b, "He", Tb,
|
b, lightMedium, Tb,
|
||||||
distance_C);
|
distance_C);
|
||||||
|
|
||||||
if (Esx3 <= 0 || Eanode <= 0 || Ecathode <= 0) {
|
if (Esx3 <= 0 || Eanode <= 0 || Ecathode <= 0) {
|
||||||
|
|
@ -755,13 +791,13 @@ int main(int argc, char **argv){
|
||||||
vY_track = r_rhoMin_fix.Y();
|
vY_track = r_rhoMin_fix.Y();
|
||||||
vZ_track = r_rhoMin_fix.Z();
|
vZ_track = r_rhoMin_fix.Z();
|
||||||
|
|
||||||
EBeam_track = elossBeam->Eval((vZ_track + 454.3) / 10);
|
EBeam_track = elossBeam->Eval((vZ_track - beamEntranceZ) / 10);
|
||||||
|
|
||||||
Tb_recon = CalculateOriginalEnergy(hitX, hitY, hitZ,
|
Tb_recon = CalculateOriginalEnergy(hitX, hitY, hitZ,
|
||||||
vX_track, vY_track, vZ_track,
|
vX_track, vY_track, vZ_track,
|
||||||
//0, 0, r_rhoMin_fix.Z(),
|
//0, 0, r_rhoMin_fix.Z(),
|
||||||
//0, 0, vertexZ,
|
//0, 0, vertexZ,
|
||||||
b, "He", Esx3,
|
b, lightMedium, Esx3,
|
||||||
distance_sx3);
|
distance_sx3);
|
||||||
|
|
||||||
const TVector3 projectileDirection = TVector3(hitX - aX_sigma, hitY - aY_sigma, hitZ - aZ_sigma);
|
const TVector3 projectileDirection = TVector3(hitX - aX_sigma, hitY - aY_sigma, hitZ - aZ_sigma);
|
||||||
|
|
@ -772,7 +808,7 @@ int main(int argc, char **argv){
|
||||||
|
|
||||||
//kinematic reconstruction
|
//kinematic reconstruction
|
||||||
EBeam_kin = apkin_27Al.getEbeam_givenQ(Tb_recon, Ex, theta_recon); //args are (reaction energy, Ex, thetab) still tracking
|
EBeam_kin = apkin_27Al.getEbeam_givenQ(Tb_recon, Ex, theta_recon); //args are (reaction energy, Ex, thetab) still tracking
|
||||||
vZ_kin = elossBeamInverse->Eval(EBeam_kin) * 10 - 454.3;
|
vZ_kin = elossBeamInverse->Eval(EBeam_kin) * 10 + beamEntranceZ;
|
||||||
|
|
||||||
Ex_kin = apkin_27Al.getExc(Tb_recon, theta_recon);
|
Ex_kin = apkin_27Al.getExc(Tb_recon, theta_recon);
|
||||||
/*Checklist: anode smudge, sx3 smudge, beam position off axis, beam angle*/
|
/*Checklist: anode smudge, sx3 smudge, beam position off axis, beam angle*/
|
||||||
|
|
@ -803,7 +839,7 @@ int main(int argc, char **argv){
|
||||||
}
|
}
|
||||||
|
|
||||||
vZ_kin = std::isfinite(EBeam_kin) && EBeam_kin >= 0.0
|
vZ_kin = std::isfinite(EBeam_kin) && EBeam_kin >= 0.0
|
||||||
? elossBeamInverse->Eval(EBeam_kin) * 10 - 454.3
|
? elossBeamInverse->Eval(EBeam_kin) * 10 + beamEntranceZ
|
||||||
: TMath::QuietNaN();
|
: TMath::QuietNaN();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -856,18 +892,18 @@ int main(int argc, char **argv){
|
||||||
double distance_qqq;
|
double distance_qqq;
|
||||||
Eqqq = CalculateEnergyLoss(vertexX, vertexY, vertexZ,
|
Eqqq = CalculateEnergyLoss(vertexX, vertexY, vertexZ,
|
||||||
qqqX, qqqY, qqqZ,
|
qqqX, qqqY, qqqZ,
|
||||||
b, "He",
|
b, lightMedium,
|
||||||
Tb, distance_qqq);
|
Tb, distance_qqq);
|
||||||
dl = distance_qqq;
|
dl = distance_qqq;
|
||||||
double distance_A;
|
double distance_A;
|
||||||
Eanode = CalculateEnergyLoss(vertexX, vertexY, vertexZ,
|
Eanode = CalculateEnergyLoss(vertexX, vertexY, vertexZ,
|
||||||
aX, aY, aZ,
|
aX, aY, aZ,
|
||||||
b, "He",
|
b, lightMedium,
|
||||||
Tb, distance_A);
|
Tb, distance_A);
|
||||||
double distance_C;
|
double distance_C;
|
||||||
Ecathode = CalculateEnergyLoss(vertexX, vertexY, vertexZ,
|
Ecathode = CalculateEnergyLoss(vertexX, vertexY, vertexZ,
|
||||||
cX, cY, cZ,
|
cX, cY, cZ,
|
||||||
b, "He",
|
b, lightMedium,
|
||||||
Tb, distance_C);
|
Tb, distance_C);
|
||||||
|
|
||||||
if (Eqqq <= 0 || Eanode <= 0 || Ecathode <= 0) {
|
if (Eqqq <= 0 || Eanode <= 0 || Ecathode <= 0) {
|
||||||
|
|
@ -889,16 +925,16 @@ int main(int argc, char **argv){
|
||||||
|
|
||||||
// QQQ sits at fixed z: smear in-plane (radial, azimuthal), z stays fixed
|
// QQQ sits at fixed z: smear in-plane (radial, azimuthal), z stays fixed
|
||||||
const double qHitPhi = hitPos.Phi();
|
const double qHitPhi = hitPos.Phi();
|
||||||
const double qSigR = 2.0, qSigPhi = 2.0; // mm
|
const double qSigR = qqqSigmaR, qSigPhi = qqqSigmaPhi;
|
||||||
const double dR = gRandom->Gaus(0, qSigR);
|
const double dR = gRandom->Gaus(0, qSigR);
|
||||||
const double dTan = gRandom->Gaus(0, qSigPhi);
|
const double dTan = gRandom->Gaus(0, qSigPhi);
|
||||||
const double qHitX = hitPos.X() + dR * std::cos(qHitPhi) - dTan * std::sin(qHitPhi);
|
const double qHitX = hitPos.X() + dR * std::cos(qHitPhi) - dTan * std::sin(qHitPhi);
|
||||||
const double qHitY = hitPos.Y() + dR * std::sin(qHitPhi) + dTan * std::cos(qHitPhi);
|
const double qHitY = hitPos.Y() + dR * std::sin(qHitPhi) + dTan * std::cos(qHitPhi);
|
||||||
const double qHitZ = hitPos.Z();
|
const double qHitZ = hitPos.Z();
|
||||||
|
|
||||||
const double qAX = gRandom->Gaus(aX, 2.3);
|
const double qAX = gRandom->Gaus(aX, anodeSigma);
|
||||||
const double qAY = gRandom->Gaus(aY, 2.3);
|
const double qAY = gRandom->Gaus(aY, anodeSigma);
|
||||||
const double qAZ = gRandom->Gaus(aZ, 2.3);
|
const double qAZ = gRandom->Gaus(aZ, anodeSigma);
|
||||||
|
|
||||||
if (qqqID >= 0 && !std::isnan(aX) && !std::isnan(aY) && !std::isnan(aZ) && aZ != 54321 && (aX != 0 || aY != 0 || aZ != 0)) {
|
if (qqqID >= 0 && !std::isnan(aX) && !std::isnan(aY) && !std::isnan(aZ) && aZ != 54321 && (aX != 0 || aY != 0 || aZ != 0)) {
|
||||||
// line through QQQ hit and anode point; vertex = closest approach to the beam (z) axis
|
// line through QQQ hit and anode point; vertex = closest approach to the beam (z) axis
|
||||||
|
|
@ -914,11 +950,11 @@ int main(int argc, char **argv){
|
||||||
vY_track = rVtx.Y();
|
vY_track = rVtx.Y();
|
||||||
vZ_track = rVtx.Z();
|
vZ_track = rVtx.Z();
|
||||||
|
|
||||||
EBeam_track = elossBeam->Eval((vZ_track + 454.3) / 10);
|
EBeam_track = elossBeam->Eval((vZ_track - beamEntranceZ) / 10);
|
||||||
|
|
||||||
Tb_recon = CalculateOriginalEnergy(qHitX, qHitY, qHitZ,
|
Tb_recon = CalculateOriginalEnergy(qHitX, qHitY, qHitZ,
|
||||||
vX_track, vY_track, vZ_track,
|
vX_track, vY_track, vZ_track,
|
||||||
b, "He", Eqqq,
|
b, lightMedium, Eqqq,
|
||||||
distance_qqq);
|
distance_qqq);
|
||||||
|
|
||||||
// polar angle of the track relative to the beam (z) axis
|
// polar angle of the track relative to the beam (z) axis
|
||||||
|
|
@ -928,7 +964,7 @@ int main(int argc, char **argv){
|
||||||
if (reactionConfig.recoilLightA == 1 && !TMath::IsNaN(EBeam_track)) {
|
if (reactionConfig.recoilLightA == 1 && !TMath::IsNaN(EBeam_track)) {
|
||||||
Kinematics apkin_27Al(26.981538408,4.00260325413,1.00782503224,29.973770136,EBeam_track/26.981538408);
|
Kinematics apkin_27Al(26.981538408,4.00260325413,1.00782503224,29.973770136,EBeam_track/26.981538408);
|
||||||
EBeam_kin = apkin_27Al.getEbeam_givenQ(Tb_recon, Ex, theta_recon);
|
EBeam_kin = apkin_27Al.getEbeam_givenQ(Tb_recon, Ex, theta_recon);
|
||||||
vZ_kin = elossBeamInverse->Eval(EBeam_kin) * 10 - 454.3;
|
vZ_kin = elossBeamInverse->Eval(EBeam_kin) * 10 + beamEntranceZ;
|
||||||
Ex_kin = apkin_27Al.getExc(Tb_recon, theta_recon);
|
Ex_kin = apkin_27Al.getExc(Tb_recon, theta_recon);
|
||||||
} else if (reactionConfig.recoilLightA == 4) {
|
} else if (reactionConfig.recoilLightA == 4) {
|
||||||
double beamMomentum = std::sqrt((EBeam_track + al27Iso.Mass) * (EBeam_track + al27Iso.Mass) - al27Iso.Mass * al27Iso.Mass);
|
double beamMomentum = std::sqrt((EBeam_track + al27Iso.Mass) * (EBeam_track + al27Iso.Mass) - al27Iso.Mass * al27Iso.Mass);
|
||||||
|
|
@ -951,7 +987,7 @@ int main(int argc, char **argv){
|
||||||
}
|
}
|
||||||
|
|
||||||
vZ_kin = std::isfinite(EBeam_kin) && EBeam_kin >= 0.0
|
vZ_kin = std::isfinite(EBeam_kin) && EBeam_kin >= 0.0
|
||||||
? elossBeamInverse->Eval(EBeam_kin) * 10 - 454.3
|
? elossBeamInverse->Eval(EBeam_kin) * 10 + beamEntranceZ
|
||||||
: TMath::QuietNaN();
|
: TMath::QuietNaN();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
40
Armory/anasen_config.yaml
Normal file
40
Armory/anasen_config.yaml
Normal file
|
|
@ -0,0 +1,40 @@
|
||||||
|
# ANASEN simulation configuration. Run: ./AnasenMS [events] [vis] [--config file.yaml]
|
||||||
|
# Each run's config is copied to config_history/<date_time>.yaml and embedded in the ROOT file.
|
||||||
|
|
||||||
|
simulation:
|
||||||
|
events: 1000000 # overridden by first command-line argument
|
||||||
|
output_file: SimAnasen1.root
|
||||||
|
seed: -1 # >= 0 sets the ROOT random seed for reproducibility
|
||||||
|
history_dir: config_history
|
||||||
|
|
||||||
|
reaction: # [A, Z]
|
||||||
|
projectile: [1, 1]
|
||||||
|
target: [4, 2]
|
||||||
|
light_ejectile: [4, 2]
|
||||||
|
heavy_recoil: [1, 1]
|
||||||
|
projectile_excitation_MeV: [0]
|
||||||
|
heavy_excitation_MeV: [0]
|
||||||
|
|
||||||
|
beam:
|
||||||
|
energy_MeV: 7 # maximum beam energy (table is shifted so this is the entrance energy)
|
||||||
|
min_energy_MeV: 6.56 # lowest energy sampled uniformly at the vertex
|
||||||
|
entrance_z_mm: -454.3 # beam entrance into the gas
|
||||||
|
vertex_x_mm: [-1.75, 1.75] # beam spot half-width = upper value, added in quadrature to straggle
|
||||||
|
vertex_y_mm: [-1.75, 1.75]
|
||||||
|
vertex_z_mm: [-174.3, 174.3]
|
||||||
|
|
||||||
|
eloss:
|
||||||
|
table_dir: ../ELoss/ # light-particle tables: <table_dir><medium>Loss/E_vs_x_<particle>.dat
|
||||||
|
beam_table: ../ELoss/HeLoss/E_vs_x_proton.dat # path (cm) vs energy and straggle for the beam
|
||||||
|
light_medium: He
|
||||||
|
|
||||||
|
resolution:
|
||||||
|
sx3_sigma_w_mm: 2
|
||||||
|
sx3_sigma_l_mm: 2
|
||||||
|
qqq_sigma_r_mm: 2
|
||||||
|
qqq_sigma_phi_mm: 2
|
||||||
|
pw_anode_sigma: 0 # normalized anode term (0-1) used in PW track fit
|
||||||
|
pw_cathode_sigma: 0 # normalized cathode term (0-1) used in PW track fit
|
||||||
|
anode_position_sigma_mm: 2.3 # smearing of reconstructed anode crossing
|
||||||
|
|
||||||
|
dead_channel: [] # list of dead channels, e.g., ["sx3_1", "qqq_2"]
|
||||||
41
Armory/config_history/2026-10-15_125111.yaml
Normal file
41
Armory/config_history/2026-10-15_125111.yaml
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
# run: 2026-10-15_125111 events: 200 output: SimAnasen1.root source: anasen_config.yaml
|
||||||
|
# ANASEN simulation configuration. Run: ./AnasenMS [events] [vis] [--config file.yaml]
|
||||||
|
# Each run's config is copied to config_history/<date_time>.yaml and embedded in the ROOT file.
|
||||||
|
|
||||||
|
simulation:
|
||||||
|
events: 1000000 # overridden by first command-line argument
|
||||||
|
output_file: SimAnasen1.root
|
||||||
|
seed: -1 # >= 0 sets the ROOT random seed for reproducibility
|
||||||
|
history_dir: config_history
|
||||||
|
|
||||||
|
reaction: # [A, Z]
|
||||||
|
projectile: [1, 1]
|
||||||
|
target: [4, 2]
|
||||||
|
light_ejectile: [4, 2]
|
||||||
|
heavy_recoil: [1, 1]
|
||||||
|
projectile_excitation_MeV: [0]
|
||||||
|
heavy_excitation_MeV: [0]
|
||||||
|
|
||||||
|
beam:
|
||||||
|
energy_MeV: 7 # maximum beam energy (table is shifted so this is the entrance energy)
|
||||||
|
min_energy_MeV: 6.56 # lowest energy sampled uniformly at the vertex
|
||||||
|
entrance_z_mm: -454.3 # beam entrance into the gas
|
||||||
|
vertex_x_mm: [-1.75, 1.75] # beam spot half-width = upper value, added in quadrature to straggle
|
||||||
|
vertex_y_mm: [-1.75, 1.75]
|
||||||
|
vertex_z_mm: [-174.3, 174.3]
|
||||||
|
|
||||||
|
eloss:
|
||||||
|
table_dir: ../ELoss/ # light-particle tables: <table_dir><medium>Loss/E_vs_x_<particle>.dat
|
||||||
|
beam_table: ../ELoss/HeLoss/E_vs_x_proton.dat # path (cm) vs energy and straggle for the beam
|
||||||
|
light_medium: He
|
||||||
|
|
||||||
|
resolution:
|
||||||
|
sx3_sigma_w_mm: 2
|
||||||
|
sx3_sigma_l_mm: 2
|
||||||
|
qqq_sigma_r_mm: 2
|
||||||
|
qqq_sigma_phi_mm: 2
|
||||||
|
pw_anode_sigma: 0 # normalized anode term (0-1) used in PW track fit
|
||||||
|
pw_cathode_sigma: 0 # normalized cathode term (0-1) used in PW track fit
|
||||||
|
anode_position_sigma_mm: 2.3 # smearing of reconstructed anode crossing
|
||||||
|
|
||||||
|
dead_channel: [] # list of dead channels, e.g., ["sx3_1", "qqq_2"]
|
||||||
41
Armory/config_history/2026-10-15_125209.yaml
Normal file
41
Armory/config_history/2026-10-15_125209.yaml
Normal file
|
|
@ -0,0 +1,41 @@
|
||||||
|
# run: 2026-10-15_125209 events: 1000000 output: SimAnasen1.root source: anasen_config.yaml
|
||||||
|
# ANASEN simulation configuration. Run: ./AnasenMS [events] [vis] [--config file.yaml]
|
||||||
|
# Each run's config is copied to config_history/<date_time>.yaml and embedded in the ROOT file.
|
||||||
|
|
||||||
|
simulation:
|
||||||
|
events: 1000000 # overridden by first command-line argument
|
||||||
|
output_file: SimAnasen1.root
|
||||||
|
seed: -1 # >= 0 sets the ROOT random seed for reproducibility
|
||||||
|
history_dir: config_history
|
||||||
|
|
||||||
|
reaction: # [A, Z]
|
||||||
|
projectile: [1, 1]
|
||||||
|
target: [4, 2]
|
||||||
|
light_ejectile: [4, 2]
|
||||||
|
heavy_recoil: [1, 1]
|
||||||
|
projectile_excitation_MeV: [0]
|
||||||
|
heavy_excitation_MeV: [0]
|
||||||
|
|
||||||
|
beam:
|
||||||
|
energy_MeV: 7 # maximum beam energy (table is shifted so this is the entrance energy)
|
||||||
|
min_energy_MeV: 6.56 # lowest energy sampled uniformly at the vertex
|
||||||
|
entrance_z_mm: -454.3 # beam entrance into the gas
|
||||||
|
vertex_x_mm: [-1.75, 1.75] # beam spot half-width = upper value, added in quadrature to straggle
|
||||||
|
vertex_y_mm: [-1.75, 1.75]
|
||||||
|
vertex_z_mm: [-174.3, 174.3]
|
||||||
|
|
||||||
|
eloss:
|
||||||
|
table_dir: ../ELoss/ # light-particle tables: <table_dir><medium>Loss/E_vs_x_<particle>.dat
|
||||||
|
beam_table: ../ELoss/HeLoss/E_vs_x_proton.dat # path (cm) vs energy and straggle for the beam
|
||||||
|
light_medium: He
|
||||||
|
|
||||||
|
resolution:
|
||||||
|
sx3_sigma_w_mm: 2
|
||||||
|
sx3_sigma_l_mm: 2
|
||||||
|
qqq_sigma_r_mm: 2
|
||||||
|
qqq_sigma_phi_mm: 2
|
||||||
|
pw_anode_sigma: 0 # normalized anode term (0-1) used in PW track fit
|
||||||
|
pw_cathode_sigma: 0 # normalized cathode term (0-1) used in PW track fit
|
||||||
|
anode_position_sigma_mm: 2.3 # smearing of reconstructed anode crossing
|
||||||
|
|
||||||
|
dead_channel: [] # list of dead channels, e.g., ["sx3_1", "qqq_2"]
|
||||||
2
Armory/config_history/index.log
Normal file
2
Armory/config_history/index.log
Normal file
|
|
@ -0,0 +1,2 @@
|
||||||
|
2026-10-15_125111 200 SimAnasen1.root config_history/2026-10-15_125111.yaml
|
||||||
|
2026-10-15_125209 1000000 SimAnasen1.root config_history/2026-10-15_125209.yaml
|
||||||
Loading…
Reference in New Issue
Block a user