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)