File indexing completed on 2026-10-09 08:30:27
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "ActsPlugins/Mille/MillePedeSteering.hpp"
0010
0011 #include "Acts/Utilities/Logger.hpp"
0012 #include "Acts/Utilities/Result.hpp"
0013 #include "ActsPlugins/Mille/MillePedeError.hpp"
0014
0015 #include <filesystem>
0016 #include <format>
0017 #include <fstream>
0018 #include <map>
0019
0020 using namespace ActsPlugins;
0021
0022 namespace {
0023 using Strategy = ActsPlugins::MillePedeSolutionStrategy;
0024 using EqualityConstraint = ActsPlugins::MillePedeEqualityConstraint;
0025 using Config = ActsPlugins::MillePedeSteeringConfig;
0026
0027 void addInputBlock(std::ofstream& out, const Config& conf,
0028 const Acts::Logger& logger) {
0029 if (conf.inputFiles.empty()) {
0030 ACTS_WARNING(
0031 "You are about to generate a steering file without any input! Suit "
0032 "yourself, but this will probably not align anything...");
0033 }
0034 out << "*** Input files *** " << std::endl;
0035 out << "Cfiles " << std::endl;
0036 for (const std::string& f : conf.inputFiles) {
0037 std::filesystem::path p = f;
0038
0039
0040 if (p.is_relative()) {
0041 p = std::filesystem::current_path() / p;
0042 }
0043 out << p.string() << std::endl;
0044 }
0045 out << std::endl;
0046 }
0047
0048 void addSolutionMethod(std::ofstream& out, const Config& conf,
0049 const Acts::Logger& logger) {
0050 using enum Strategy;
0051 static const std::map<Strategy, std::string> stratNames{
0052 {Inversion, "inversion"},
0053 {Diagonalization, "diagonalization"},
0054 {Decomposition, "decomposition"},
0055 {FullMinRes, "fullMINRES"},
0056 {SparseMinRes, "sparseMINRES"},
0057 {FullMinResQlp, "fullMINRES-QLP"},
0058 {SparseMinResQlp, "sparseMINRES-QLP"},
0059 {FullLapack, "fullLAPACK"},
0060 {UnpackedLapack, "unpackedLAPACK"},
0061 {SparsePardiso, "sparsePARDISO"},
0062 };
0063 auto found = stratNames.find(conf.strategy);
0064 if (found == stratNames.end()) {
0065 ACTS_ERROR(
0066 "Strategy specified in the steering not yet supported in "
0067 "addSolutionMethod - this is a bug, please report to the devs");
0068 return;
0069 }
0070 out << "*** Solution method *** " << std::endl;
0071 out << std::format("method {} {} {}", found->second, conf.minIterations,
0072 conf.convergenceLimit)
0073 << std::endl
0074 << std::endl;
0075 }
0076
0077 void addConstraint(std::ofstream& out, const EqualityConstraint& constraint,
0078 const Acts::Logger& ) {
0079 out << std::format("Constraint {:.6f}", constraint.constraint) << std::endl;
0080 for (const auto& [label, weight] : constraint.labelsAndWeights) {
0081 out << std::format(" {} {:.6f}", label, weight) << std::endl;
0082 }
0083 out << std::endl;
0084 }
0085
0086 void addConstraintsBlock(std::ofstream& out, const Config& conf,
0087 const Acts::Logger& logger) {
0088 for (const EqualityConstraint& con : conf.constraints) {
0089 addConstraint(out, con, logger);
0090 }
0091 out << std::endl;
0092 }
0093
0094 void addOthers(std::ofstream& out, const Config& conf,
0095 const Acts::Logger& ) {
0096 out << "*** Other steering flags " << std::endl;
0097 out << std::format("entries {} {} {}", std::get<0>(conf.entriesCut),
0098 std::get<1>(conf.entriesCut), std::get<2>(conf.entriesCut))
0099 << std::endl;
0100 out << std::format("outlierdownweighting {} ", conf.outlierDownweighting)
0101 << std::endl;
0102 out << std::format("dwfractioncut {} ", conf.downweightFractionCut)
0103 << std::endl;
0104 out << std::format("threads {} {} ", conf.nOMPthreads, conf.nIOthreads)
0105 << std::endl;
0106 out << std::format("matiter {} ", conf.matIter) << std::endl;
0107 out << std::format("printcounts {} ", conf.printCounts) << std::endl;
0108 out << std::format("chisqcut {} {} ", conf.chi2Cut.first, conf.chi2Cut.second)
0109 << std::endl;
0110 if (conf.monitorResiduals) {
0111 out << " monitorresiduals" << std::endl;
0112 }
0113 if (conf.monitorPulls) {
0114 out << " monitorpulls" << std::endl;
0115 }
0116 if (conf.skipEmptyCons) {
0117 out << " skipemptycons" << std::endl;
0118 }
0119 if (conf.countRecords) {
0120 out << " countrecords" << std::endl;
0121 }
0122 out << std::endl;
0123 out << "*** User-specified config flags " << std::endl;
0124 for (const std::string& extraLine : conf.extraLines) {
0125 out << extraLine << std::endl;
0126 }
0127 out << std::endl;
0128 }
0129 }
0130
0131 Acts::Result<std::filesystem::path> ActsPlugins::generateMillePedeSteeringFile(
0132 const std::filesystem::path& destination, const Config& config,
0133 const Acts::Logger& logger) {
0134 std::ofstream theSteer(destination);
0135 if (!theSteer.is_open()) {
0136 ACTS_ERROR("Unable to create the MP steering file " << destination);
0137 return Acts::Result<std::filesystem::path>::failure(
0138 MillePedeError::UnableToWriteSteering);
0139 }
0140
0141 theSteer << "*** Auto-generated Millepede steering file from ACTS *** "
0142 << std::endl;
0143
0144 if (!config.constraints.empty()) {
0145 std::filesystem::path consFile = destination;
0146 consFile.replace_extension("cons.txt");
0147 theSteer << "*** Constraints file " << std::endl;
0148 if (consFile.is_relative()) {
0149 consFile = std::filesystem::current_path() / consFile;
0150 }
0151 theSteer << consFile.string() << std::endl;
0152 std::cout << consFile.string() << std::endl;
0153 std::ofstream theCons(consFile);
0154 if (!theSteer.is_open()) {
0155 ACTS_ERROR("Unable to create the MP constraints file " << consFile);
0156 return Acts::Result<std::filesystem::path>::failure(
0157 MillePedeError::UnableToWriteSteering);
0158 }
0159 addConstraintsBlock(theCons, config, logger());
0160 theCons.close();
0161 }
0162
0163 addInputBlock(theSteer, config, logger());
0164 addSolutionMethod(theSteer, config, logger());
0165 addOthers(theSteer, config, logger());
0166
0167 theSteer.close();
0168 return destination;
0169 }