diff --git a/CalibTracker/StandaloneTrackerTopology/src/StandaloneTrackerTopology.cc b/CalibTracker/StandaloneTrackerTopology/src/StandaloneTrackerTopology.cc
index a5f54f2330cbe..f137a07966830 100644
--- a/CalibTracker/StandaloneTrackerTopology/src/StandaloneTrackerTopology.cc
+++ b/CalibTracker/StandaloneTrackerTopology/src/StandaloneTrackerTopology.cc
@@ -38,13 +38,31 @@ namespace {
const auto subDet = std::stoi(att_name.substr(SubdetName.size()));
switch (subDet) {
case PixelSubdetector::PixelBarrel: // layer, ladder module
- pxbVals_.layerStartBit_ = vals[0];
- pxbVals_.ladderStartBit_ = vals[1];
- pxbVals_.moduleStartBit_ = vals[2];
- pxbVals_.layerMask_ = vals[3];
- pxbVals_.ladderMask_ = vals[4];
- pxbVals_.moduleMask_ = vals[5];
+ /*
+ In the case of the phase-2 IT there is an additional layer of hierarcy, due ot split sensors in Layer 1
+ What follows is a ugly hack, but at least is consistent with TrackerTopologyEP.cc
+ */
+
+ if (vals.size() > 6) { // Phase 2: extra hierarchy level for 3D sensors
+ pxbVals_.layerStartBit_ = vals[0];
+ pxbVals_.ladderStartBit_ = vals[1];
+ pxbVals_.moduleStartBit_ = vals[2];
+ pxbVals_.doubleStartBit_ = vals[3];
+
+ pxbVals_.layerMask_ = vals[4];
+ pxbVals_.ladderMask_ = vals[5];
+ pxbVals_.moduleMask_ = vals[6];
+ pxbVals_.doubleMask_ = vals[7];
+ } else { // Phase-0 or Phase-1
+ pxbVals_.layerStartBit_ = vals[0];
+ pxbVals_.ladderStartBit_ = vals[1];
+ pxbVals_.moduleStartBit_ = vals[2];
+
+ pxbVals_.layerMask_ = vals[3];
+ pxbVals_.ladderMask_ = vals[4];
+ pxbVals_.moduleMask_ = vals[5];
+ }
foundPXB = true;
break;
diff --git a/CalibTracker/StandaloneTrackerTopology/test/BuildFile.xml b/CalibTracker/StandaloneTrackerTopology/test/BuildFile.xml
new file mode 100644
index 0000000000000..2e31ca71dc10c
--- /dev/null
+++ b/CalibTracker/StandaloneTrackerTopology/test/BuildFile.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/CalibTracker/StandaloneTrackerTopology/test/StandaloneTrackerTopologyTest.cc b/CalibTracker/StandaloneTrackerTopology/test/StandaloneTrackerTopologyTest.cc
new file mode 100644
index 0000000000000..19ca9be23c096
--- /dev/null
+++ b/CalibTracker/StandaloneTrackerTopology/test/StandaloneTrackerTopologyTest.cc
@@ -0,0 +1,229 @@
+// -*- C++ -*-
+//
+// Package: CalibTracker/StandaloneTrackerTopology
+// Class: StandaloneTrackerTopologyTest
+//
+/**\class StandaloneTrackerTopologyTest StandaloneTrackerTopologyTest.cc CalibTracker/StandaloneTrackerTopology/test/StandaloneTrackerTopologyTest.cc
+
+ Description: [one line class summary]
+
+ Implementation:
+ [Notes on implementation]
+*/
+//
+// Original Author: Marco Musich
+// Created: Wed, 18 Oct 2023 10:00:00 GMT
+//
+//
+
+// system include files
+#include
+
+// user include files
+#include "FWCore/Framework/interface/Frameworkfwd.h"
+#include "FWCore/Framework/interface/global/EDAnalyzer.h"
+
+#include "FWCore/Framework/interface/Event.h"
+#include "FWCore/Framework/interface/MakerMacros.h"
+
+#include "FWCore/ParameterSet/interface/ParameterSet.h"
+#include "FWCore/Utilities/interface/InputTag.h"
+
+#include "Geometry/Records/interface/TrackerDigiGeometryRecord.h"
+#include "Geometry/TrackerGeometryBuilder/interface/TrackerGeometry.h"
+#include "DataFormats/TrackerCommon/interface/TrackerTopology.h"
+#include "Geometry/Records/interface/TrackerTopologyRcd.h"
+#include "Geometry/CommonDetUnit/interface/PixelGeomDetUnit.h"
+#include "CalibTracker/StandaloneTrackerTopology/interface/StandaloneTrackerTopology.h"
+
+//
+// class declaration
+//
+
+class StandaloneTrackerTopologyTest : public edm::global::EDAnalyzer<> {
+public:
+ explicit StandaloneTrackerTopologyTest(const edm::ParameterSet&);
+ ~StandaloneTrackerTopologyTest() override = default;
+
+ static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
+
+private:
+ void analyze(edm::StreamID, edm::Event const& iEvent, edm::EventSetup const& iSetup) const override;
+ void testTopology(const TrackerGeometry* pDD,
+ const TrackerTopology* tTopoFromDB,
+ const TrackerTopology* tTopoStandalone) const;
+
+ // ----------member data ---------------------------
+ const edm::ESGetToken geomEsToken_;
+ const edm::ESGetToken topoToken_;
+};
+
+//
+// constructors and destructor
+//
+StandaloneTrackerTopologyTest::StandaloneTrackerTopologyTest(const edm::ParameterSet& iConfig)
+ : geomEsToken_(esConsumes()), topoToken_(esConsumes()) {}
+
+//
+// member functions
+//
+void StandaloneTrackerTopologyTest::testTopology(const TrackerGeometry* pDD,
+ const TrackerTopology* tTopoFromDB,
+ const TrackerTopology* tTopoStandalone) const {
+ // test Barrel Pixel
+ for (auto det : pDD->detsPXB()) {
+ const PixelGeomDetUnit* pixelDet = dynamic_cast(det);
+ const auto& layerA = tTopoFromDB->pxbLayer(pixelDet->geographicalId());
+ const auto& ladderA = tTopoFromDB->pxbLadder(pixelDet->geographicalId());
+ const auto& moduleA = tTopoFromDB->pxbModule(pixelDet->geographicalId());
+
+ const auto& layerB = tTopoStandalone->pxbLayer(pixelDet->geographicalId());
+ const auto& ladderB = tTopoStandalone->pxbLadder(pixelDet->geographicalId());
+ const auto& moduleB = tTopoStandalone->pxbModule(pixelDet->geographicalId());
+
+ if (layerA != layerB || ladderA != ladderB || moduleA != moduleB) {
+ throw cms::Exception("ConfigurationMismatch")
+ << "PXB: Topology from DB doesn't match with Topology from XML file!"
+ << " DetId: " << pixelDet->geographicalId() << " layerA: " << layerA << " layerB: " << layerB
+ << " ladderA :" << ladderA << " ladderB :" << ladderB << " moduleA :" << moduleA << " moduleB :" << moduleB
+ << std::endl;
+ }
+ }
+
+ // test Pixel Endcaps
+ for (auto det : pDD->detsPXF()) {
+ const PixelGeomDetUnit* pixelDet = dynamic_cast(det);
+ const auto& diskA = tTopoFromDB->pxfDisk(pixelDet->geographicalId());
+ const auto& bladeA = tTopoFromDB->pxfBlade(pixelDet->geographicalId());
+ const auto& moduleA = tTopoFromDB->pxfModule(pixelDet->geographicalId());
+
+ const auto& diskB = tTopoStandalone->pxfDisk(pixelDet->geographicalId());
+ const auto& bladeB = tTopoStandalone->pxfBlade(pixelDet->geographicalId());
+ const auto& moduleB = tTopoStandalone->pxfModule(pixelDet->geographicalId());
+
+ if (diskA != diskB || bladeA != bladeB || moduleA != moduleB) {
+ throw cms::Exception("ConfigurationMismatch")
+ << "PXF: Topology from DB doesn't match with Topology from XML file"
+ << " DetId: " << pixelDet->geographicalId() << " diskA: " << diskA << " diskB: " << diskB
+ << " bladeA :" << bladeA << " bladeB :" << bladeB << " moduleA :" << moduleA << " moduleB :" << moduleB
+ << std::endl;
+ }
+ }
+
+ // test inner barrel
+ for (auto det : pDD->detsTIB()) {
+ const GeomDetUnit* Det = dynamic_cast(det);
+ const auto& sideA = tTopoFromDB->tibSide(Det->geographicalId());
+ const auto& layerA = tTopoFromDB->tibLayer(Det->geographicalId());
+ const auto& moduleA = tTopoFromDB->tibModule(Det->geographicalId());
+
+ const auto& sideB = tTopoStandalone->tibSide(Det->geographicalId());
+ const auto& layerB = tTopoStandalone->tibLayer(Det->geographicalId());
+ const auto& moduleB = tTopoStandalone->tibModule(Det->geographicalId());
+
+ if (sideA != sideB || layerA != layerB || moduleA != moduleB) {
+ throw cms::Exception("ConfigurationMismatch")
+ << "TIB: Topology from DB doesn't match with Topology from XML file"
+ << " DetId: " << Det->geographicalId() << " sideA: " << sideA << " sideB: " << sideB << " layerA :" << layerA
+ << " layerB :" << layerB << " moduleA :" << moduleA << " moduleB :" << moduleB << std::endl;
+ }
+ }
+
+ // test inner disks
+ for (auto det : pDD->detsTID()) {
+ const GeomDetUnit* Det = dynamic_cast(det);
+ const auto& sideA = tTopoFromDB->tidSide(Det->geographicalId());
+ const auto& wheelA = tTopoFromDB->tidWheel(Det->geographicalId());
+ const auto& moduleA = tTopoFromDB->tidModule(Det->geographicalId());
+
+ const auto& sideB = tTopoStandalone->tidSide(Det->geographicalId());
+ const auto& wheelB = tTopoStandalone->tidWheel(Det->geographicalId());
+ const auto& moduleB = tTopoStandalone->tidModule(Det->geographicalId());
+
+ if (sideA != sideB || wheelA != wheelB || moduleA != moduleB) {
+ throw cms::Exception("ConfigurationMismatch")
+ << "TID: Topology from DB doesn't match with Topology from XML file"
+ << " DetId: " << Det->geographicalId() << " sideA: " << sideA << " sideB: " << sideB << " wheelA :" << wheelA
+ << " wheelB :" << wheelB << " moduleA :" << moduleA << " moduleB :" << moduleB << std::endl;
+ }
+ }
+
+ // test outer barrel
+ for (auto det : pDD->detsTOB()) {
+ const GeomDetUnit* Det = dynamic_cast(det);
+
+ const auto& layerA = tTopoFromDB->tobLayer(Det->geographicalId());
+ const auto& rodA = tTopoFromDB->tobRod(Det->geographicalId());
+ const auto& moduleA = tTopoFromDB->tobModule(Det->geographicalId());
+
+ const auto& layerB = tTopoStandalone->tobLayer(Det->geographicalId());
+ const auto& rodB = tTopoStandalone->tobRod(Det->geographicalId());
+ const auto& moduleB = tTopoStandalone->tobModule(Det->geographicalId());
+
+ if (layerA != layerB || rodA != rodB || moduleA != moduleB) {
+ throw cms::Exception("ConfigurationMismatch")
+ << "TOB: Topology from DB doesn't match with Topology from XML file"
+ << " DetId: " << Det->geographicalId() << " layerA :" << layerA << " layerB :" << layerB << " rodA: " << rodA
+ << " rodB: " << rodB << " moduleA :" << moduleA << " moduleB :" << moduleB << std::endl;
+ }
+ }
+
+ // test outer disks
+ for (auto det : pDD->detsTEC()) {
+ const GeomDetUnit* Det = dynamic_cast(det);
+ const auto& sideA = tTopoFromDB->tecSide(Det->geographicalId());
+ const auto& wheelA = tTopoFromDB->tecWheel(Det->geographicalId());
+ const auto& moduleA = tTopoFromDB->tecModule(Det->geographicalId());
+
+ const auto& sideB = tTopoStandalone->tecSide(Det->geographicalId());
+ const auto& wheelB = tTopoStandalone->tecWheel(Det->geographicalId());
+ const auto& moduleB = tTopoStandalone->tecModule(Det->geographicalId());
+
+ if (sideA != sideB || wheelA != wheelB || moduleA != moduleB) {
+ throw cms::Exception("ConfigurationMismatch")
+ << "TEC: Topology from DB doesn't match with Topology from XML file"
+ << " DetId: " << Det->geographicalId() << " sideA: " << sideA << " sideB: " << sideB << " wheelA :" << wheelA
+ << " wheelB :" << wheelB << " moduleA :" << moduleA << " moduleB :" << moduleB << std::endl;
+ }
+ }
+}
+
+// ------------ method called for each event ------------
+void StandaloneTrackerTopologyTest::analyze(edm::StreamID,
+ edm::Event const& iEvent,
+ edm::EventSetup const& iSetup) const {
+ using namespace edm;
+
+ // get the Tracker geometry from event setup
+ const TrackerGeometry* pDD = &iSetup.getData(geomEsToken_);
+ const TrackerTopology* tTopo = &iSetup.getData(topoToken_);
+
+ const char* pathToTopologyXML;
+ if ((pDD->isThere(GeomDetEnumerators::P2PXB)) || (pDD->isThere(GeomDetEnumerators::P2PXEC))) {
+ edm::LogPrint("StandaloneTrackerTopologyTest") << "===== Testing Phase-2 Pixel Tracker geometry =====" << std::endl;
+ pathToTopologyXML = "Geometry/TrackerCommonData/data/PhaseII/trackerParameters.xml";
+ } else if ((pDD->isThere(GeomDetEnumerators::P1PXB)) || (pDD->isThere(GeomDetEnumerators::P1PXEC))) {
+ edm::LogPrint("StandaloneTrackerTopologyTest") << "===== Testing Phase-1 Pixel Tracker geometry =====" << std::endl;
+ pathToTopologyXML = "Geometry/TrackerCommonData/data/PhaseI/trackerParameters.xml";
+ } else {
+ edm::LogPrint("StandaloneTrackerTopologyTest") << "===== Testing Phase-0 Pixel Tracker geometry =====" << std::endl;
+ pathToTopologyXML = "Geometry/TrackerCommonData/data/trackerParameters.xml";
+ }
+
+ edm::LogPrint("StandaloneTrackerTopologyTest") << "parameters file" << pathToTopologyXML << std::endl;
+
+ TrackerTopology tTopoStandalone =
+ StandaloneTrackerTopology::fromTrackerParametersXMLFile(edm::FileInPath(pathToTopologyXML).fullPath());
+
+ // the actual test
+ testTopology(pDD, tTopo, &tTopoStandalone);
+}
+
+// ------------ method fills 'descriptions' with the allowed parameters for the module ------------
+void StandaloneTrackerTopologyTest::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
+ edm::ParameterSetDescription desc;
+ descriptions.addDefault(desc);
+}
+
+//define this as a plug-in
+DEFINE_FWK_MODULE(StandaloneTrackerTopologyTest);
diff --git a/CalibTracker/StandaloneTrackerTopology/test/testStandaloneTrackerTopology.sh b/CalibTracker/StandaloneTrackerTopology/test/testStandaloneTrackerTopology.sh
new file mode 100755
index 0000000000000..afa0a21421eae
--- /dev/null
+++ b/CalibTracker/StandaloneTrackerTopology/test/testStandaloneTrackerTopology.sh
@@ -0,0 +1,9 @@
+#!/bin/sh
+
+function die { echo $1: status $2 ; exit $2; }
+
+echo " testing CalibTracker/StandalonTrackerTopology"
+
+cmsRun ${SCRAM_TEST_PATH}/testStandaloneTrackerTopology_cfg.py || die "Failure using cmsRun testPixelTopologyMapTest_cfg.py (Phase-0 test)" $?
+cmsRun ${SCRAM_TEST_PATH}/testStandaloneTrackerTopology_cfg.py runNumber=300000 || die "Failure using cmsRun testPixelTopologyMapTest_cfg.py (Phase-1 test)" $?
+cmsRun ${SCRAM_TEST_PATH}/testStandaloneTrackerTopology_cfg.py globalTag=auto:phase2_realistic_T21 || die "Failure using cmsRun testPixelTopologyMapTest_cfg.py (Phase-2 test)" $?
diff --git a/CalibTracker/StandaloneTrackerTopology/test/testStandaloneTrackerTopology_cfg.py b/CalibTracker/StandaloneTrackerTopology/test/testStandaloneTrackerTopology_cfg.py
new file mode 100644
index 0000000000000..c4896e4e59c96
--- /dev/null
+++ b/CalibTracker/StandaloneTrackerTopology/test/testStandaloneTrackerTopology_cfg.py
@@ -0,0 +1,66 @@
+import FWCore.ParameterSet.Config as cms
+import FWCore.ParameterSet.VarParsing as VarParsing
+
+process = cms.Process("TopologyAnalysis")
+options = VarParsing.VarParsing("analysis")
+
+options.register ('globalTag',
+ "auto:run2_data",
+ VarParsing.VarParsing.multiplicity.singleton, # singleton or list
+ VarParsing.VarParsing.varType.string, # string, int, or float
+ "GlobalTag")
+
+options.register ('runNumber',
+ 1,
+ VarParsing.VarParsing.multiplicity.singleton, # singleton or list
+ VarParsing.VarParsing.varType.int, # string, int, or float
+ "run number")
+
+options.parseArguments()
+
+###################################################################
+# Message logger service
+###################################################################
+process.load("FWCore.MessageService.MessageLogger_cfi")
+process.MessageLogger.cerr.FwkReport.reportEvery = 1
+
+###################################################################
+# Geometry producer and standard includes
+###################################################################
+process.load("Configuration.StandardSequences.Services_cff")
+
+if 'phase2' in options.globalTag:
+ process.load("Configuration.Geometry.GeometryExtended2026D98_cff")
+ process.load("Configuration.Geometry.GeometryExtended2026D98Reco_cff")
+else:
+ process.load("Configuration.StandardSequences.GeometryRecoDB_cff")
+
+####################################################################
+# Get the GlogalTag
+####################################################################
+process.load("Configuration.StandardSequences.FrontierConditions_GlobalTag_cff")
+from Configuration.AlCa.GlobalTag import GlobalTag
+process.GlobalTag = GlobalTag(process.GlobalTag, options.globalTag, '')
+
+###################################################################
+# Empty Source
+###################################################################
+process.source = cms.Source("EmptySource",
+ firstRun = cms.untracked.uint32(options.runNumber),
+ numberEventsInRun = cms.untracked.uint32(1),
+ )
+
+process.maxEvents = cms.untracked.PSet(
+ input = cms.untracked.int32(1)
+)
+
+###################################################################
+# The analysis module
+###################################################################
+process.myanalysis = cms.EDAnalyzer("StandaloneTrackerTopologyTest")
+
+###################################################################
+# Path
+###################################################################
+process.p1 = cms.Path(process.myanalysis)
+
diff --git a/CondCore/SiPixelPlugins/interface/PixelRegionContainers.h b/CondCore/SiPixelPlugins/interface/PixelRegionContainers.h
index 9965eb7c3d51a..4b2adef075c62 100644
--- a/CondCore/SiPixelPlugins/interface/PixelRegionContainers.h
+++ b/CondCore/SiPixelPlugins/interface/PixelRegionContainers.h
@@ -297,9 +297,8 @@ namespace PixelRegions {
if (m_theMap.find(myId) != m_theMap.end()) {
m_theMap[myId]->Fill(value);
} else {
- edm::LogError("PixelRegionContainers")
- << detid << " :=> " << myId << " is not a recongnized PixelId enumerator! \n"
- << m_trackerTopo->print(detid);
+ throw cms::Exception("LogicError") << detid << " :=> " << myId << " is not a recongnized PixelId enumerator! \n"
+ << m_trackerTopo->print(detid);
}
}
diff --git a/CondCore/SiPixelPlugins/interface/SiPixelPayloadInspectorHelper.h b/CondCore/SiPixelPlugins/interface/SiPixelPayloadInspectorHelper.h
index ef528b43b4b10..f4f5d9de8a0a9 100644
--- a/CondCore/SiPixelPlugins/interface/SiPixelPayloadInspectorHelper.h
+++ b/CondCore/SiPixelPlugins/interface/SiPixelPayloadInspectorHelper.h
@@ -91,6 +91,15 @@ namespace SiPixelPI {
}
}
+ const void print(std::stringstream& ss) {
+ ss << "---------------------------------------------------------------\n"
+ << " PhaseInfo Data \n\n"
+ << " Phase : " << phase() << "\n"
+ << " DetSide: " << m_detsize << "\n"
+ << " pathToXML: " << pathToTopoXML() << "\n"
+ << "-------------------------------------------------------------\n\n";
+ }
+
const bool isPhase1Comparison(const PhaseInfo& theOtherPhase) const {
if (phase() == phase::one || theOtherPhase.phase() == phase::one)
return true;
@@ -111,6 +120,15 @@ namespace SiPixelPI {
size_t m_detsize;
};
+ //============================================================================
+ // add ostream for PhaseInfo
+ inline std::ostream& operator<<(std::ostream& os, PhaseInfo phInfo) {
+ std::stringstream ss;
+ phInfo.print(ss);
+ os << ss.str();
+ return os;
+ }
+
//============================================================================
inline std::pair unpack(cond::Time_t since) {
auto kLowMask = 0XFFFFFFFF;
diff --git a/CondCore/SiPixelPlugins/plugins/SiPixelLorentzAngle_PayloadInspector.cc b/CondCore/SiPixelPlugins/plugins/SiPixelLorentzAngle_PayloadInspector.cc
index 48d0cde750b25..4a7a699c09fe7 100644
--- a/CondCore/SiPixelPlugins/plugins/SiPixelLorentzAngle_PayloadInspector.cc
+++ b/CondCore/SiPixelPlugins/plugins/SiPixelLorentzAngle_PayloadInspector.cc
@@ -287,6 +287,8 @@ namespace {
// deal with last IOV
const char *path_toTopologyXML = l_phaseInfo.pathToTopoXML();
+ edm::LogPrint("SiPixelLorentzAngleValuesComparisonPerRegion") << l_phaseInfo;
+
auto l_tTopo =
StandaloneTrackerTopology::fromTrackerParametersXMLFile(edm::FileInPath(path_toTopologyXML).fullPath());
diff --git a/CondCore/SiPixelPlugins/test/testSiPixelLorentzAngle.sh b/CondCore/SiPixelPlugins/test/testSiPixelLorentzAngle.sh
index 0d23aaad8c61d..935e5a85b373e 100755
--- a/CondCore/SiPixelPlugins/test/testSiPixelLorentzAngle.sh
+++ b/CondCore/SiPixelPlugins/test/testSiPixelLorentzAngle.sh
@@ -15,6 +15,17 @@ fi
mkdir $W_DIR/plots_LA
+getPayloadData.py \
+ --plugin pluginSiPixelLorentzAngle_PayloadInspector \
+ --plot plot_SiPixelLorentzAngleValuesBarrelCompareTwoTags \
+ --tag SiPixelLorentzAngle_phase2_T19_v1_mc \
+ --tagtwo SiPixelLorentzAngle_phase2_T15_v5_mc \
+ --time_type Run \
+ --iovs '{"start_iov": "1", "end_iov": "1"}' \
+ --iovstwo '{"start_iov": "1", "end_iov": "1"}' \
+ --db Prod \
+ --test ;
+
getPayloadData.py \
--plugin pluginSiPixelLorentzAngle_PayloadInspector \
--plot plot_SiPixelLorentzAngleValuesBarrelCompareTwoTags \