Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2023-10-25 09:56:53

0001 /** \class DD4hep_VolumeBasedMagneticFieldESProducerFromDB
0002  *
0003  *  Producer for the VolumeBasedMagneticField, taking all inputs (geometry, etc) from DB.
0004  *  This version uses DD4hep and is adapted from the DDD version (MagneticField/GeomBuilder/plugins/VolumeBasedMagneticFieldESProducerFromDB.cc)
0005  *
0006  */
0007 
0008 #include "FWCore/Framework/interface/EventSetupRecordIntervalFinder.h"
0009 #include "FWCore/Framework/interface/ESProducer.h"
0010 #include "FWCore/Concurrency/interface/SharedResourceNames.h"
0011 
0012 #include "CondFormats/RunInfo/interface/RunInfo.h"
0013 #include "CondFormats/DataRecord/interface/RunSummaryRcd.h"
0014 
0015 #include "MagneticField/Engine/interface/MagneticField.h"
0016 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0017 #include "MagneticField/VolumeBasedEngine/interface/VolumeBasedMagneticField.h"
0018 #include "MagneticField/ParametrizedEngine/interface/ParametrizedMagneticFieldFactory.h"
0019 
0020 #include "MagneticField/Records/interface/IdealMagneticFieldRecord.h"
0021 
0022 #include "FWCore/Framework/interface/ESTransientHandle.h"
0023 #include "FWCore/Framework/interface/EventSetup.h"
0024 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0025 #include "FWCore/Utilities/interface/ESProductTag.h"
0026 
0027 #include "FWCore/Framework/interface/ModuleFactory.h"
0028 #include "MagneticField/GeomBuilder/src/DD4hep_MagGeoBuilder.h"
0029 
0030 #include "DetectorDescription/DDCMS/interface/DDDetector.h"
0031 
0032 #include "CondFormats/Common/interface/FileBlob.h"
0033 #include "CondFormats/DataRecord/interface/MFGeometryFileRcd.h"
0034 #include "MagneticField/Records/interface/IdealMagneticFieldRecord.h"
0035 #include "CondFormats/MFObjects/interface/MagFieldConfig.h"
0036 #include "CondFormats/DataRecord/interface/MagFieldConfigRcd.h"
0037 
0038 #include "FWCore/MessageLogger/interface/MessageLogger.h"
0039 
0040 #include <string>
0041 #include <vector>
0042 #include <iostream>
0043 #include <memory>
0044 
0045 using namespace std;
0046 using namespace magneticfield;
0047 using namespace edm;
0048 
0049 namespace magneticfield {
0050   class DD4hep_VolumeBasedMagneticFieldESProducerFromDB : public edm::ESProducer {
0051   public:
0052     DD4hep_VolumeBasedMagneticFieldESProducerFromDB(const edm::ParameterSet& iConfig);
0053     ~DD4hep_VolumeBasedMagneticFieldESProducerFromDB() override;
0054     // forbid copy ctor and assignment op.
0055     DD4hep_VolumeBasedMagneticFieldESProducerFromDB(const DD4hep_VolumeBasedMagneticFieldESProducerFromDB&) = delete;
0056     const DD4hep_VolumeBasedMagneticFieldESProducerFromDB& operator=(
0057         const DD4hep_VolumeBasedMagneticFieldESProducerFromDB&) = delete;
0058 
0059     std::shared_ptr<MagFieldConfig const> chooseConfigViaParameter(const IdealMagneticFieldRecord& iRecord);
0060     std::shared_ptr<MagFieldConfig const> chooseConfigAtRuntime(const IdealMagneticFieldRecord& iRecord);
0061 
0062     std::unique_ptr<MagneticField> produce(const IdealMagneticFieldRecord& iRecord);
0063 
0064     static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
0065 
0066   private:
0067     static std::string_view closerNominalLabel(float current);
0068 
0069     edm::ESGetToken<MagFieldConfig, MagFieldConfigRcd> mayGetConfigToken_;
0070     edm::ESGetToken<MagFieldConfig, MagFieldConfigRcd> knownFromParamConfigToken_;
0071 
0072     //NOTE: change of record since this MagFieldConfig was chosen based on data
0073     // from the record RunInfoRcd so therefore has a dependency upon that record
0074     edm::ESGetToken<MagFieldConfig, IdealMagneticFieldRecord> chosenConfigToken_;
0075 
0076     edm::ESGetToken<FileBlob, MFGeometryFileRcd> mayConsumeBlobToken_;
0077     cms::DDDetector* detector_{nullptr};
0078     int cachedGeometryVersion_{-1};
0079 
0080     const bool debug_;
0081     const bool useMergeFileIfAvailable_;
0082   };
0083 }  // namespace magneticfield
0084 
0085 DD4hep_VolumeBasedMagneticFieldESProducerFromDB::DD4hep_VolumeBasedMagneticFieldESProducerFromDB(
0086     const edm::ParameterSet& iConfig)
0087     : debug_(iConfig.getUntrackedParameter<bool>("debugBuilder")),
0088       useMergeFileIfAvailable_(iConfig.getParameter<bool>("useMergeFileIfAvailable")) {
0089   std::string const myConfigLabel = "VBMFESChoice";
0090   usesResources({edm::ESSharedResourceNames::kDD4hep});
0091 
0092   //Based on configuration, pick algorithm to produce the proper MagFieldConfig with a specific label
0093   const int current = iConfig.getParameter<int>("valueOverride");
0094   if (current < 0) {
0095     //We do not know what to get until we first read RunInfo
0096     setWhatProduced(
0097         this, &DD4hep_VolumeBasedMagneticFieldESProducerFromDB::chooseConfigAtRuntime, edm::es::Label(myConfigLabel))
0098         .setMayConsume(
0099             mayGetConfigToken_,
0100             [](auto const& iGet, edm::ESTransientHandle<RunInfo> iHandle) {
0101               auto const label = closerNominalLabel(iHandle->m_avg_current);
0102               edm::LogInfo("MagneticField") << "Current :" << iHandle->m_avg_current
0103                                             << " (from RunInfo DB); using map configuration with label: " << label;
0104               return iGet("", label);
0105             },
0106             edm::ESProductTag<RunInfo, RunInfoRcd>("", ""));
0107 
0108   } else {
0109     //we know exactly what we are going to get
0110     auto const label = closerNominalLabel(current);
0111     edm::LogInfo("MagneticField") << "Current :" << current
0112                                   << " (from valueOverride card); using map configuration with label: " << label;
0113     auto cc = setWhatProduced(this,
0114                               &DD4hep_VolumeBasedMagneticFieldESProducerFromDB::chooseConfigViaParameter,
0115                               edm::es::Label(myConfigLabel));
0116 
0117     knownFromParamConfigToken_ = cc.consumes(edm::ESInputTag(""s, std::string(label)));
0118   }
0119 
0120   auto const label = iConfig.getUntrackedParameter<std::string>("label");
0121   auto const myConfigTag = edm::ESInputTag(iConfig.getParameter<std::string>("@module_label"), myConfigLabel);
0122 
0123   //We use the MagFieldConfig created above to decide which FileBlob to use
0124   auto cc = setWhatProduced(this, label);
0125   cc.setMayConsume(
0126       mayConsumeBlobToken_,
0127       [](auto const& iGet, edm::ESTransientHandle<MagFieldConfig> iConfig) {
0128         if (iConfig->version == "parametrizedMagneticField") {
0129           return iGet.nothing();
0130         }
0131         return iGet("", std::to_string(iConfig->geometryVersion));
0132       },
0133       edm::ESProductTag<MagFieldConfig, IdealMagneticFieldRecord>(myConfigTag));
0134   chosenConfigToken_ = cc.consumes(myConfigTag);  //Use same tag as the choice
0135 }
0136 
0137 DD4hep_VolumeBasedMagneticFieldESProducerFromDB::~DD4hep_VolumeBasedMagneticFieldESProducerFromDB() {
0138   delete detector_;
0139 }
0140 
0141 std::shared_ptr<MagFieldConfig const> DD4hep_VolumeBasedMagneticFieldESProducerFromDB::chooseConfigAtRuntime(
0142     IdealMagneticFieldRecord const& iRcd) {
0143   edm::ESHandle<MagFieldConfig> config = iRcd.getHandle(mayGetConfigToken_);
0144 
0145   //just forward what we just got but do not take ownership
0146   return std::shared_ptr<MagFieldConfig const>(config.product(), [](auto*) {});
0147 }
0148 
0149 std::shared_ptr<MagFieldConfig const> DD4hep_VolumeBasedMagneticFieldESProducerFromDB::chooseConfigViaParameter(
0150     const IdealMagneticFieldRecord& iRecord) {
0151   auto config = iRecord.getHandle(knownFromParamConfigToken_);
0152 
0153   //just forward what we just got but do not take ownership
0154   return std::shared_ptr<MagFieldConfig const>(config.product(), [](auto*) {});
0155 }
0156 
0157 // ------------ method called to produce the data  ------------
0158 std::unique_ptr<MagneticField> DD4hep_VolumeBasedMagneticFieldESProducerFromDB::produce(
0159     const IdealMagneticFieldRecord& iRecord) {
0160   auto const& conf = iRecord.getTransientHandle(chosenConfigToken_);
0161 
0162   std::unique_ptr<MagneticField> paramField =
0163       ParametrizedMagneticFieldFactory::get(conf->slaveFieldVersion, conf->slaveFieldParameters);
0164 
0165   edm::LogInfo("MagneticField") << "(DD4hep) Version: " << conf->version
0166                                 << " geometryVersion: " << conf->geometryVersion
0167                                 << " slaveFieldVersion: " << conf->slaveFieldVersion;
0168 
0169   if (conf->version == "parametrizedMagneticField") {
0170     // The map consist of only the parametrization in this case
0171     return paramField;
0172   }
0173 
0174   // Full VolumeBased map + parametrization
0175   MagGeoBuilder builder(conf->version, conf->geometryVersion, debug_, useMergeFileIfAvailable_);
0176 
0177   // Set scaling factors
0178   if (!conf->keys.empty()) {
0179     builder.setScaling(conf->keys, conf->values);
0180   }
0181 
0182   // Set specification for the grid tables to be used.
0183   if (!conf->gridFiles.empty()) {
0184     builder.setGridFiles(conf->gridFiles);
0185   }
0186 
0187   // Build the geometry from the DB blob and cache it
0188   if (cachedGeometryVersion_ != conf->geometryVersion) {
0189     if (nullptr != detector_) {
0190       edm::LogError("MagneticField") << "MF Geometry needs to be re-created since current changed (cached: "
0191                                      << cachedGeometryVersion_ << " requested: " << conf->geometryVersion
0192                                      << "), which is not supported by dd4hep" << endl;
0193     }
0194 
0195     auto const& blob = iRecord.getTransientHandle(mayConsumeBlobToken_);
0196     std::unique_ptr<std::vector<unsigned char> > tb = blob->getUncompressedBlob();
0197 
0198     string sblob(tb->begin(), tb->end());
0199     sblob.insert(sblob.rfind("</DDDefinition>"),
0200                  "<MaterialSection label=\"materials.xml\"><ElementaryMaterial name=\"materials:Vacuum\" "
0201                  "density=\"1e-13*mg/cm3\" "
0202                  "symbol=\" \" atomicWeight=\"1*g/mole\" atomicNumber=\"1\"/></MaterialSection>");
0203 
0204     detector_ = new cms::DDDetector("cmsMagneticField:MAGF", sblob, true);
0205     cachedGeometryVersion_ = conf->geometryVersion;
0206   }
0207 
0208   builder.build(detector_);
0209 
0210   // Build the VB map. Ownership of the parametrization is transferred to it
0211   return std::make_unique<VolumeBasedMagneticField>(conf->geometryVersion,
0212                                                     builder.barrelLayers(),
0213                                                     builder.endcapSectors(),
0214                                                     builder.barrelVolumes(),
0215                                                     builder.endcapVolumes(),
0216                                                     builder.maxR(),
0217                                                     builder.maxZ(),
0218                                                     paramField.release(),
0219                                                     true);
0220 }
0221 
0222 std::string_view DD4hep_VolumeBasedMagneticFieldESProducerFromDB::closerNominalLabel(float current) {
0223   constexpr std::array<int, 7> nominalCurrents = {{-1, 0, 9558, 14416, 16819, 18268, 19262}};
0224   constexpr std::array<std::string_view, 7> nominalLabels = {{"3.8T", "0T", "2T", "3T", "3.5T", "3.8T", "4T"}};
0225 
0226   int i = 0;
0227   for (; i < (int)nominalLabels.size() - 1; i++) {
0228     if (2 * current < nominalCurrents[i] + nominalCurrents[i + 1])
0229       return nominalLabels[i];
0230   }
0231   return nominalLabels[i];
0232 }
0233 
0234 void DD4hep_VolumeBasedMagneticFieldESProducerFromDB::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
0235   edm::ParameterSetDescription desc;
0236   desc.addUntracked<bool>("debugBuilder", false);
0237   desc.add<bool>("useMergeFileIfAvailable", true);
0238   desc.add<int>("valueOverride", -1)->setComment("Force value of current (in A); take the value from DB if < 0.");
0239   desc.addUntracked<std::string>("label", "");
0240 
0241   descriptions.addDefault(desc);
0242 }
0243 
0244 DEFINE_FWK_EVENTSETUP_MODULE(DD4hep_VolumeBasedMagneticFieldESProducerFromDB);