Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add DD4Hep version MF producer from DB #28832

Merged
merged 3 commits into from Feb 5, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
@@ -0,0 +1,13 @@
# This cfi sets a field map configured based on the run and GT.
#
# PLEASE DO NOT USE THIS cfi DIRECTLY
# Always use the standard sequence Configuration.StandardSequences.MagneticField_cff

import FWCore.ParameterSet.Config as cms

VolumeBasedMagneticFieldESProducer = cms.ESProducer("DD4hep_VolumeBasedMagneticFieldESProducerFromDB",
label = cms.untracked.string(''),
debugBuilder = cms.untracked.bool(False),
valueOverride = cms.int32(-1), # Force value of current (in A); take the value from DB if < 0.
)

12 changes: 9 additions & 3 deletions MagneticField/Engine/test/regression.py
Expand Up @@ -8,7 +8,7 @@
'static_DDD', #default value
VarParsing.VarParsing.multiplicity.singleton,
VarParsing.VarParsing.varType.string,
"MF producer to use. Valid values: 'static_DDD', 'static_DD4Hep' or 'fromDB'")
"MF producer to use. Valid values: 'static_DDD', 'static_DD4Hep', 'fromDB', 'fromDB_DD4Hep'")

options.register('era',
'RunII', #default value
Expand Down Expand Up @@ -86,8 +86,12 @@
exit()


elif options.producerType == 'fromDB':
process.load("Configuration.StandardSequences.MagneticField_cff")
elif options.producerType == 'fromDB' or options.producerType == 'fromDB_DD4Hep':
if options.producerType == 'fromDB':
process.load("Configuration.StandardSequences.MagneticField_cff")
elif options.producerType == 'fromDB_DD4Hep':
process.load("MagneticField.Engine.volumeBasedMagneticFieldFromDB_dd4hep_cfi")

process.load("Configuration.StandardSequences.FrontierConditions_GlobalTag_cff")
from Configuration.AlCa.GlobalTag import GlobalTag
process.GlobalTag = GlobalTag(process.GlobalTag, 'auto:run2_data', '') # Note: testing the proper set-up of data and MC iovs is beyond the scope of this script.
Expand All @@ -107,6 +111,8 @@
elif options.current > 4779 :
process.VolumeBasedMagneticFieldESProducer.valueOverride = 10000 #2 T



else :
print '\nERROR: invalid producerType', producerType,'\n'

Expand Down
Expand Up @@ -22,7 +22,6 @@
#include "FWCore/ParameterSet/interface/ParameterSet.h"
#include "FWCore/Utilities/interface/ESProductTag.h"

#include "DetectorDescription/Core/interface/DDCompactView.h"
#include "FWCore/Framework/interface/ModuleFactory.h"
#include "MagneticField/GeomBuilder/src/MagGeoBuilderFromDDD.h"

Expand All @@ -40,10 +39,6 @@
#include <iostream>
#include <memory>

#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/classification.hpp>
#include <boost/lexical_cast.hpp>

using namespace std;
using namespace magneticfield;
using namespace edm;
Expand Down
@@ -0,0 +1,220 @@
/** \class DD4hep_VolumeBasedMagneticFieldESProducerFromDB
*
* Producer for the VolumeBasedMagneticField, taking all inputs (geometry, etc) from DB.
* This version uses DD4hep and is adapted from the DDD version (MagneticField/GeomBuilder/plugins/VolumeBasedMagneticFieldESProducerFromDB.cc)
*
*/

#include "FWCore/Framework/interface/EventSetupRecordIntervalFinder.h"
#include "FWCore/Framework/interface/ESProducer.h"

#include "CondFormats/RunInfo/interface/RunInfo.h"
#include "CondFormats/DataRecord/interface/RunSummaryRcd.h"

#include "MagneticField/Engine/interface/MagneticField.h"
#include "FWCore/ParameterSet/interface/ParameterSet.h"
#include "MagneticField/VolumeBasedEngine/interface/VolumeBasedMagneticField.h"
#include "MagneticField/ParametrizedEngine/interface/ParametrizedMagneticFieldFactory.h"

#include "MagneticField/Records/interface/IdealMagneticFieldRecord.h"

#include "FWCore/Framework/interface/ESTransientHandle.h"
#include "FWCore/Framework/interface/EventSetup.h"
#include "FWCore/ParameterSet/interface/ParameterSet.h"
#include "FWCore/Utilities/interface/ESProductTag.h"

#include "FWCore/Framework/interface/ModuleFactory.h"
#include "MagneticField/GeomBuilder/src/DD4hep_MagGeoBuilder.h"

#include "DetectorDescription/DDCMS/interface/DDDetector.h"

#include "CondFormats/Common/interface/FileBlob.h"
#include "CondFormats/DataRecord/interface/MFGeometryFileRcd.h"
#include "MagneticField/Records/interface/IdealMagneticFieldRecord.h"
#include "CondFormats/MFObjects/interface/MagFieldConfig.h"
#include "CondFormats/DataRecord/interface/MagFieldConfigRcd.h"

#include "FWCore/MessageLogger/interface/MessageLogger.h"

#include <string>
#include <vector>
#include <iostream>
#include <memory>

using namespace std;
using namespace magneticfield;
using namespace edm;

namespace magneticfield {
class DD4hep_VolumeBasedMagneticFieldESProducerFromDB : public edm::ESProducer {
public:
DD4hep_VolumeBasedMagneticFieldESProducerFromDB(const edm::ParameterSet& iConfig);
// forbid copy ctor and assignment op.
DD4hep_VolumeBasedMagneticFieldESProducerFromDB(const DD4hep_VolumeBasedMagneticFieldESProducerFromDB&) = delete;
const DD4hep_VolumeBasedMagneticFieldESProducerFromDB& operator=(
const DD4hep_VolumeBasedMagneticFieldESProducerFromDB&) = delete;

std::shared_ptr<MagFieldConfig const> chooseConfigViaParameter(const IdealMagneticFieldRecord& iRecord);
std::shared_ptr<MagFieldConfig const> chooseConfigAtRuntime(const IdealMagneticFieldRecord& iRecord);

std::unique_ptr<MagneticField> produce(const IdealMagneticFieldRecord& iRecord);

static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);

private:
static std::string_view closerNominalLabel(float current);

edm::ESGetToken<MagFieldConfig, MagFieldConfigRcd> mayGetConfigToken_;
edm::ESGetToken<MagFieldConfig, MagFieldConfigRcd> knownFromParamConfigToken_;

//NOTE: change of record since this MagFieldConfig was chosen based on data
// from the record RunInfoRcd so therefore has a dependency upon that record
edm::ESGetToken<MagFieldConfig, IdealMagneticFieldRecord> chosenConfigToken_;

edm::ESGetToken<FileBlob, MFGeometryFileRcd> mayConsumeBlobToken_;
const bool debug_;
};
} // namespace magneticfield

DD4hep_VolumeBasedMagneticFieldESProducerFromDB::DD4hep_VolumeBasedMagneticFieldESProducerFromDB(
const edm::ParameterSet& iConfig)
: debug_(iConfig.getUntrackedParameter<bool>("debugBuilder")) {
std::string const myConfigLabel = "VBMFESChoice";

//Based on configuration, pick algorithm to produce the proper MagFieldConfig with a specific label
const int current = iConfig.getParameter<int>("valueOverride");
if (current < 0) {
//We do not know what to get until we first read RunInfo
setWhatProduced(
this, &DD4hep_VolumeBasedMagneticFieldESProducerFromDB::chooseConfigAtRuntime, edm::es::Label(myConfigLabel))
.setMayConsume(
mayGetConfigToken_,
[](auto const& iGet, edm::ESTransientHandle<RunInfo> iHandle) {
auto const label = closerNominalLabel(iHandle->m_avg_current);
edm::LogInfo("MagneticFieldDB") << "Current :" << iHandle->m_avg_current
<< " (from RunInfo DB); using map configuration with label: " << label;
return iGet("", label);
},
edm::ESProductTag<RunInfo, RunInfoRcd>("", ""));

} else {
//we know exactly what we are going to get
auto const label = closerNominalLabel(current);
edm::LogInfo("MagneticFieldDB") << "Current :" << current
<< " (from valueOverride card); using map configuration with label: " << label;
setWhatProduced(
this, &DD4hep_VolumeBasedMagneticFieldESProducerFromDB::chooseConfigViaParameter, edm::es::Label(myConfigLabel))
.setConsumes(knownFromParamConfigToken_, edm::ESInputTag(""s, std::string(label)));
}

auto const label = iConfig.getUntrackedParameter<std::string>("label");
auto const myConfigTag = edm::ESInputTag(iConfig.getParameter<std::string>("@module_label"), myConfigLabel);

//We use the MagFieldConfig created above to decide which FileBlob to use
setWhatProduced(this, label)
.setMayConsume(
mayConsumeBlobToken_,
[](auto const& iGet, edm::ESTransientHandle<MagFieldConfig> iConfig) {
if (iConfig->version == "parametrizedMagneticField") {
return iGet.nothing();
}
return iGet("", std::to_string(iConfig->geometryVersion));
},
edm::ESProductTag<MagFieldConfig, IdealMagneticFieldRecord>(myConfigTag))
.setConsumes(chosenConfigToken_, myConfigTag); //Use same tag as the choice
}

std::shared_ptr<MagFieldConfig const> DD4hep_VolumeBasedMagneticFieldESProducerFromDB::chooseConfigAtRuntime(
IdealMagneticFieldRecord const& iRcd) {
edm::ESHandle<MagFieldConfig> config = iRcd.getHandle(mayGetConfigToken_);

//just forward what we just got but do not take ownership
return std::shared_ptr<MagFieldConfig const>(config.product(), [](auto*) {});
}

std::shared_ptr<MagFieldConfig const> DD4hep_VolumeBasedMagneticFieldESProducerFromDB::chooseConfigViaParameter(
const IdealMagneticFieldRecord& iRecord) {
auto config = iRecord.getHandle(knownFromParamConfigToken_);

//just forward what we just got but do not take ownership
return std::shared_ptr<MagFieldConfig const>(config.product(), [](auto*) {});
}

// ------------ method called to produce the data ------------
std::unique_ptr<MagneticField> DD4hep_VolumeBasedMagneticFieldESProducerFromDB::produce(
const IdealMagneticFieldRecord& iRecord) {
auto const& conf = iRecord.getTransientHandle(chosenConfigToken_);

std::unique_ptr<MagneticField> paramField =
ParametrizedMagneticFieldFactory::get(conf->slaveFieldVersion, conf->slaveFieldParameters);

edm::LogInfo("MagneticFieldDB") << "Version: " << conf->version << " geometryVersion: " << conf->geometryVersion
<< " slaveFieldVersion: " << conf->slaveFieldVersion;

if (conf->version == "parametrizedMagneticField") {
// The map consist of only the parametrization in this case
return paramField;
}

// Full VolumeBased map + parametrization
MagGeoBuilder builder(conf->version, conf->geometryVersion, debug_);

// Set scaling factors
if (!conf->keys.empty()) {
builder.setScaling(conf->keys, conf->values);
}

// Set specification for the grid tables to be used.
if (!conf->gridFiles.empty()) {
builder.setGridFiles(conf->gridFiles);
}

// Build the geometry from the DB blob

auto const& blob = iRecord.getTransientHandle(mayConsumeBlobToken_);
std::unique_ptr<std::vector<unsigned char> > tb = blob->getUncompressedBlob();

string sblob(tb->begin(), tb->end());
sblob.insert(
sblob.rfind("</DDDefinition>"),
"<MaterialSection label=\"materials.xml\"><ElementaryMaterial name=\"materials:Vacuum\" density=\"1e-13*mg/cm3\" "
"symbol=\" \" atomicWeight=\"1*g/mole\" atomicNumber=\"1\"/></MaterialSection>");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this looks like a kludge.
Is this insert [still] needed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. DD4Hep expects vaccuum to be defined, which was not the case in DDD. Current DB payloads do not therefore include its definition. Adding it here is simpler and safer than replacing all DB payloads.


auto ddet = make_unique<cms::DDDetector>("", sblob, true);

builder.build(ddet.get());

// Build the VB map. Ownership of the parametrization is transferred to it
return std::make_unique<VolumeBasedMagneticField>(conf->geometryVersion,
builder.barrelLayers(),
builder.endcapSectors(),
builder.barrelVolumes(),
builder.endcapVolumes(),
builder.maxR(),
builder.maxZ(),
paramField.release(),
true);
}

std::string_view DD4hep_VolumeBasedMagneticFieldESProducerFromDB::closerNominalLabel(float current) {
constexpr std::array<int, 7> nominalCurrents = {{-1, 0, 9558, 14416, 16819, 18268, 19262}};
constexpr std::array<std::string_view, 7> nominalLabels = {{"3.8T", "0T", "2T", "3T", "3.5T", "3.8T", "4T"}};

int i = 0;
for (; i < (int)nominalLabels.size() - 1; i++) {
if (2 * current < nominalCurrents[i] + nominalCurrents[i + 1])
return nominalLabels[i];
}
return nominalLabels[i];
}

void DD4hep_VolumeBasedMagneticFieldESProducerFromDB::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
edm::ParameterSetDescription desc;
desc.addUntracked<bool>("debugBuilder", false);
desc.add<int>("valueOverride", -1)->setComment("Force value of current (in A); take the value from DB if < 0.");
desc.addUntracked<std::string>("label", "");

descriptions.addDefault(desc);
}

DEFINE_FWK_EVENTSETUP_MODULE(DD4hep_VolumeBasedMagneticFieldESProducerFromDB);
3 changes: 2 additions & 1 deletion MagneticField/GeomBuilder/src/DD4hep_MagGeoBuilder.cc
Expand Up @@ -119,7 +119,8 @@ void MagGeoBuilder::build(const cms::DDDetector* det) {
int eVolCount = 0;

const string magfStr{"MAGF"};
if (fv.name() != magfStr) {
const string magfStr2{"cmsMagneticField:MAGF"};
if (fv.name() != magfStr && fv.name() != magfStr2) {
std::string topNodeName(fv.name());
LogTrace("MagGeoBuilder") << "Filtered view top node name is " << topNodeName << ".";

Expand Down
Expand Up @@ -21,6 +21,7 @@ namespace magneticfield {
class ParametrizedMagneticFieldProducer;
class AutoParametrizedMagneticFieldProducer;
class VolumeBasedMagneticFieldESProducerFromDB;
class DD4hep_VolumeBasedMagneticFieldESProducerFromDB;
} // namespace magneticfield

class ParametrizedMagneticFieldFactory {
Expand All @@ -32,6 +33,7 @@ class ParametrizedMagneticFieldFactory {
friend class magneticfield::ParametrizedMagneticFieldProducer;
friend class magneticfield::AutoParametrizedMagneticFieldProducer;
friend class magneticfield::VolumeBasedMagneticFieldESProducerFromDB;
friend class magneticfield::DD4hep_VolumeBasedMagneticFieldESProducerFromDB;

// Get map configured from pset (deprecated)
std::unique_ptr<MagneticField> static get(std::string version, const edm::ParameterSet& parameters);
Expand Down