diff --git a/FixedOrderGen/src/config.cc b/FixedOrderGen/src/config.cc index b0a6060..3188a76 100644 --- a/FixedOrderGen/src/config.cc +++ b/FixedOrderGen/src/config.cc @@ -1,353 +1,353 @@ #include "config.hh" #include #include "Subleading.hh" #include "HEJ/config.hh" #include "HEJ/YAMLreader.hh" namespace HEJFOG{ using HEJ::set_from_yaml; using HEJ::set_from_yaml_if_defined; namespace{ //! Get YAML tree of supported options /** * The configuration file is checked against this tree of options * in assert_all_options_known. */ YAML::Node const & get_supported_options(){ const static YAML::Node supported = [](){ YAML::Node supported; static const auto opts = { "process", "events", "subleading fraction","subleading channels", "scales", "scale factors", "max scale ratio", "pdf", "event output", "analysis", "import scales" }; // add subnodes to "supported" - the assigned value is irrelevant for(auto && opt: opts) supported[opt] = ""; for(auto && jet_opt: {"min pt", "peak pt", "algorithm", "R", "max rapidity"}){ supported["jets"][jet_opt] = ""; } for(auto && particle_type: {"Higgs", "Wp", "W+", "Wm", "W-", "Z"}){ for(auto && particle_opt: {"mass", "width"}){ supported["particle properties"][particle_type][particle_opt] = ""; } supported["particle properties"][particle_type]["decays"]["into"] = ""; supported["particle properties"][particle_type]["decays"]["branching ratio"] = ""; } for(auto && opt: {"mt", "use impact factors", "include bottom", "mb"}){ supported["Higgs coupling"][opt] = ""; } for(auto && beam_opt: {"energy", "particles"}){ supported["beam"][beam_opt] = ""; } for(auto && unweight_opt: {"sample size", "max deviation"}){ supported["unweight"][unweight_opt] = ""; } for(auto && opt: {"name", "seed"}){ supported["random generator"][opt] = ""; } return supported; }(); return supported; } JetParameters get_jet_parameters( YAML::Node const & node, std::string const & entry ){ const auto p = HEJ::get_jet_parameters(node, entry); JetParameters result; result.def = p.def; result.min_pt = p.min_pt; set_from_yaml(result.max_y, node, entry, "max rapidity"); set_from_yaml_if_defined(result.peak_pt, node, entry, "peak pt"); return result; } Beam get_Beam( YAML::Node const & node, std::string const & entry ){ Beam beam; std::vector particles; set_from_yaml(beam.energy, node, entry, "energy"); set_from_yaml_if_defined(particles, node, entry, "particles"); if(! particles.empty()){ for(HEJ::ParticleID particle: particles){ if(particle != HEJ::pid::p && particle != HEJ::pid::p_bar){ throw std::invalid_argument{ "Unsupported value in option " + entry + ": particles:" " only proton ('p') and antiproton ('p_bar') beams are supported" }; } } if(particles.size() != 2){ throw std::invalid_argument{"Not exactly two beam particles"}; } beam.particles.front() = particles.front(); beam.particles.back() = particles.back(); } return beam; } std::vector split( std::string const & str, std::string const & delims ){ std::vector result; for(size_t begin, end = 0; end != str.npos;){ begin = str.find_first_not_of(delims, end); if(begin == str.npos) break; end = str.find_first_of(delims, begin + 1); result.emplace_back(str.substr(begin, end - begin)); } return result; } std::invalid_argument invalid_incoming(std::string const & what){ return std::invalid_argument{ "Incoming particle type " + what + " not supported," " incoming particles have to be 'p', 'p_bar' or partons" }; } std::invalid_argument invalid_outgoing(std::string const & what){ return std::invalid_argument{ "Outgoing particle type " + what + " not supported," " outgoing particles have to be 'j', 'photon', 'W+', 'W-', 'Z', 'H'" }; } Process get_process( YAML::Node const & node, std::string const & entry ){ Process result; std::string process_string; set_from_yaml(process_string, node, entry); assert(! process_string.empty()); const auto particles = split(process_string, " \n\t\v=>"); if(particles.size() < 3){ throw std::invalid_argument{ "Bad format in option process: '" + process_string + "', expected format is 'in1 in2 => out1 ...'" }; } result.incoming.front() = HEJ::to_ParticleID(particles[0]); result.incoming.back() = HEJ::to_ParticleID(particles[1]); for(size_t i = 0; i < result.incoming.size(); ++i){ const HEJ::ParticleID in = result.incoming[i]; if( in != HEJ::pid::proton && in != HEJ::pid::p_bar && !HEJ::is_parton(in) ){ throw invalid_incoming(particles[i]); } } result.njets = 0; for(size_t i = result.incoming.size(); i < particles.size(); ++i){ assert(! particles[i].empty()); if(particles[i] == "j") ++result.njets; else if(std::isdigit(particles[i].front()) && particles[i].back() == 'j') result.njets += std::stoi(particles[i]); else{ const auto pid = HEJ::to_ParticleID(particles[i]); if(!HEJ::is_AWZH_boson(pid)){ throw invalid_outgoing(particles[i]); } if(result.boson){ throw std::invalid_argument{ "More than one outgoing boson is not supported" }; } result.boson = pid; } } if(result.njets < 2){ throw std::invalid_argument{ "Process has to include at least two jets ('j')" }; } return result; } HEJFOG::Subleading to_subleading_channel(YAML::Node const & yaml){ std::string name; using HEJFOG::Subleading; set_from_yaml(name, yaml); if(name == "none") return none; if(name == "all") return all; if(name == "unordered" || name == "uno") return uno; throw HEJ::unknown_option("Unknown subleading channel '"+name+"'"); } unsigned int get_subleading_channels(YAML::Node const & node){ using YAML::NodeType; using HEJFOG::Subleading; // all channels allowed by default if(!node) return all; switch(node.Type()){ case NodeType::Undefined: return all; case NodeType::Null: return none; case NodeType::Scalar: return to_subleading_channel(node); case NodeType::Map: throw HEJ::invalid_type{"map is not a valid option for subleading channels"}; case NodeType::Sequence: unsigned int channels = HEJFOG::Subleading::none; for(auto && channel_node: node){ channels |= get_subleading_channels(channel_node); } return channels; } throw std::logic_error{"unreachable"}; } Decay get_decay(YAML::Node const & node){ Decay decay; set_from_yaml(decay.products, node, "into"); set_from_yaml(decay.branching_ratio, node, "branching ratio"); return decay; } std::vector get_decays(YAML::Node const & node){ using YAML::NodeType; if(!node) return {}; switch(node.Type()){ case NodeType::Null: case NodeType::Undefined: return {}; case NodeType::Scalar: throw HEJ::invalid_type{"value is not a list of decays"}; case NodeType::Map: return {get_decay(node)}; case NodeType::Sequence: std::vector result; for(auto && decay_str: node){ result.emplace_back(); set_from_yaml(result.back().products, decay_str, "into"); set_from_yaml(result.back().branching_ratio, decay_str, "branching ratio"); } return result; } throw std::logic_error{"unreachable"}; } ParticleProperties get_particle_properties( YAML::Node const & node, std::string const & entry ){ ParticleProperties result; set_from_yaml(result.mass, node, entry, "mass"); set_from_yaml(result.width, node, entry, "width"); try{ result.decays = get_decays(node[entry]["decays"]); } catch(HEJ::missing_option const & ex){ throw HEJ::missing_option{entry + ": decays: " + ex.what()}; } catch(HEJ::invalid_type const & ex){ throw HEJ::invalid_type{entry + ": decays: " + ex.what()}; } return result; } ParticlesPropMap get_all_particles_properties(YAML::Node const & node){ ParticlesPropMap result; for(auto const & entry: node) { const auto name = entry.first.as(); const auto id = HEJ::to_ParticleID(name); result.emplace(id, get_particle_properties(node,name)); } return result; } UnweightSettings get_unweight( YAML::Node const & node, std::string const & entry ){ UnweightSettings result; set_from_yaml(result.sample_size, node, entry, "sample size"); if(result.sample_size <= 0){ throw std::invalid_argument{ "negative sample size " + std::to_string(result.sample_size) }; } set_from_yaml(result.max_dev, node, entry, "max deviation"); return result; } Config to_Config(YAML::Node const & yaml){ try{ HEJ::assert_all_options_known(yaml, get_supported_options()); } catch(HEJ::unknown_option const & ex){ throw HEJ::unknown_option{std::string{"Unknown option '"} + ex.what() + "'"}; } Config config; config.process = get_process(yaml, "process"); set_from_yaml(config.events, yaml, "events"); config.jets = get_jet_parameters(yaml, "jets"); config.beam = get_Beam(yaml, "beam"); for(size_t i = 0; i < config.process.incoming.size(); ++i){ const auto & in = config.process.incoming[i]; using namespace HEJ::pid; if( (in == p || in == p_bar) && in != config.beam.particles[i]){ throw std::invalid_argument{ "Particle type of beam " + std::to_string(i+1) + " incompatible" + " with type of incoming particle " + std::to_string(i+1) }; } } set_from_yaml(config.pdf_id, yaml, "pdf"); set_from_yaml(config.subleading_fraction, yaml, "subleading fraction"); if(config.subleading_fraction < 0 || config.subleading_fraction > 1){ throw std::invalid_argument{ "subleading fraction has to be between 0 and 1" }; } if(config.subleading_fraction == 0) config.subleading_channels = Subleading::none; else config.subleading_channels = get_subleading_channels(yaml["subleading channels"]); if(!config.process.boson && config.subleading_channels != Subleading::none) throw HEJ::not_implemented("Subleading processes for pure Jet production not implemented yet"); if(yaml["particle properties"]){ config.particles_properties = get_all_particles_properties( yaml["particle properties"]); } if(config.process.boson && config.particles_properties.find(*(config.process.boson)) == config.particles_properties.end()) throw HEJ::missing_option("Process wants to generate boson " - +std::to_string(*(config.process.boson))+", but boson properties are missing"); + +std::to_string(*(config.process.boson))+", but particle properties are missing"); set_from_yaml_if_defined(config.analysis_parameters, yaml, "analysis"); config.scales = HEJ::to_ScaleConfig(yaml); set_from_yaml_if_defined(config.output, yaml, "event output"); config.rng = HEJ::to_RNGConfig(yaml, "random generator"); config.Higgs_coupling = HEJ::get_Higgs_coupling(yaml, "Higgs coupling"); if(yaml["unweight"]) config.unweight = get_unweight(yaml, "unweight"); return config; } } // namespace anonymous Config load_config(std::string const & config_file){ try{ return to_Config(YAML::LoadFile(config_file)); } catch(...){ std::cerr << "Error reading " << config_file << ":\n "; throw; } } }