diff --git a/Alignment/TrackerAlignment/plugins/BuildFile.xml b/Alignment/TrackerAlignment/plugins/BuildFile.xml index 80f73aeb586ab..63b1ccd1b6d27 100644 --- a/Alignment/TrackerAlignment/plugins/BuildFile.xml +++ b/Alignment/TrackerAlignment/plugins/BuildFile.xml @@ -1,10 +1,21 @@ - - - - - + + + + + + + + + + + + + + + + diff --git a/Alignment/TrackerAlignment/plugins/MCMisalignmentScaler.cc b/Alignment/TrackerAlignment/plugins/MCMisalignmentScaler.cc new file mode 100644 index 0000000000000..ac61ac6191660 --- /dev/null +++ b/Alignment/TrackerAlignment/plugins/MCMisalignmentScaler.cc @@ -0,0 +1,284 @@ +// -*- C++ -*- +// +// Package: Alignment/TrackerAlignment +// Class: MCMisalignmentScaler +// +/**\class MCMisalignmentScaler MCMisalignmentScaler.cc Alignment/TrackerAlignment/plugins/MCMisalignmentScaler.cc + + Description: Plugin to rescale misalignment wrt. ideal geometry + + Implementation: + + The plugin takes the ideal geometry and the alignment object and rescales + the position difference by the scaling factor provided by the user. + +*/ +// +// Original Author: Gregor Mittag +// Created: Tue, 10 Oct 2017 15:49:17 GMT +// +// + + +// system include files +#include +#include + +// user include files +#include "FWCore/Framework/interface/Frameworkfwd.h" +#include "FWCore/Framework/interface/one/EDAnalyzer.h" +#include "FWCore/Framework/interface/Event.h" +#include "FWCore/Framework/interface/EventSetup.h" +#include "FWCore/Framework/interface/ESHandle.h" +#include "FWCore/Framework/interface/MakerMacros.h" +#include "FWCore/ParameterSet/interface/ParameterSet.h" +#include "FWCore/ServiceRegistry/interface/Service.h" + +#include "CalibFormats/SiStripObjects/interface/SiStripQuality.h" +#include "CalibTracker/Records/interface/SiStripQualityRcd.h" + +#include "CondCore/DBOutputService/interface/PoolDBOutputService.h" + +#include "CondFormats/Alignment/interface/Alignments.h" +#include "CondFormats/AlignmentRecord/interface/TrackerAlignmentRcd.h" +#include "CondFormats/DataRecord/interface/SiPixelQualityRcd.h" +#include "CondFormats/GeometryObjects/interface/PTrackerParameters.h" +#include "CondFormats/SiPixelObjects/interface/SiPixelQuality.h" + +#include "DataFormats/TrackerCommon/interface/TrackerTopology.h" + +#include "Geometry/TrackerGeometryBuilder/interface/TrackerGeometry.h" +#include "Geometry/TrackerGeometryBuilder/interface/TrackerGeomBuilderFromGeometricDet.h" +#include "Geometry/Records/interface/IdealGeometryRecord.h" +#include "Geometry/Records/interface/TrackerTopologyRcd.h" +#include "Geometry/Records/interface/PTrackerParametersRcd.h" + +// +// class declaration +// + +class MCMisalignmentScaler : public edm::one::EDAnalyzer<> { +public: + explicit MCMisalignmentScaler(const edm::ParameterSet&); + ~MCMisalignmentScaler() override = default; + + static void fillDescriptions(edm::ConfigurationDescriptions&); + +private: + using ScalerMap = std::unordered_map >; + + void analyze(const edm::Event&, const edm::EventSetup&) override; + ScalerMap decodeSubDetectors(const edm::VParameterSet&); + + // ----------member data --------------------------- + const ScalerMap scalers_; + const bool pullBadModulesToIdeal_; + bool firstEvent_{true}; +}; + +// +// constructors and destructor +// +MCMisalignmentScaler::MCMisalignmentScaler(const edm::ParameterSet& iConfig) : + scalers_{decodeSubDetectors(iConfig.getParameter("scalers"))}, + pullBadModulesToIdeal_{iConfig.getUntrackedParameter("pullBadModulesToIdeal")} +{ +} + + + +// +// member functions +// + +// ------------ method called for each event ------------ +void +MCMisalignmentScaler::analyze(const edm::Event&, const edm::EventSetup& iSetup) +{ + if (!firstEvent_) return; + firstEvent_ = false; + + // get handle on bad modules + edm::ESHandle pixelModules; + iSetup.get().get(pixelModules); + edm::ESHandle stripModules; + iSetup.get().get(stripModules); + + // get the tracker geometry + edm::ESHandle geometricDet; + iSetup.get().get(geometricDet); + edm::ESHandle ptp; + iSetup.get().get(ptp); + edm::ESHandle tTopoHandle; + iSetup.get().get(tTopoHandle); + const auto* const topology = tTopoHandle.product(); + TrackerGeomBuilderFromGeometricDet trackerBuilder; + auto tracker = std::unique_ptr { + trackerBuilder.build(&(*geometricDet), *ptp, topology)}; + + auto dets = tracker->dets(); + std::sort(dets.begin(), dets.end(), + [](const auto& a, const auto& b) { + return a->geographicalId().rawId() < b->geographicalId().rawId();}); + + // get the input alignment + edm::ESHandle alignments; + iSetup.get().get(alignments); + + if (dets.size() != alignments->m_align.size()) { + throw cms::Exception("GeometryMismatch") + << "Size mismatch between alignments (size=" << alignments->m_align.size() + << ") and ideal geometry (size=" << dets.size() << ")"; + } + + Alignments rescaledAlignments{}; + { + auto ideal = dets.cbegin(); + const auto& ideal_end = dets.cend(); + auto misaligned = alignments->m_align.cbegin(); + for (; ideal != ideal_end; ++ideal, ++misaligned) { + if ((*ideal)->geographicalId().rawId() != misaligned->rawId()) { + throw cms::Exception("GeometryMismatch") + << "Order differs between Dets in alignments ideal geometry."; + } + + // determine scale factor + const auto& subDetId = (*ideal)->geographicalId().subdetId(); + auto side = topology->side((*ideal)->geographicalId()); + if (side == 0) { + switch(subDetId) { + case PixelSubdetector::PixelBarrel: + side = 1; // both sides are treated identical -> pick one of them + break; + case StripSubdetector::TIB: + side = topology->tibSide((*ideal)->geographicalId()); + break; + case StripSubdetector::TOB: + side = topology->tobSide((*ideal)->geographicalId()); + break; + default: break; + } + } + const auto& scaleFactor = (pullBadModulesToIdeal_ && + (pixelModules->IsModuleBad(misaligned->rawId()) || + stripModules->IsModuleBad(misaligned->rawId())) ? + 0.0 : + scalers_.find(subDetId)->second.find(side)->second); + + auto x_diff = misaligned->translation().x() - (*ideal)->position().x(); + auto y_diff = misaligned->translation().y() - (*ideal)->position().y(); + auto z_diff = misaligned->translation().z() - (*ideal)->position().z(); + const AlignTransform::Translation rescaledTranslation{ + (*ideal)->position().x() + scaleFactor*x_diff, + (*ideal)->position().y() + scaleFactor*y_diff, + (*ideal)->position().z() + scaleFactor*z_diff + }; + + const AlignTransform rescaledTransform{rescaledTranslation, + misaligned->rotation(), + misaligned->rawId()}; + rescaledAlignments.m_align.emplace_back(std::move(rescaledTransform)); + } + } + + edm::Service poolDb; + if (!poolDb.isAvailable()) { + throw cms::Exception("NotAvailable") << "PoolDBOutputService not available"; + } + edm::LogInfo("Alignment") + << "Writing rescaled tracker-alignment record."; + const auto& since = cond::timeTypeSpecs[cond::runnumber].beginValue; + poolDb->writeOne(&rescaledAlignments, since, "TrackerAlignmentRcd"); + +} + + +MCMisalignmentScaler::ScalerMap +MCMisalignmentScaler::decodeSubDetectors(const edm::VParameterSet& psets) +{ + // initialize scaler map + ScalerMap subDetMap; + for (unsigned int subDetId = 1; subDetId <= 6; ++subDetId) { + subDetMap[subDetId][1] = 1.0; + subDetMap[subDetId][2] = 1.0; + } + + // apply scale factors from configuration + for (const auto& pset: psets) { + const auto& name = pset.getUntrackedParameter("subDetector"); + const auto& factor = pset.getUntrackedParameter("factor"); + + std::vector sides; + if (name.find("-") != std::string::npos) sides.push_back(1); + if (name.find("+") != std::string::npos) sides.push_back(2); + if (sides.empty()) { // -> use both sides + sides.push_back(1); + sides.push_back(2); + } + + if (name.find("Tracker") != std::string::npos) { + for (unsigned int subDetId = 1; subDetId <= 6; ++subDetId) { + for (const auto& side: sides) subDetMap[subDetId][side] *= factor; + } + if (sides.size() == 1) { + // if only one side to be scaled + // -> scale also the other side for PXB (subdetid = 1) + subDetMap[PixelSubdetector::PixelBarrel][std::abs(sides[0] - 2) + 1] *= factor; + } + } else if (name.find("PXB") != std::string::npos) { + // ignore sides for PXB + subDetMap[PixelSubdetector::PixelBarrel][1] *= factor; + subDetMap[PixelSubdetector::PixelBarrel][2] *= factor; + } else if (name.find("PXF") != std::string::npos) { + for (const auto& side: sides) subDetMap[PixelSubdetector::PixelEndcap][side] *= factor; + } else if (name.find("TIB") != std::string::npos) { + for (const auto& side: sides) subDetMap[StripSubdetector::TIB][side] *= factor; + } else if (name.find("TOB") != std::string::npos) { + for (const auto& side: sides) subDetMap[StripSubdetector::TOB][side] *= factor; + } else if (name.find("TID") != std::string::npos) { + for (const auto& side: sides) subDetMap[StripSubdetector::TID][side] *= factor; + } else if (name.find("TEC") != std::string::npos) { + for (const auto& side: sides) subDetMap[StripSubdetector::TEC][side] *= factor; + } else { + throw cms::Exception("BadConfig") + << "@SUB=MCMisalignmentScaler::decodeSubDetectors\n" + << "Unknown tracker subdetector: " << name + << "\nSupported options: Tracker, PXB, PXF, TIB, TOB, TID, TEC " + << "(possibly decorated with '+' or '-')"; + } + } + + std::stringstream logInfo; + logInfo << "MC misalignment scale factors:\n"; + for (const auto& subdet: subDetMap) { + logInfo << " Subdet " << subdet.first << "\n"; + for (const auto& side: subdet.second) { + logInfo << " side " << side.first << ": " << side.second << "\n"; + } + logInfo << "\n"; + } + edm::LogInfo("Alignment") << logInfo.str(); + + return subDetMap; +} + + +// ------------ method fills 'descriptions' with the allowed parameters for the module ------------ +void +MCMisalignmentScaler::fillDescriptions(edm::ConfigurationDescriptions& descriptions) +{ + edm::ParameterSetDescription desc; + desc.setComment("Creates rescaled MC misalignment scenario. " + "PoolDBOutputService must be set up for 'TrackerAlignmentRcd'."); + edm::ParameterSetDescription descScaler; + descScaler.setComment("ParameterSet specifying the tracker part to be scaled " + "by a given factor."); + descScaler.addUntracked("subDetector", "Tracker"); + descScaler.addUntracked("factor", 1.0); + desc.addVPSet("scalers", descScaler, std::vector(1)); + desc.addUntracked("pullBadModulesToIdeal", false); + descriptions.add("mcMisalignmentScaler", desc); +} + +//define this as a plug-in +DEFINE_FWK_MODULE(MCMisalignmentScaler); diff --git a/Alignment/TrackerAlignment/test/mcMisalignmentScaler_cfg.py b/Alignment/TrackerAlignment/test/mcMisalignmentScaler_cfg.py new file mode 100644 index 0000000000000..384859dcfc29c --- /dev/null +++ b/Alignment/TrackerAlignment/test/mcMisalignmentScaler_cfg.py @@ -0,0 +1,49 @@ +import FWCore.ParameterSet.Config as cms +process = cms.Process("MCMisalignmentScaler") + +process.load("Configuration.StandardSequences.MagneticField_cff") # B-field map +process.load("Configuration.Geometry.GeometryRecoDB_cff") # Ideal geometry and interface +process.load("Configuration.StandardSequences.FrontierConditions_GlobalTag_cff") # Global tag +from Configuration.AlCa.GlobalTag import GlobalTag +process.siStripQualityESProducer.ListOfRecordToMerge = cms.VPSet( + cms.PSet(record = cms.string("RunInfoRcd"), tag = cms.string("")), + cms.PSet(record = cms.string("SiStripBadChannelRcd"), tag = cms.string("")), + cms.PSet(record = cms.string("SiStripBadFiberRcd"), tag = cms.string("")), + cms.PSet(record = cms.string("SiStripBadModuleRcd"), tag = cms.string("")), + cms.PSet(record = cms.string("SiStripBadStripRcd"), tag = cms.string("")), + cms.PSet(record = cms.string("SiStripDetCablingRcd"), tag = cms.string("")), +) +process.load("Alignment.TrackerAlignment.mcMisalignmentScaler_cfi") + +################################################################################ +# parameters to configure: +process.GlobalTag = GlobalTag(process.GlobalTag, "auto:phase1_2017_realistic") +process.mcMisalignmentScaler.scalers.append( + cms.PSet( + subDetector = cms.untracked.string("Tracker"), + factor = cms.untracked.double(0.2) + ) +) +process.mcMisalignmentScaler.pullBadModulesToIdeal = False +################################################################################ + + +usedGlobalTag = process.GlobalTag.globaltag.value() +print "Using Global Tag:", usedGlobalTag + +from CondCore.CondDB.CondDB_cfi import CondDB +process.PoolDBOutputService = cms.Service("PoolDBOutputService", + CondDB, + timetype = cms.untracked.string("runnumber"), + toPut = cms.VPSet( + cms.PSet( + record = cms.string("TrackerAlignmentRcd"), + tag = cms.string("Alignments") + ), + ) +) +process.PoolDBOutputService.connect = "sqlite_file:misalignment_rescaled0p2.db" + +process.maxEvents = cms.untracked.PSet(input = cms.untracked.int32(1)) +process.source = cms.Source("EmptySource") +process.p = cms.Path(process.mcMisalignmentScaler)