Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2022-06-06 07:38:44

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     // forbid copy ctor and assignment op.
0054     DD4hep_VolumeBasedMagneticFieldESProducerFromDB(const DD4hep_VolumeBasedMagneticFieldESProducerFromDB&) = delete;
0055     const DD4hep_VolumeBasedMagneticFieldESProducerFromDB& operator=(
0056         const DD4hep_VolumeBasedMagneticFieldESProducerFromDB&) = delete;
0057 
0058     std::shared_ptr<MagFieldConfig const> chooseConfigViaParameter(const IdealMagneticFieldRecord& iRecord);
0059     std::shared_ptr<MagFieldConfig const> chooseConfigAtRuntime(const IdealMagneticFieldRecord& iRecord);
0060 
0061     std::unique_ptr<MagneticField> produce(const IdealMagneticFieldRecord& iRecord);
0062 
0063     static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
0064 
0065   private:
0066     static std::string_view closerNominalLabel(float current);
0067 
0068     edm::ESGetToken<MagFieldConfig, MagFieldConfigRcd> mayGetConfigToken_;
0069     edm::ESGetToken<MagFieldConfig, MagFieldConfigRcd> knownFromParamConfigToken_;
0070 
0071     //NOTE: change of record since this MagFieldConfig was chosen based on data
0072     // from the record RunInfoRcd so therefore has a dependency upon that record
0073     edm::ESGetToken<MagFieldConfig, IdealMagneticFieldRecord> chosenConfigToken_;
0074 
0075     edm::ESGetToken<FileBlob, MFGeometryFileRcd> mayConsumeBlobToken_;
0076     const bool debug_;
0077     const bool useMergeFileIfAvailable_;
0078   };
0079 }  // namespace magneticfield
0080 
0081 DD4hep_VolumeBasedMagneticFieldESProducerFromDB::DD4hep_VolumeBasedMagneticFieldESProducerFromDB(
0082     const edm::ParameterSet& iConfig)
0083     : debug_(iConfig.getUntrackedParameter<bool>("debugBuilder")),
0084       useMergeFileIfAvailable_(iConfig.getParameter<bool>("useMergeFileIfAvailable")) {
0085   std::string const myConfigLabel = "VBMFESChoice";
0086   usesResources({edm::ESSharedResourceNames::kDD4hep});
0087 
0088   //Based on configuration, pick algorithm to produce the proper MagFieldConfig with a specific label
0089   const int current = iConfig.getParameter<int>("valueOverride");
0090   if (current < 0) {
0091     //We do not know what to get until we first read RunInfo
0092     setWhatProduced(
0093         this, &DD4hep_VolumeBasedMagneticFieldESProducerFromDB::chooseConfigAtRuntime, edm::es::Label(myConfigLabel))
0094         .setMayConsume(
0095             mayGetConfigToken_,
0096             [](auto const& iGet, edm::ESTransientHandle<RunInfo> iHandle) {
0097               auto const label = closerNominalLabel(iHandle->m_avg_current);
0098               edm::LogInfo("MagneticField") << "Current :" << iHandle->m_avg_current
0099                                             << " (from RunInfo DB); using map configuration with label: " << label;
0100               return iGet("", label);
0101             },
0102             edm::ESProductTag<RunInfo, RunInfoRcd>("", ""));
0103 
0104   } else {
0105     //we know exactly what we are going to get
0106     auto const label = closerNominalLabel(current);
0107     edm::LogInfo("MagneticField") << "Current :" << current
0108                                   << " (from valueOverride card); using map configuration with label: " << label;
0109     auto cc = setWhatProduced(this,
0110                               &DD4hep_VolumeBasedMagneticFieldESProducerFromDB::chooseConfigViaParameter,
0111                               edm::es::Label(myConfigLabel));
0112 
0113     knownFromParamConfigToken_ = cc.consumes(edm::ESInputTag(""s, std::string(label)));
0114   }
0115 
0116   auto const label = iConfig.getUntrackedParameter<std::string>("label");
0117   auto const myConfigTag = edm::ESInputTag(iConfig.getParameter<std::string>("@module_label"), myConfigLabel);
0118 
0119   //We use the MagFieldConfig created above to decide which FileBlob to use
0120   auto cc = setWhatProduced(this, label);
0121   cc.setMayConsume(
0122       mayConsumeBlobToken_,
0123       [](auto const& iGet, edm::ESTransientHandle<MagFieldConfig> iConfig) {
0124         if (iConfig->version == "parametrizedMagneticField") {
0125           return iGet.nothing();
0126         }
0127         return iGet("", std::to_string(iConfig->geometryVersion));
0128       },
0129       edm::ESProductTag<MagFieldConfig, IdealMagneticFieldRecord>(myConfigTag));
0130   chosenConfigToken_ = cc.consumes(myConfigTag);  //Use same tag as the choice
0131 }
0132 
0133 std::shared_ptr<MagFieldConfig const> DD4hep_VolumeBasedMagneticFieldESProducerFromDB::chooseConfigAtRuntime(
0134     IdealMagneticFieldRecord const& iRcd) {
0135   edm::ESHandle<MagFieldConfig> config = iRcd.getHandle(mayGetConfigToken_);
0136 
0137   //just forward what we just got but do not take ownership
0138   return std::shared_ptr<MagFieldConfig const>(config.product(), [](auto*) {});
0139 }
0140 
0141 std::shared_ptr<MagFieldConfig const> DD4hep_VolumeBasedMagneticFieldESProducerFromDB::chooseConfigViaParameter(
0142     const IdealMagneticFieldRecord& iRecord) {
0143   auto config = iRecord.getHandle(knownFromParamConfigToken_);
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 // ------------ method called to produce the data  ------------
0150 std::unique_ptr<MagneticField> DD4hep_VolumeBasedMagneticFieldESProducerFromDB::produce(
0151     const IdealMagneticFieldRecord& iRecord) {
0152   auto const& conf = iRecord.getTransientHandle(chosenConfigToken_);
0153 
0154   std::unique_ptr<MagneticField> paramField =
0155       ParametrizedMagneticFieldFactory::get(conf->slaveFieldVersion, conf->slaveFieldParameters);
0156 
0157   edm::LogInfo("MagneticField") << "(DD4hep) Version: " << conf->version
0158                                 << " geometryVersion: " << conf->geometryVersion
0159                                 << " slaveFieldVersion: " << conf->slaveFieldVersion;
0160 
0161   if (conf->version == "parametrizedMagneticField") {
0162     // The map consist of only the parametrization in this case
0163     return paramField;
0164   }
0165 
0166   // Full VolumeBased map + parametrization
0167   MagGeoBuilder builder(conf->version, conf->geometryVersion, debug_, useMergeFileIfAvailable_);
0168 
0169   // Set scaling factors
0170   if (!conf->keys.empty()) {
0171     builder.setScaling(conf->keys, conf->values);
0172   }
0173 
0174   // Set specification for the grid tables to be used.
0175   if (!conf->gridFiles.empty()) {
0176     builder.setGridFiles(conf->gridFiles);
0177   }
0178 
0179   // Build the geometry from the DB blob
0180 
0181   auto const& blob = iRecord.getTransientHandle(mayConsumeBlobToken_);
0182   std::unique_ptr<std::vector<unsigned char> > tb = blob->getUncompressedBlob();
0183 
0184   string sblob(tb->begin(), tb->end());
0185   sblob.insert(
0186       sblob.rfind("</DDDefinition>"),
0187       "<MaterialSection label=\"materials.xml\"><ElementaryMaterial name=\"materials:Vacuum\" density=\"1e-13*mg/cm3\" "
0188       "symbol=\" \" atomicWeight=\"1*g/mole\" atomicNumber=\"1\"/></MaterialSection>");
0189 
0190   auto ddet = make_unique<cms::DDDetector>("cmsMagneticField:MAGF", sblob, true);
0191 
0192   builder.build(ddet.get());
0193 
0194   // Build the VB map. Ownership of the parametrization is transferred to it
0195   return std::make_unique<VolumeBasedMagneticField>(conf->geometryVersion,
0196                                                     builder.barrelLayers(),
0197                                                     builder.endcapSectors(),
0198                                                     builder.barrelVolumes(),
0199                                                     builder.endcapVolumes(),
0200                                                     builder.maxR(),
0201                                                     builder.maxZ(),
0202                                                     paramField.release(),
0203                                                     true);
0204 }
0205 
0206 std::string_view DD4hep_VolumeBasedMagneticFieldESProducerFromDB::closerNominalLabel(float current) {
0207   constexpr std::array<int, 7> nominalCurrents = {{-1, 0, 9558, 14416, 16819, 18268, 19262}};
0208   constexpr std::array<std::string_view, 7> nominalLabels = {{"3.8T", "0T", "2T", "3T", "3.5T", "3.8T", "4T"}};
0209 
0210   int i = 0;
0211   for (; i < (int)nominalLabels.size() - 1; i++) {
0212     if (2 * current < nominalCurrents[i] + nominalCurrents[i + 1])
0213       return nominalLabels[i];
0214   }
0215   return nominalLabels[i];
0216 }
0217 
0218 void DD4hep_VolumeBasedMagneticFieldESProducerFromDB::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
0219   edm::ParameterSetDescription desc;
0220   desc.addUntracked<bool>("debugBuilder", false);
0221   desc.add<bool>("useMergeFileIfAvailable", true);
0222   desc.add<int>("valueOverride", -1)->setComment("Force value of current (in A); take the value from DB if < 0.");
0223   desc.addUntracked<std::string>("label", "");
0224 
0225   descriptions.addDefault(desc);
0226 }
0227 
0228 DEFINE_FWK_EVENTSETUP_MODULE(DD4hep_VolumeBasedMagneticFieldESProducerFromDB);