diff --git a/Configuration/ProcessModifiers/python/alpakaValidationPixel_cff.py b/Configuration/ProcessModifiers/python/alpakaValidationPixel_cff.py
new file mode 100644
index 0000000000000..ebdb7d9e6981a
--- /dev/null
+++ b/Configuration/ProcessModifiers/python/alpakaValidationPixel_cff.py
@@ -0,0 +1,6 @@
+import FWCore.ParameterSet.Config as cms
+
+# This modifier chain is for turning on DQM modules used for alpaka device/host validation for pixels
+
+alpakaValidationPixel = cms.Modifier()
+
diff --git a/Configuration/ProcessModifiers/python/alpakaValidation_cff.py b/Configuration/ProcessModifiers/python/alpakaValidation_cff.py
new file mode 100644
index 0000000000000..3399bdda7c4df
--- /dev/null
+++ b/Configuration/ProcessModifiers/python/alpakaValidation_cff.py
@@ -0,0 +1,11 @@
+import FWCore.ParameterSet.Config as cms
+
+from Configuration.ProcessModifiers.alpaka_cff import *
+from Configuration.ProcessModifiers.alpakaValidationPixel_cff import *
+
+# This modifier chain is for turning on DQM modules used for alpaka device/host validation
+
+alpakaValidation = cms.ModifierChain(
+ alpaka,
+ alpakaValidationPixel
+)
diff --git a/Configuration/PyReleaseValidation/python/upgradeWorkflowComponents.py b/Configuration/PyReleaseValidation/python/upgradeWorkflowComponents.py
index ef7525a26b540..3f9a6ed96c9e5 100644
--- a/Configuration/PyReleaseValidation/python/upgradeWorkflowComponents.py
+++ b/Configuration/PyReleaseValidation/python/upgradeWorkflowComponents.py
@@ -894,6 +894,7 @@ def setup_(self, step, stepName, stepDict, k, properties):
# - HLT on CPU
# - Pixel-only reconstruction on CPU, with DQM and validation
# - harvesting
+
upgradeWFs['PatatrackPixelOnlyCPU'] = PatatrackWorkflow(
digi = {
# the HLT menu is already set up for using GPUs if available and if the "gpu" modifier is enabled
@@ -1513,6 +1514,53 @@ def setup_(self, step, stepName, stepDict, k, properties):
offset = 0.597,
)
+
+# Alpaka workflows
+
+upgradeWFs['PatatrackPixelOnlyAlpaka'] = PatatrackWorkflow(
+ digi = {
+ '--procModifiers': 'alpaka'
+ },
+ reco = {
+ '-s': 'RAW2DIGI:RawToDigi_pixelOnly,RECO:reconstruction_pixelTrackingOnly,VALIDATION:@pixelTrackingOnlyValidation,DQM:@pixelTrackingOnlyDQM',
+ '--procModifiers': 'alpaka'
+ },
+ harvest = {
+ '-s': 'HARVESTING:@trackingOnlyValidation+@pixelTrackingOnlyDQM'
+ },
+ suffix = 'Patatrack_PixelOnlyAlpaka',
+ offset = 0.402,
+)
+
+upgradeWFs['PatatrackPixelOnlyAlpakaValidation'] = PatatrackWorkflow(
+ digi = {
+ '--procModifiers': 'alpaka'
+ },
+ reco = {
+ '-s': 'RAW2DIGI:RawToDigi_pixelOnly,RECO:reconstruction_pixelTrackingOnly,VALIDATION:@pixelTrackingOnlyValidation,DQM:@pixelTrackingOnlyDQM',
+ '--procModifiers': 'alpakaValidation'
+ },
+ harvest = {
+ '-s': 'HARVESTING:@trackingOnlyValidation+@pixelTrackingOnlyDQM'
+ },
+ suffix = 'Patatrack_PixelOnlyAlpaka_Validation',
+ offset = 0.403,
+)
+
+upgradeWFs['PatatrackPixelOnlyAlpakaProfiling'] = PatatrackWorkflow(
+ digi = {
+ '--procModifiers': 'alpaka'
+ },
+ reco = {
+ '-s': 'RAW2DIGI:RawToDigi_pixelOnly,RECO:reconstruction_pixelTrackingOnly',
+ '--procModifiers': 'alpaka',
+ '--customise' : 'RecoTracker/Configuration/customizePixelOnlyForProfiling.customizePixelOnlyForProfilingGPUOnly'
+ },
+ harvest = None,
+ suffix = 'Patatrack_PixelOnlyAlpaka_Profiling',
+ offset = 0.404,
+)
+
# end of Patatrack workflows
class UpgradeWorkflow_ProdLike(UpgradeWorkflow):
@@ -2718,7 +2766,7 @@ def condition(self, fragment, stepList, key, hasHarvest):
},
'2022HI' : {
'Geom' : 'DB:Extended',
- 'GT':'auto:phase1_2022_realistic_hi',
+ 'GT':'auto:phase1_2022_realistic_hi',
'HLTmenu': '@fake2',
'Era':'Run3_pp_on_PbPb',
'BeamSpot': 'DBrealistic',
@@ -2726,7 +2774,7 @@ def condition(self, fragment, stepList, key, hasHarvest):
},
'2022HIRP' : {
'Geom' : 'DB:Extended',
- 'GT':'auto:phase1_2022_realistic_hi',
+ 'GT':'auto:phase1_2022_realistic_hi',
'HLTmenu': '@fake2',
'Era':'Run3_pp_on_PbPb_approxSiStripClusters',
'BeamSpot': 'DBrealistic',
@@ -2734,7 +2782,7 @@ def condition(self, fragment, stepList, key, hasHarvest):
},
'2023HI' : {
'Geom' : 'DB:Extended',
- 'GT':'auto:phase1_2023_realistic_hi',
+ 'GT':'auto:phase1_2023_realistic_hi',
'HLTmenu': '@fake2',
'Era':'Run3_pp_on_PbPb',
'BeamSpot': 'DBrealistic',
@@ -2742,7 +2790,7 @@ def condition(self, fragment, stepList, key, hasHarvest):
},
'2023HIRP' : {
'Geom' : 'DB:Extended',
- 'GT':'auto:phase1_2023_realistic_hi',
+ 'GT':'auto:phase1_2023_realistic_hi',
'HLTmenu': '@fake2',
'Era':'Run3_pp_on_PbPb_approxSiStripClusters',
'BeamSpot': 'DBrealistic',
diff --git a/DQM/SiPixelHeterogeneous/plugins/BuildFile.xml b/DQM/SiPixelHeterogeneous/plugins/BuildFile.xml
index 66adf1666762e..79925fdcb6cf8 100644
--- a/DQM/SiPixelHeterogeneous/plugins/BuildFile.xml
+++ b/DQM/SiPixelHeterogeneous/plugins/BuildFile.xml
@@ -5,8 +5,11 @@
+
+
+
+
-
diff --git a/DQM/SiPixelHeterogeneous/plugins/SiPixelCompareRecHitsSoAAlpaka.cc b/DQM/SiPixelHeterogeneous/plugins/SiPixelCompareRecHitsSoAAlpaka.cc
new file mode 100644
index 0000000000000..474194ad72616
--- /dev/null
+++ b/DQM/SiPixelHeterogeneous/plugins/SiPixelCompareRecHitsSoAAlpaka.cc
@@ -0,0 +1,244 @@
+#include "DQMServices/Core/interface/MonitorElement.h"
+#include "DQMServices/Core/interface/DQMEDAnalyzer.h"
+#include "DQMServices/Core/interface/DQMStore.h"
+#include "DataFormats/Math/interface/approx_atan2.h"
+#include "DataFormats/SiPixelDetId/interface/PixelSubdetector.h"
+#include "DataFormats/TrackerCommon/interface/TrackerTopology.h"
+#include "DataFormats/TrackingRecHitSoA/interface/TrackingRecHitsHost.h"
+#include "DataFormats/TrackingRecHitSoA/interface/TrackingRecHitsSoA.h"
+#include "FWCore/Framework/interface/Event.h"
+#include "FWCore/Framework/interface/Frameworkfwd.h"
+#include "FWCore/MessageLogger/interface/MessageLogger.h"
+#include "FWCore/ParameterSet/interface/ParameterSet.h"
+#include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
+#include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
+#include "Geometry/CommonDetUnit/interface/PixelGeomDetUnit.h"
+#include "Geometry/CommonTopologies/interface/PixelTopology.h"
+#include "Geometry/Records/interface/TrackerDigiGeometryRecord.h"
+#include "Geometry/TrackerGeometryBuilder/interface/TrackerGeometry.h"
+
+template
+class SiPixelCompareRecHitsSoAAlpaka : public DQMEDAnalyzer {
+public:
+ using HitsOnHost = TrackingRecHitHost;
+
+ explicit SiPixelCompareRecHitsSoAAlpaka(const edm::ParameterSet&);
+ ~SiPixelCompareRecHitsSoAAlpaka() override = default;
+ void dqmBeginRun(const edm::Run&, const edm::EventSetup&) override;
+ void bookHistograms(DQMStore::IBooker& ibooker, edm::Run const& iRun, edm::EventSetup const& iSetup) override;
+ void analyze(const edm::Event& iEvent, const edm::EventSetup& iSetup) override;
+ static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
+
+private:
+ const edm::ESGetToken geomToken_;
+ const edm::ESGetToken topoToken_;
+ const edm::EDGetTokenT tokenSoAHitsHost_; //these two are both on Host but originally they have been
+ const edm::EDGetTokenT tokenSoAHitsDevice_; //produced on Host or on Device
+ const std::string topFolderName_;
+ const float mind2cut_;
+ static constexpr uint32_t invalidHit_ = std::numeric_limits::max();
+ static constexpr float micron_ = 10000.;
+ const TrackerGeometry* tkGeom_ = nullptr;
+ const TrackerTopology* tTopo_ = nullptr;
+ MonitorElement* hnHits_;
+ MonitorElement* hBchargeL_[4]; // max 4 barrel hits
+ MonitorElement* hBsizexL_[4];
+ MonitorElement* hBsizeyL_[4];
+ MonitorElement* hBposxL_[4];
+ MonitorElement* hBposyL_[4];
+ MonitorElement* hFchargeD_[2][12]; // max 12 endcap disks
+ MonitorElement* hFsizexD_[2][12];
+ MonitorElement* hFsizeyD_[2][12];
+ MonitorElement* hFposxD_[2][12];
+ MonitorElement* hFposyD_[2][12];
+ //differences
+ MonitorElement* hBchargeDiff_;
+ MonitorElement* hFchargeDiff_;
+ MonitorElement* hBsizeXDiff_;
+ MonitorElement* hFsizeXDiff_;
+ MonitorElement* hBsizeYDiff_;
+ MonitorElement* hFsizeYDiff_;
+ MonitorElement* hBposXDiff_;
+ MonitorElement* hFposXDiff_;
+ MonitorElement* hBposYDiff_;
+ MonitorElement* hFposYDiff_;
+};
+
+//
+// constructors
+//
+template
+SiPixelCompareRecHitsSoAAlpaka::SiPixelCompareRecHitsSoAAlpaka(const edm::ParameterSet& iConfig)
+ : geomToken_(esConsumes()),
+ topoToken_(esConsumes()),
+ tokenSoAHitsHost_(consumes(iConfig.getParameter("pixelHitsSrcHost"))),
+ tokenSoAHitsDevice_(consumes(iConfig.getParameter("pixelHitsSrcDevice"))),
+ topFolderName_(iConfig.getParameter("topFolderName")),
+ mind2cut_(iConfig.getParameter("minD2cut")) {}
+
+//
+// Begin Run
+//
+template
+void SiPixelCompareRecHitsSoAAlpaka::dqmBeginRun(const edm::Run& iRun, const edm::EventSetup& iSetup) {
+ tkGeom_ = &iSetup.getData(geomToken_);
+ tTopo_ = &iSetup.getData(topoToken_);
+}
+
+//
+// -- Analyze
+//
+template
+void SiPixelCompareRecHitsSoAAlpaka::analyze(const edm::Event& iEvent, const edm::EventSetup& iSetup) {
+ const auto& rhsoaHandleHost = iEvent.getHandle(tokenSoAHitsHost_);
+ const auto& rhsoaHandleDevice = iEvent.getHandle(tokenSoAHitsDevice_);
+ if (not rhsoaHandleHost or not rhsoaHandleDevice) {
+ edm::LogWarning out("SiPixelCompareRecHitsSoAAlpaka");
+ if (not rhsoaHandleHost) {
+ out << "reference (Host) rechits not found; ";
+ }
+ if (not rhsoaHandleDevice) {
+ out << "target (Device) rechits not found; ";
+ }
+ out << "the comparison will not run.";
+ return;
+ }
+
+ auto const& rhsoaHost = *rhsoaHandleHost;
+ auto const& rhsoaDevice = *rhsoaHandleDevice;
+
+ auto const& soa2dHost = rhsoaHost.const_view();
+ auto const& soa2dDevice = rhsoaDevice.const_view();
+
+ uint32_t nHitsHost = soa2dHost.metadata().size();
+ uint32_t nHitsDevice = soa2dDevice.metadata().size();
+
+ hnHits_->Fill(nHitsHost, nHitsDevice);
+ auto detIds = tkGeom_->detUnitIds();
+ for (uint32_t i = 0; i < nHitsHost; i++) {
+ float minD = mind2cut_;
+ uint32_t matchedHit = invalidHit_;
+ uint16_t indHost = soa2dHost[i].detectorIndex();
+ float xLocalHost = soa2dHost[i].xLocal();
+ float yLocalHost = soa2dHost[i].yLocal();
+ for (uint32_t j = 0; j < nHitsDevice; j++) {
+ if (soa2dDevice.detectorIndex(j) == indHost) {
+ float dx = xLocalHost - soa2dDevice[j].xLocal();
+ float dy = yLocalHost - soa2dDevice[j].yLocal();
+ float distance = dx * dx + dy * dy;
+ if (distance < minD) {
+ minD = distance;
+ matchedHit = j;
+ }
+ }
+ }
+ DetId id = detIds[indHost];
+ uint32_t chargeHost = soa2dHost[i].chargeAndStatus().charge;
+ int16_t sizeXHost = std::ceil(float(std::abs(soa2dHost[i].clusterSizeX()) / 8.));
+ int16_t sizeYHost = std::ceil(float(std::abs(soa2dHost[i].clusterSizeY()) / 8.));
+ uint32_t chargeDevice = 0;
+ int16_t sizeXDevice = -99;
+ int16_t sizeYDevice = -99;
+ float xLocalDevice = -999.;
+ float yLocalDevice = -999.;
+ if (matchedHit != invalidHit_) {
+ chargeDevice = soa2dDevice[matchedHit].chargeAndStatus().charge;
+ sizeXDevice = std::ceil(float(std::abs(soa2dDevice[matchedHit].clusterSizeX()) / 8.));
+ sizeYDevice = std::ceil(float(std::abs(soa2dDevice[matchedHit].clusterSizeY()) / 8.));
+ xLocalDevice = soa2dDevice[matchedHit].xLocal();
+ yLocalDevice = soa2dDevice[matchedHit].yLocal();
+ }
+ switch (id.subdetId()) {
+ case PixelSubdetector::PixelBarrel:
+ hBchargeL_[tTopo_->pxbLayer(id) - 1]->Fill(chargeHost, chargeDevice);
+ hBsizexL_[tTopo_->pxbLayer(id) - 1]->Fill(sizeXHost, sizeXDevice);
+ hBsizeyL_[tTopo_->pxbLayer(id) - 1]->Fill(sizeYHost, sizeYDevice);
+ hBposxL_[tTopo_->pxbLayer(id) - 1]->Fill(xLocalHost, xLocalDevice);
+ hBposyL_[tTopo_->pxbLayer(id) - 1]->Fill(yLocalHost, yLocalDevice);
+ hBchargeDiff_->Fill(chargeHost - chargeDevice);
+ hBsizeXDiff_->Fill(sizeXHost - sizeXDevice);
+ hBsizeYDiff_->Fill(sizeYHost - sizeYDevice);
+ hBposXDiff_->Fill(micron_ * (xLocalHost - xLocalDevice));
+ hBposYDiff_->Fill(micron_ * (yLocalHost - yLocalDevice));
+ break;
+ case PixelSubdetector::PixelEndcap:
+ hFchargeD_[tTopo_->pxfSide(id) - 1][tTopo_->pxfDisk(id) - 1]->Fill(chargeHost, chargeDevice);
+ hFsizexD_[tTopo_->pxfSide(id) - 1][tTopo_->pxfDisk(id) - 1]->Fill(sizeXHost, sizeXDevice);
+ hFsizeyD_[tTopo_->pxfSide(id) - 1][tTopo_->pxfDisk(id) - 1]->Fill(sizeYHost, sizeYDevice);
+ hFposxD_[tTopo_->pxfSide(id) - 1][tTopo_->pxfDisk(id) - 1]->Fill(xLocalHost, xLocalDevice);
+ hFposyD_[tTopo_->pxfSide(id) - 1][tTopo_->pxfDisk(id) - 1]->Fill(yLocalHost, yLocalDevice);
+ hFchargeDiff_->Fill(chargeHost - chargeDevice);
+ hFsizeXDiff_->Fill(sizeXHost - sizeXDevice);
+ hFsizeYDiff_->Fill(sizeYHost - sizeYDevice);
+ hFposXDiff_->Fill(micron_ * (xLocalHost - xLocalDevice));
+ hFposYDiff_->Fill(micron_ * (yLocalHost - yLocalDevice));
+ break;
+ }
+ }
+}
+
+//
+// -- Book Histograms
+//
+template
+void SiPixelCompareRecHitsSoAAlpaka::bookHistograms(DQMStore::IBooker& iBook,
+ edm::Run const& iRun,
+ edm::EventSetup const& iSetup) {
+ iBook.cd();
+ iBook.setCurrentFolder(topFolderName_);
+
+ // clang-format off
+ //Global
+ hnHits_ = iBook.book2I("nHits", "HostvsDevice RecHits per event;#Host RecHits;#Device RecHits", 200, 0, 5000,200, 0, 5000);
+ //Barrel Layer
+ for(unsigned int il=0;ilnumberOfLayers(PixelSubdetector::PixelBarrel);il++){
+ hBchargeL_[il] = iBook.book2I(Form("recHitsBLay%dCharge",il+1), Form("HostvsDevice RecHits Charge Barrel Layer%d;Host Charge;Device Charge",il+1), 250, 0, 100000, 250, 0, 100000);
+ hBsizexL_[il] = iBook.book2I(Form("recHitsBLay%dSizex",il+1), Form("HostvsDevice RecHits SizeX Barrel Layer%d;Host SizeX;Device SizeX",il+1), 30, 0, 30, 30, 0, 30);
+ hBsizeyL_[il] = iBook.book2I(Form("recHitsBLay%dSizey",il+1), Form("HostvsDevice RecHits SizeY Barrel Layer%d;Host SizeY;Device SizeY",il+1), 30, 0, 30, 30, 0, 30);
+ hBposxL_[il] = iBook.book2D(Form("recHitsBLay%dPosx",il+1), Form("HostvsDevice RecHits x-pos in Barrel Layer%d;Host pos x;Device pos x",il+1), 200, -5, 5, 200,-5,5);
+ hBposyL_[il] = iBook.book2D(Form("recHitsBLay%dPosy",il+1), Form("HostvsDevice RecHits y-pos in Barrel Layer%d;Host pos y;Device pos y",il+1), 200, -5, 5, 200,-5,5);
+ }
+ //Endcaps
+ //Endcaps Disk
+ for(int is=0;is<2;is++){
+ int sign=is==0? -1:1;
+ for(unsigned int id=0;idnumberOfLayers(PixelSubdetector::PixelEndcap);id++){
+ hFchargeD_[is][id] = iBook.book2I(Form("recHitsFDisk%+dCharge",id*sign+sign), Form("HostvsDevice RecHits Charge Endcaps Disk%+d;Host Charge;Device Charge",id*sign+sign), 250, 0, 100000, 250, 0, 100000);
+ hFsizexD_[is][id] = iBook.book2I(Form("recHitsFDisk%+dSizex",id*sign+sign), Form("HostvsDevice RecHits SizeX Endcaps Disk%+d;Host SizeX;Device SizeX",id*sign+sign), 30, 0, 30, 30, 0, 30);
+ hFsizeyD_[is][id] = iBook.book2I(Form("recHitsFDisk%+dSizey",id*sign+sign), Form("HostvsDevice RecHits SizeY Endcaps Disk%+d;Host SizeY;Device SizeY",id*sign+sign), 30, 0, 30, 30, 0, 30);
+ hFposxD_[is][id] = iBook.book2D(Form("recHitsFDisk%+dPosx",id*sign+sign), Form("HostvsDevice RecHits x-pos Endcaps Disk%+d;Host pos x;Device pos x",id*sign+sign), 200, -5, 5, 200, -5, 5);
+ hFposyD_[is][id] = iBook.book2D(Form("recHitsFDisk%+dPosy",id*sign+sign), Form("HostvsDevice RecHits y-pos Endcaps Disk%+d;Host pos y;Device pos y",id*sign+sign), 200, -5, 5, 200, -5, 5);
+ }
+ }
+ //1D differences
+ hBchargeDiff_ = iBook.book1D("rechitChargeDiffBpix","Charge differnce of rechits in BPix; rechit charge difference (Host - Device)", 101, -50.5, 50.5);
+ hFchargeDiff_ = iBook.book1D("rechitChargeDiffFpix","Charge differnce of rechits in FPix; rechit charge difference (Host - Device)", 101, -50.5, 50.5);
+ hBsizeXDiff_ = iBook.book1D("rechitsizeXDiffBpix","SizeX difference of rechits in BPix; rechit sizex difference (Host - Device)", 21, -10.5, 10.5);
+ hFsizeXDiff_ = iBook.book1D("rechitsizeXDiffFpix","SizeX difference of rechits in FPix; rechit sizex difference (Host - Device)", 21, -10.5, 10.5);
+ hBsizeYDiff_ = iBook.book1D("rechitsizeYDiffBpix","SizeY difference of rechits in BPix; rechit sizey difference (Host - Device)", 21, -10.5, 10.5);
+ hFsizeYDiff_ = iBook.book1D("rechitsizeYDiffFpix","SizeY difference of rechits in FPix; rechit sizey difference (Host - Device)", 21, -10.5, 10.5);
+ hBposXDiff_ = iBook.book1D("rechitsposXDiffBpix","x-position difference of rechits in BPix; rechit x-pos difference (Host - Device)", 1000, -10, 10);
+ hFposXDiff_ = iBook.book1D("rechitsposXDiffFpix","x-position difference of rechits in FPix; rechit x-pos difference (Host - Device)", 1000, -10, 10);
+ hBposYDiff_ = iBook.book1D("rechitsposYDiffBpix","y-position difference of rechits in BPix; rechit y-pos difference (Host - Device)", 1000, -10, 10);
+ hFposYDiff_ = iBook.book1D("rechitsposYDiffFpix","y-position difference of rechits in FPix; rechit y-pos difference (Host - Device)", 1000, -10, 10);
+}
+
+template
+void SiPixelCompareRecHitsSoAAlpaka::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
+ // monitorpixelRecHitsSoAAlpaka
+ edm::ParameterSetDescription desc;
+ desc.add("pixelHitsSrcHost", edm::InputTag("siPixelRecHitsPreSplittingAlpakaSerial"));
+ desc.add("pixelHitsSrcDevice", edm::InputTag("siPixelRecHitsPreSplittingAlpaka"));
+ desc.add("topFolderName", "SiPixelHeterogeneous/PixelRecHitsCompareDeviceVSHost");
+ desc.add("minD2cut", 0.0001);
+ descriptions.addWithDefaultLabel(desc);
+}
+
+using SiPixelPhase1CompareRecHitsSoAAlpaka = SiPixelCompareRecHitsSoAAlpaka;
+using SiPixelPhase2CompareRecHitsSoAAlpaka = SiPixelCompareRecHitsSoAAlpaka;
+using SiPixelHIonPhase1CompareRecHitsSoAAlpaka = SiPixelCompareRecHitsSoAAlpaka;
+
+#include "FWCore/Framework/interface/MakerMacros.h"
+DEFINE_FWK_MODULE(SiPixelPhase1CompareRecHitsSoAAlpaka);
+DEFINE_FWK_MODULE(SiPixelPhase2CompareRecHitsSoAAlpaka);
+DEFINE_FWK_MODULE(SiPixelHIonPhase1CompareRecHitsSoAAlpaka);
diff --git a/DQM/SiPixelHeterogeneous/plugins/SiPixelCompareTrackSoAAlpaka.cc b/DQM/SiPixelHeterogeneous/plugins/SiPixelCompareTrackSoAAlpaka.cc
new file mode 100644
index 0000000000000..65a6dc2802831
--- /dev/null
+++ b/DQM/SiPixelHeterogeneous/plugins/SiPixelCompareTrackSoAAlpaka.cc
@@ -0,0 +1,308 @@
+// for string manipulations
+#include
+#include "DataFormats/Common/interface/Handle.h"
+#include "DataFormats/Math/interface/deltaR.h"
+#include "DataFormats/Math/interface/deltaPhi.h"
+#include "FWCore/Framework/interface/Event.h"
+#include "FWCore/Framework/interface/Frameworkfwd.h"
+#include "FWCore/Framework/interface/MakerMacros.h"
+#include "FWCore/MessageLogger/interface/MessageLogger.h"
+#include "FWCore/ParameterSet/interface/ParameterSet.h"
+#include "FWCore/Utilities/interface/InputTag.h"
+// DQM Histograming
+#include "DQMServices/Core/interface/MonitorElement.h"
+#include "DQMServices/Core/interface/DQMEDAnalyzer.h"
+#include "DQMServices/Core/interface/DQMStore.h"
+// DataFormats
+#include "DataFormats/TrackSoA/interface/TracksHost.h"
+#include "DataFormats/TrackSoA/interface/alpaka/TrackUtilities.h"
+
+namespace {
+ // same logic used for the MTV:
+ // cf https://github.com/cms-sw/cmssw/blob/master/Validation/RecoTrack/src/MTVHistoProducerAlgoForTracker.cc
+ typedef dqm::reco::DQMStore DQMStore;
+
+ void setBinLog(TAxis* axis) {
+ int bins = axis->GetNbins();
+ float from = axis->GetXmin();
+ float to = axis->GetXmax();
+ float width = (to - from) / bins;
+ std::vector new_bins(bins + 1, 0);
+ for (int i = 0; i <= bins; i++) {
+ new_bins[i] = TMath::Power(10, from + i * width);
+ }
+ axis->Set(bins, new_bins.data());
+ }
+
+ void setBinLogX(TH1* h) {
+ TAxis* axis = h->GetXaxis();
+ setBinLog(axis);
+ }
+ void setBinLogY(TH1* h) {
+ TAxis* axis = h->GetYaxis();
+ setBinLog(axis);
+ }
+
+ template
+ dqm::reco::MonitorElement* make2DIfLog(DQMStore::IBooker& ibook, bool logx, bool logy, Args&&... args) {
+ auto h = std::make_unique(std::forward(args)...);
+ if (logx)
+ setBinLogX(h.get());
+ if (logy)
+ setBinLogY(h.get());
+ const auto& name = h->GetName();
+ return ibook.book2I(name, h.release());
+ }
+} // namespace
+
+template
+class SiPixelCompareTrackSoAAlpaka : public DQMEDAnalyzer {
+public:
+ using PixelTrackSoA = TracksHost;
+
+ explicit SiPixelCompareTrackSoAAlpaka(const edm::ParameterSet&);
+ ~SiPixelCompareTrackSoAAlpaka() override = default;
+ void bookHistograms(DQMStore::IBooker& ibooker, edm::Run const& iRun, edm::EventSetup const& iSetup) override;
+ void analyze(const edm::Event& iEvent, const edm::EventSetup& iSetup) override;
+ static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
+
+private:
+ const edm::EDGetTokenT tokenSoATrackHost_;
+ const edm::EDGetTokenT tokenSoATrackDevice_;
+ const std::string topFolderName_;
+ const bool useQualityCut_;
+ const pixelTrack::Quality minQuality_;
+ const float dr2cut_;
+ MonitorElement* hnTracks_;
+ MonitorElement* hnLooseAndAboveTracks_;
+ MonitorElement* hnLooseAndAboveTracks_matched_;
+ MonitorElement* hnHits_;
+ MonitorElement* hnHitsVsPhi_;
+ MonitorElement* hnHitsVsEta_;
+ MonitorElement* hnLayers_;
+ MonitorElement* hnLayersVsPhi_;
+ MonitorElement* hnLayersVsEta_;
+ MonitorElement* hCharge_;
+ MonitorElement* hchi2_;
+ MonitorElement* hChi2VsPhi_;
+ MonitorElement* hChi2VsEta_;
+ MonitorElement* hpt_;
+ MonitorElement* hptLogLog_;
+ MonitorElement* heta_;
+ MonitorElement* hphi_;
+ MonitorElement* hz_;
+ MonitorElement* htip_;
+ MonitorElement* hquality_;
+ //1D differences
+ MonitorElement* hptdiffMatched_;
+ MonitorElement* hCurvdiffMatched_;
+ MonitorElement* hetadiffMatched_;
+ MonitorElement* hphidiffMatched_;
+ MonitorElement* hzdiffMatched_;
+ MonitorElement* htipdiffMatched_;
+
+ //for matching eff vs region: derive the ratio at harvesting
+ MonitorElement* hpt_eta_tkAllHost_;
+ MonitorElement* hpt_eta_tkAllHostMatched_;
+ MonitorElement* hphi_z_tkAllHost_;
+ MonitorElement* hphi_z_tkAllHostMatched_;
+};
+
+//
+// constructors
+//
+
+template
+SiPixelCompareTrackSoAAlpaka::SiPixelCompareTrackSoAAlpaka(const edm::ParameterSet& iConfig)
+ : tokenSoATrackHost_(consumes(iConfig.getParameter("pixelTrackSrcHost"))),
+ tokenSoATrackDevice_(consumes(iConfig.getParameter("pixelTrackSrcDevice"))),
+ topFolderName_(iConfig.getParameter("topFolderName")),
+ useQualityCut_(iConfig.getParameter("useQualityCut")),
+ minQuality_(pixelTrack::qualityByName(iConfig.getParameter("minQuality"))),
+ dr2cut_(iConfig.getParameter("deltaR2cut")) {}
+
+//
+// -- Analyze
+//
+template
+void SiPixelCompareTrackSoAAlpaka::analyze(const edm::Event& iEvent, const edm::EventSetup& iSetup) {
+ using helper = TracksUtilities;
+ const auto& tsoaHandleHost = iEvent.getHandle(tokenSoATrackHost_);
+ const auto& tsoaHandleDevice = iEvent.getHandle(tokenSoATrackDevice_);
+ if (not tsoaHandleHost or not tsoaHandleDevice) {
+ edm::LogWarning out("SiPixelCompareTrackSoAAlpaka");
+ if (not tsoaHandleHost) {
+ out << "reference (cpu) tracks not found; ";
+ }
+ if (not tsoaHandleDevice) {
+ out << "target (gpu) tracks not found; ";
+ }
+ out << "the comparison will not run.";
+ return;
+ }
+
+ auto const& tsoaHost = *tsoaHandleHost;
+ auto const& tsoaDevice = *tsoaHandleDevice;
+ auto maxTracksHost = tsoaHost.view().metadata().size(); //this should be same for both?
+ auto maxTracksDevice = tsoaDevice.view().metadata().size(); //this should be same for both?
+ auto const* qualityHost = tsoaHost.view().quality();
+ auto const* qualityDevice = tsoaDevice.view().quality();
+ int32_t nTracksHost = 0;
+ int32_t nTracksDevice = 0;
+ int32_t nLooseAndAboveTracksHost = 0;
+ int32_t nLooseAndAboveTracksHost_matchedDevice = 0;
+ int32_t nLooseAndAboveTracksDevice = 0;
+
+ //Loop over Device tracks and store the indices of the loose tracks. Whats happens if useQualityCut_ is false?
+ std::vector looseTrkidxDevice;
+ for (int32_t jt = 0; jt < maxTracksDevice; ++jt) {
+ if (helper::nHits(tsoaDevice.view(), jt) == 0)
+ break; // this is a guard
+ if (!(tsoaDevice.view()[jt].pt() > 0.))
+ continue;
+ nTracksDevice++;
+ if (useQualityCut_ && qualityDevice[jt] < minQuality_)
+ continue;
+ nLooseAndAboveTracksDevice++;
+ looseTrkidxDevice.emplace_back(jt);
+ }
+
+ //Now loop over Host tracks//nested loop for loose gPU tracks
+ for (int32_t it = 0; it < maxTracksHost; ++it) {
+ int nHitsHost = helper::nHits(tsoaHost.view(), it);
+
+ if (nHitsHost == 0)
+ break; // this is a guard
+
+ float ptHost = tsoaHost.view()[it].pt();
+ float etaHost = tsoaHost.view()[it].eta();
+ float phiHost = helper::phi(tsoaHost.view(), it);
+ float zipHost = helper::zip(tsoaHost.view(), it);
+ float tipHost = helper::tip(tsoaHost.view(), it);
+
+ if (!(ptHost > 0.))
+ continue;
+ nTracksHost++;
+ if (useQualityCut_ && qualityHost[it] < minQuality_)
+ continue;
+ nLooseAndAboveTracksHost++;
+ //Now loop over loose Device trk and find the closest in DeltaR//do we need pt cut?
+ const int32_t notFound = -1;
+ int32_t closestTkidx = notFound;
+ float mindr2 = dr2cut_;
+
+ for (auto gid : looseTrkidxDevice) {
+ float etaDevice = tsoaDevice.view()[gid].eta();
+ float phiDevice = helper::phi(tsoaDevice.view(), gid);
+ float dr2 = reco::deltaR2(etaHost, phiHost, etaDevice, phiDevice);
+ if (dr2 > dr2cut_)
+ continue; // this is arbitrary
+ if (mindr2 > dr2) {
+ mindr2 = dr2;
+ closestTkidx = gid;
+ }
+ }
+
+ hpt_eta_tkAllHost_->Fill(etaHost, ptHost); //all Host tk
+ hphi_z_tkAllHost_->Fill(phiHost, zipHost);
+ if (closestTkidx == notFound)
+ continue;
+ nLooseAndAboveTracksHost_matchedDevice++;
+
+ hchi2_->Fill(tsoaHost.view()[it].chi2(), tsoaDevice.view()[closestTkidx].chi2());
+ hCharge_->Fill(reco::charge(tsoaHost.view(), it), reco::charge(tsoaDevice.view(), closestTkidx));
+ hnHits_->Fill(helper::nHits(tsoaHost.view(), it), helper::nHits(tsoaDevice.view(), closestTkidx));
+ hnLayers_->Fill(tsoaHost.view()[it].nLayers(), tsoaDevice.view()[closestTkidx].nLayers());
+ hpt_->Fill(tsoaHost.view()[it].pt(), tsoaDevice.view()[closestTkidx].pt());
+ hptLogLog_->Fill(tsoaHost.view()[it].pt(), tsoaDevice.view()[closestTkidx].pt());
+ heta_->Fill(etaHost, tsoaDevice.view()[closestTkidx].eta());
+ hphi_->Fill(phiHost, helper::phi(tsoaDevice.view(), closestTkidx));
+ hz_->Fill(zipHost, helper::zip(tsoaDevice.view(), closestTkidx));
+ htip_->Fill(tipHost, helper::tip(tsoaDevice.view(), closestTkidx));
+ hptdiffMatched_->Fill(ptHost - tsoaDevice.view()[closestTkidx].pt());
+ hCurvdiffMatched_->Fill((reco::charge(tsoaHost.view(), it) / tsoaHost.view()[it].pt()) -
+ (reco::charge(tsoaDevice.view(), closestTkidx) / tsoaDevice.view()[closestTkidx].pt()));
+ hetadiffMatched_->Fill(etaHost - tsoaDevice.view()[closestTkidx].eta());
+ hphidiffMatched_->Fill(reco::deltaPhi(phiHost, helper::phi(tsoaDevice.view(), closestTkidx)));
+ hzdiffMatched_->Fill(zipHost - helper::zip(tsoaDevice.view(), closestTkidx));
+ htipdiffMatched_->Fill(tipHost - helper::tip(tsoaDevice.view(), closestTkidx));
+ hpt_eta_tkAllHostMatched_->Fill(etaHost, tsoaHost.view()[it].pt()); //matched to gpu
+ hphi_z_tkAllHostMatched_->Fill(etaHost, zipHost);
+ }
+ hnTracks_->Fill(nTracksHost, nTracksDevice);
+ hnLooseAndAboveTracks_->Fill(nLooseAndAboveTracksHost, nLooseAndAboveTracksDevice);
+ hnLooseAndAboveTracks_matched_->Fill(nLooseAndAboveTracksHost, nLooseAndAboveTracksHost_matchedDevice);
+}
+
+//
+// -- Book Histograms
+//
+template
+void SiPixelCompareTrackSoAAlpaka::bookHistograms(DQMStore::IBooker& iBook,
+ edm::Run const& iRun,
+ edm::EventSetup const& iSetup) {
+ iBook.cd();
+ iBook.setCurrentFolder(topFolderName_);
+
+ // clang-format off
+ std::string toRep = "Number of tracks";
+ // FIXME: all the 2D correlation plots are quite heavy in terms of memory consumption, so a as soon as DQM supports THnSparse
+ // these should be moved to a less resource consuming format
+ hnTracks_ = iBook.book2I("nTracks", fmt::format("{} per event; Host; Device",toRep), 501, -0.5, 500.5, 501, -0.5, 500.5);
+ hnLooseAndAboveTracks_ = iBook.book2I("nLooseAndAboveTracks", fmt::format("{} (quality #geq loose) per event; Host; Device",toRep), 501, -0.5, 500.5, 501, -0.5, 500.5);
+ hnLooseAndAboveTracks_matched_ = iBook.book2I("nLooseAndAboveTracks_matched", fmt::format("{} (quality #geq loose) per event; Host; Device",toRep), 501, -0.5, 500.5, 501, -0.5, 500.5);
+
+ toRep = "Number of all RecHits per track (quality #geq loose)";
+ hnHits_ = iBook.book2I("nRecHits", fmt::format("{};Host;Device",toRep), 15, -0.5, 14.5, 15, -0.5, 14.5);
+
+ toRep = "Number of all layers per track (quality #geq loose)";
+ hnLayers_ = iBook.book2I("nLayers", fmt::format("{};Host;Device",toRep), 15, -0.5, 14.5, 15, -0.5, 14.5);
+
+ toRep = "Track (quality #geq loose) #chi^{2}/ndof";
+ hchi2_ = iBook.book2I("nChi2ndof", fmt::format("{};Host;Device",toRep), 40, 0., 20., 40, 0., 20.);
+
+ toRep = "Track (quality #geq loose) charge";
+ hCharge_ = iBook.book2I("charge",fmt::format("{};Host;Device",toRep),3, -1.5, 1.5, 3, -1.5, 1.5);
+
+ hpt_ = iBook.book2I("pt", "Track (quality #geq loose) p_{T} [GeV];Host;Device", 200, 0., 200., 200, 0., 200.);
+ hptLogLog_ = make2DIfLog(iBook, true, true, "ptLogLog", "Track (quality #geq loose) p_{T} [GeV];Host;Device", 200, log10(0.5), log10(200.), 200, log10(0.5), log10(200.));
+ heta_ = iBook.book2I("eta", "Track (quality #geq loose) #eta;Host;Device", 30, -3., 3., 30, -3., 3.);
+ hphi_ = iBook.book2I("phi", "Track (quality #geq loose) #phi;Host;Device", 30, -M_PI, M_PI, 30, -M_PI, M_PI);
+ hz_ = iBook.book2I("z", "Track (quality #geq loose) z [cm];Host;Device", 30, -30., 30., 30, -30., 30.);
+ htip_ = iBook.book2I("tip", "Track (quality #geq loose) TIP [cm];Host;Device", 100, -0.5, 0.5, 100, -0.5, 0.5);
+ //1D difference plots
+ hptdiffMatched_ = iBook.book1D("ptdiffmatched", " p_{T} diff [GeV] between matched tracks; #Delta p_{T} [GeV]", 60, -30., 30.);
+ hCurvdiffMatched_ = iBook.book1D("curvdiffmatched", "q/p_{T} diff [GeV] between matched tracks; #Delta q/p_{T} [GeV]", 60, -30., 30.);
+ hetadiffMatched_ = iBook.book1D("etadiffmatched", " #eta diff between matched tracks; #Delta #eta", 160, -0.04 ,0.04);
+ hphidiffMatched_ = iBook.book1D("phidiffmatched", " #phi diff between matched tracks; #Delta #phi", 160, -0.04 ,0.04);
+ hzdiffMatched_ = iBook.book1D("zdiffmatched", " z diff between matched tracks; #Delta z [cm]", 300, -1.5, 1.5);
+ htipdiffMatched_ = iBook.book1D("tipdiffmatched", " TIP diff between matched tracks; #Delta TIP [cm]", 300, -1.5, 1.5);
+ //2D plots for eff
+ hpt_eta_tkAllHost_ = iBook.book2I("ptetatrkAllHost", "Track (quality #geq loose) on Host; #eta; p_{T} [GeV];", 30, -M_PI, M_PI, 200, 0., 200.);
+ hpt_eta_tkAllHostMatched_ = iBook.book2I("ptetatrkAllHostmatched", "Track (quality #geq loose) on Host matched to Device track; #eta; p_{T} [GeV];", 30, -M_PI, M_PI, 200, 0., 200.);
+
+ hphi_z_tkAllHost_ = iBook.book2I("phiztrkAllHost", "Track (quality #geq loose) on Host; #phi; z [cm];", 30, -M_PI, M_PI, 30, -30., 30.);
+ hphi_z_tkAllHostMatched_ = iBook.book2I("phiztrkAllHostmatched", "Track (quality #geq loose) on Host; #phi; z [cm];", 30, -M_PI, M_PI, 30, -30., 30.);
+
+}
+
+template
+void SiPixelCompareTrackSoAAlpaka::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
+ // monitorpixelTrackSoA
+ edm::ParameterSetDescription desc;
+ desc.add("pixelTrackSrcHost", edm::InputTag("pixelTracksAlpakaSerial"));
+ desc.add("pixelTrackSrcDevice", edm::InputTag("pixelTracksAlpaka"));
+ desc.add("topFolderName", "SiPixelHeterogeneous/PixelTrackCompareDeviceVSHost");
+ desc.add("useQualityCut", true);
+ desc.add("minQuality", "loose");
+ desc.add("deltaR2cut", 0.04);
+ descriptions.addWithDefaultLabel(desc);
+}
+
+using SiPixelPhase1CompareTrackSoAAlpaka = SiPixelCompareTrackSoAAlpaka;
+using SiPixelPhase2CompareTrackSoAAlpaka = SiPixelCompareTrackSoAAlpaka;
+using SiPixelHIonPhase1CompareTrackSoAAlpaka = SiPixelCompareTrackSoAAlpaka;
+
+DEFINE_FWK_MODULE(SiPixelPhase1CompareTrackSoAAlpaka);
+DEFINE_FWK_MODULE(SiPixelPhase2CompareTrackSoAAlpaka);
+DEFINE_FWK_MODULE(SiPixelHIonPhase1CompareTrackSoAAlpaka);
diff --git a/DQM/SiPixelHeterogeneous/plugins/SiPixelCompareVertexSoAAlpaka.cc b/DQM/SiPixelHeterogeneous/plugins/SiPixelCompareVertexSoAAlpaka.cc
new file mode 100644
index 0000000000000..2eea6a980d9c5
--- /dev/null
+++ b/DQM/SiPixelHeterogeneous/plugins/SiPixelCompareVertexSoAAlpaka.cc
@@ -0,0 +1,186 @@
+// -*- C++ -*-
+// Package: SiPixelCompareVertexSoAAlpaka
+// Class: SiPixelCompareVertexSoAAlpaka
+//
+/**\class SiPixelCompareVertexSoAAlpaka SiPixelCompareVertexSoAAlpaka.cc
+*/
+//
+// Author: Suvankar Roy Chowdhury
+//
+#include "FWCore/Framework/interface/Frameworkfwd.h"
+#include "FWCore/Framework/interface/Event.h"
+#include "FWCore/Framework/interface/MakerMacros.h"
+#include "FWCore/MessageLogger/interface/MessageLogger.h"
+#include "FWCore/ParameterSet/interface/ParameterSet.h"
+#include "FWCore/Utilities/interface/InputTag.h"
+#include "DataFormats/Common/interface/Handle.h"
+// DQM Histograming
+#include "DQMServices/Core/interface/MonitorElement.h"
+#include "DQMServices/Core/interface/DQMEDAnalyzer.h"
+#include "DQMServices/Core/interface/DQMStore.h"
+#include "DataFormats/VertexSoA/interface/ZVertexHost.h"
+#include "DataFormats/BeamSpot/interface/BeamSpot.h"
+
+class SiPixelCompareVertexSoAAlpaka : public DQMEDAnalyzer {
+public:
+ using IndToEdm = std::vector;
+ explicit SiPixelCompareVertexSoAAlpaka(const edm::ParameterSet&);
+ ~SiPixelCompareVertexSoAAlpaka() override = default;
+ void bookHistograms(DQMStore::IBooker& ibooker, edm::Run const& iRun, edm::EventSetup const& iSetup) override;
+ void analyze(const edm::Event& iEvent, const edm::EventSetup& iSetup) override;
+ static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
+
+private:
+ const edm::EDGetTokenT tokenSoAVertexHost_;
+ const edm::EDGetTokenT tokenSoAVertexDevice_;
+ const edm::EDGetTokenT tokenBeamSpot_;
+ const std::string topFolderName_;
+ const float dzCut_;
+ MonitorElement* hnVertex_;
+ MonitorElement* hx_;
+ MonitorElement* hy_;
+ MonitorElement* hz_;
+ MonitorElement* hchi2_;
+ MonitorElement* hchi2oNdof_;
+ MonitorElement* hptv2_;
+ MonitorElement* hntrks_;
+ MonitorElement* hxdiff_;
+ MonitorElement* hydiff_;
+ MonitorElement* hzdiff_;
+};
+
+//
+// constructors
+//
+
+// Note tokenSoAVertexDevice_ contains data copied from device to host, hence is a HostCollection
+SiPixelCompareVertexSoAAlpaka::SiPixelCompareVertexSoAAlpaka(const edm::ParameterSet& iConfig)
+ : tokenSoAVertexHost_(consumes(iConfig.getParameter("pixelVertexSrcHost"))),
+ tokenSoAVertexDevice_(consumes(iConfig.getParameter("pixelVertexSrcDevice"))),
+ tokenBeamSpot_(consumes(iConfig.getParameter("beamSpotSrc"))),
+ topFolderName_(iConfig.getParameter("topFolderName")),
+ dzCut_(iConfig.getParameter("dzCut")) {}
+
+//
+// -- Analyze
+//
+void SiPixelCompareVertexSoAAlpaka::analyze(const edm::Event& iEvent, const edm::EventSetup& iSetup) {
+ const auto& vsoaHandleHost = iEvent.getHandle(tokenSoAVertexHost_);
+ const auto& vsoaHandleDevice = iEvent.getHandle(tokenSoAVertexDevice_);
+ if (not vsoaHandleHost or not vsoaHandleDevice) {
+ edm::LogWarning out("SiPixelCompareVertexSoAAlpaka");
+ if (not vsoaHandleHost) {
+ out << "reference (cpu) tracks not found; ";
+ }
+ if (not vsoaHandleDevice) {
+ out << "target (gpu) tracks not found; ";
+ }
+ out << "the comparison will not run.";
+ return;
+ }
+
+ auto const& vsoaHost = *vsoaHandleHost;
+ int nVerticesHost = vsoaHost.view().nvFinal();
+ auto const& vsoaDevice = *vsoaHandleDevice;
+ int nVerticesDevice = vsoaDevice.view().nvFinal();
+
+ auto bsHandle = iEvent.getHandle(tokenBeamSpot_);
+ float x0 = 0., y0 = 0., z0 = 0., dxdz = 0., dydz = 0.;
+ if (!bsHandle.isValid()) {
+ edm::LogWarning("SiPixelCompareVertexSoAAlpaka") << "No beamspot found. returning vertexes with (0,0,Z) ";
+ } else {
+ const reco::BeamSpot& bs = *bsHandle;
+ x0 = bs.x0();
+ y0 = bs.y0();
+ z0 = bs.z0();
+ dxdz = bs.dxdz();
+ dydz = bs.dydz();
+ }
+
+ for (int ivc = 0; ivc < nVerticesHost; ivc++) {
+ auto sic = vsoaHost.view()[ivc].sortInd();
+ auto zc = vsoaHost.view()[sic].zv();
+ auto xc = x0 + dxdz * zc;
+ auto yc = y0 + dydz * zc;
+ zc += z0;
+
+ auto ndofHost = vsoaHost.view()[sic].ndof();
+ auto chi2Host = vsoaHost.view()[sic].chi2();
+
+ const int32_t notFound = -1;
+ int32_t closestVtxidx = notFound;
+ float mindz = dzCut_;
+
+ for (int ivg = 0; ivg < nVerticesDevice; ivg++) {
+ auto sig = vsoaDevice.view()[ivg].sortInd();
+ auto zgc = vsoaDevice.view()[sig].zv() + z0;
+ auto zDist = std::abs(zc - zgc);
+ //insert some matching condition
+ if (zDist > dzCut_)
+ continue;
+ if (mindz > zDist) {
+ mindz = zDist;
+ closestVtxidx = sig;
+ }
+ }
+ if (closestVtxidx == notFound)
+ continue;
+
+ auto zg = vsoaDevice.view()[closestVtxidx].zv();
+ auto xg = x0 + dxdz * zg;
+ auto yg = y0 + dydz * zg;
+ zg += z0;
+ auto ndofDevice = vsoaDevice.view()[closestVtxidx].ndof();
+ auto chi2Device = vsoaDevice.view()[closestVtxidx].chi2();
+
+ hx_->Fill(xc - x0, xg - x0);
+ hy_->Fill(yc - y0, yg - y0);
+ hz_->Fill(zc, zg);
+ hxdiff_->Fill(xc - xg);
+ hydiff_->Fill(yc - yg);
+ hzdiff_->Fill(zc - zg);
+ hchi2_->Fill(chi2Host, chi2Device);
+ hchi2oNdof_->Fill(chi2Host / ndofHost, chi2Device / ndofDevice);
+ hptv2_->Fill(vsoaHost.view()[sic].ptv2(), vsoaDevice.view()[closestVtxidx].ptv2());
+ hntrks_->Fill(ndofHost + 1, ndofDevice + 1);
+ }
+ hnVertex_->Fill(nVerticesHost, nVerticesDevice);
+}
+
+//
+// -- Book Histograms
+//
+void SiPixelCompareVertexSoAAlpaka::bookHistograms(DQMStore::IBooker& ibooker,
+ edm::Run const& iRun,
+ edm::EventSetup const& iSetup) {
+ ibooker.cd();
+ ibooker.setCurrentFolder(topFolderName_);
+
+ // FIXME: all the 2D correlation plots are quite heavy in terms of memory consumption, so a as soon as DQM supports either TH2I or THnSparse
+ // these should be moved to a less resource consuming format
+ hnVertex_ = ibooker.book2I("nVertex", "# of Vertices;Host;Device", 101, -0.5, 100.5, 101, -0.5, 100.5);
+ hx_ = ibooker.book2I("vx", "Vertez x - Beamspot x;Host;Device", 50, -0.1, 0.1, 50, -0.1, 0.1);
+ hy_ = ibooker.book2I("vy", "Vertez y - Beamspot y;Host;Device", 50, -0.1, 0.1, 50, -0.1, 0.1);
+ hz_ = ibooker.book2I("vz", "Vertez z;Host;Device", 30, -30., 30., 30, -30., 30.);
+ hchi2_ = ibooker.book2I("chi2", "Vertex chi-squared;Host;Device", 40, 0., 20., 40, 0., 20.);
+ hchi2oNdof_ = ibooker.book2I("chi2oNdof", "Vertex chi-squared/Ndof;Host;Device", 40, 0., 20., 40, 0., 20.);
+ hptv2_ = ibooker.book2I("ptsq", "Vertex #sum (p_{T})^{2};Host;Device", 200, 0., 200., 200, 0., 200.);
+ hntrks_ = ibooker.book2I("ntrk", "#tracks associated;Host;Device", 100, -0.5, 99.5, 100, -0.5, 99.5);
+ hntrks_ = ibooker.book2I("ntrk", "#tracks associated;Host;Device", 100, -0.5, 99.5, 100, -0.5, 99.5);
+ hxdiff_ = ibooker.book1D("vxdiff", ";Vertex x difference (Host - Device);#entries", 100, -0.001, 0.001);
+ hydiff_ = ibooker.book1D("vydiff", ";Vertex y difference (Host - Device);#entries", 100, -0.001, 0.001);
+ hzdiff_ = ibooker.book1D("vzdiff", ";Vertex z difference (Host - Device);#entries", 100, -2.5, 2.5);
+}
+
+void SiPixelCompareVertexSoAAlpaka::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
+ // monitorpixelVertexSoA
+ edm::ParameterSetDescription desc;
+ desc.add("pixelVertexSrcHost", edm::InputTag("pixelVerticesAlpakaSerial"));
+ desc.add("pixelVertexSrcDevice", edm::InputTag("pixelVerticesAlpaka"));
+ desc.add("beamSpotSrc", edm::InputTag("offlineBeamSpot"));
+ desc.add("topFolderName", "SiPixelHeterogeneous/PixelVertexCompareSoADeviceVSHost");
+ desc.add("dzCut", 1.);
+ descriptions.addWithDefaultLabel(desc);
+}
+
+DEFINE_FWK_MODULE(SiPixelCompareVertexSoAAlpaka);
diff --git a/DQM/SiPixelHeterogeneous/plugins/SiPixelMonitorRecHitsSoAAlpaka.cc b/DQM/SiPixelHeterogeneous/plugins/SiPixelMonitorRecHitsSoAAlpaka.cc
new file mode 100644
index 0000000000000..f4c8968fafb16
--- /dev/null
+++ b/DQM/SiPixelHeterogeneous/plugins/SiPixelMonitorRecHitsSoAAlpaka.cc
@@ -0,0 +1,198 @@
+#include "DQMServices/Core/interface/MonitorElement.h"
+#include "DQMServices/Core/interface/DQMEDAnalyzer.h"
+#include "DQMServices/Core/interface/DQMStore.h"
+#include "DataFormats/Math/interface/approx_atan2.h"
+#include "DataFormats/SiPixelDetId/interface/PixelSubdetector.h"
+#include "DataFormats/TrackerCommon/interface/TrackerTopology.h"
+#include "DataFormats/TrackingRecHitSoA/interface/TrackingRecHitsHost.h"
+#include "FWCore/Framework/interface/Event.h"
+#include "FWCore/Framework/interface/Frameworkfwd.h"
+#include "FWCore/MessageLogger/interface/MessageLogger.h"
+#include "FWCore/ParameterSet/interface/ParameterSet.h"
+#include "FWCore/ParameterSet/interface/ParameterSetDescription.h"
+#include "FWCore/ParameterSet/interface/ConfigurationDescriptions.h"
+#include "Geometry/CommonDetUnit/interface/PixelGeomDetUnit.h"
+#include "Geometry/CommonTopologies/interface/PixelTopology.h"
+#include "Geometry/Records/interface/TrackerDigiGeometryRecord.h"
+#include "Geometry/TrackerGeometryBuilder/interface/TrackerGeometry.h"
+
+template
+class SiPixelMonitorRecHitsSoAAlpaka : public DQMEDAnalyzer {
+public:
+ using HitsOnHost = TrackingRecHitHost;
+
+ explicit SiPixelMonitorRecHitsSoAAlpaka(const edm::ParameterSet&);
+ ~SiPixelMonitorRecHitsSoAAlpaka() override = default;
+ void dqmBeginRun(const edm::Run&, const edm::EventSetup&) override;
+ void bookHistograms(DQMStore::IBooker& ibooker, edm::Run const& iRun, edm::EventSetup const& iSetup) override;
+ void analyze(const edm::Event& iEvent, const edm::EventSetup& iSetup) override;
+ static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
+
+private:
+ const edm::ESGetToken geomToken_;
+ const edm::ESGetToken topoToken_;
+ const edm::EDGetTokenT tokenSoAHits_;
+ const std::string topFolderName_;
+ const TrackerGeometry* tkGeom_ = nullptr;
+ const TrackerTopology* tTopo_ = nullptr;
+ MonitorElement* hnHits;
+ MonitorElement* hBFposZP;
+ MonitorElement* hBFposZR;
+ MonitorElement* hBposXY;
+ MonitorElement* hBposZP;
+ MonitorElement* hBcharge;
+ MonitorElement* hBsizex;
+ MonitorElement* hBsizey;
+ MonitorElement* hBposZPL[4]; // max 4 barrel hits
+ MonitorElement* hBchargeL[4];
+ MonitorElement* hBsizexL[4];
+ MonitorElement* hBsizeyL[4];
+ MonitorElement* hFposXY;
+ MonitorElement* hFposZP;
+ MonitorElement* hFcharge;
+ MonitorElement* hFsizex;
+ MonitorElement* hFsizey;
+ MonitorElement* hFposXYD[2][12]; // max 12 endcap disks
+ MonitorElement* hFchargeD[2][12];
+ MonitorElement* hFsizexD[2][12];
+ MonitorElement* hFsizeyD[2][12];
+};
+
+//
+// constructors
+//
+template
+SiPixelMonitorRecHitsSoAAlpaka::SiPixelMonitorRecHitsSoAAlpaka(const edm::ParameterSet& iConfig)
+ : geomToken_(esConsumes()),
+ topoToken_(esConsumes()),
+ tokenSoAHits_(consumes(iConfig.getParameter("pixelHitsSrc"))),
+ topFolderName_(iConfig.getParameter("TopFolderName")) {}
+
+//
+// Begin Run
+//
+template
+void SiPixelMonitorRecHitsSoAAlpaka::dqmBeginRun(const edm::Run& iRun, const edm::EventSetup& iSetup) {
+ tkGeom_ = &iSetup.getData(geomToken_);
+ tTopo_ = &iSetup.getData(topoToken_);
+}
+
+//
+// -- Analyze
+//
+template
+void SiPixelMonitorRecHitsSoAAlpaka::analyze(const edm::Event& iEvent, const edm::EventSetup& iSetup) {
+ const auto& rhsoaHandle = iEvent.getHandle(tokenSoAHits_);
+ if (!rhsoaHandle.isValid()) {
+ edm::LogWarning("SiPixelMonitorRecHitsSoAAlpaka") << "No RecHits SoA found \n returning!";
+ return;
+ }
+ auto const& rhsoa = *rhsoaHandle;
+ auto const& soa2d = rhsoa.const_view();
+
+ uint32_t nHits_ = soa2d.metadata().size();
+ hnHits->Fill(nHits_);
+ auto detIds = tkGeom_->detUnitIds();
+ for (uint32_t i = 0; i < nHits_; i++) {
+ DetId id = detIds[soa2d[i].detectorIndex()];
+ float xG = soa2d[i].xGlobal();
+ float yG = soa2d[i].yGlobal();
+ float zG = soa2d[i].zGlobal();
+ float rG = soa2d[i].rGlobal();
+ float fphi = short2phi(soa2d[i].iphi());
+ uint32_t charge = soa2d[i].chargeAndStatus().charge;
+ int16_t sizeX = std::ceil(float(std::abs(soa2d[i].clusterSizeX()) / 8.));
+ int16_t sizeY = std::ceil(float(std::abs(soa2d[i].clusterSizeY()) / 8.));
+ hBFposZP->Fill(zG, fphi);
+ int16_t ysign = yG >= 0 ? 1 : -1;
+ hBFposZR->Fill(zG, rG * ysign);
+ switch (id.subdetId()) {
+ case PixelSubdetector::PixelBarrel:
+ hBposXY->Fill(xG, yG);
+ hBposZP->Fill(zG, fphi);
+ hBcharge->Fill(charge);
+ hBsizex->Fill(sizeX);
+ hBsizey->Fill(sizeY);
+ hBposZPL[tTopo_->pxbLayer(id) - 1]->Fill(zG, fphi);
+ hBchargeL[tTopo_->pxbLayer(id) - 1]->Fill(charge);
+ hBsizexL[tTopo_->pxbLayer(id) - 1]->Fill(sizeX);
+ hBsizeyL[tTopo_->pxbLayer(id) - 1]->Fill(sizeY);
+ break;
+ case PixelSubdetector::PixelEndcap:
+ hFposXY->Fill(xG, yG);
+ hFposZP->Fill(zG, fphi);
+ hFcharge->Fill(charge);
+ hFsizex->Fill(sizeX);
+ hFsizey->Fill(sizeY);
+ hFposXYD[tTopo_->pxfSide(id) - 1][tTopo_->pxfDisk(id) - 1]->Fill(xG, yG);
+ hFchargeD[tTopo_->pxfSide(id) - 1][tTopo_->pxfDisk(id) - 1]->Fill(charge);
+ hFsizexD[tTopo_->pxfSide(id) - 1][tTopo_->pxfDisk(id) - 1]->Fill(sizeX);
+ hFsizeyD[tTopo_->pxfSide(id) - 1][tTopo_->pxfDisk(id) - 1]->Fill(sizeY);
+ break;
+ }
+ }
+}
+
+//
+// -- Book Histograms
+//
+template
+void SiPixelMonitorRecHitsSoAAlpaka::bookHistograms(DQMStore::IBooker& iBook,
+ edm::Run const& iRun,
+ edm::EventSetup const& iSetup) {
+ iBook.cd();
+ iBook.setCurrentFolder(topFolderName_);
+
+ // clang-format off
+ //Global
+ hnHits = iBook.book1D("nHits", "RecHits per event;RecHits;#events", 200, 0, 5000);
+ hBFposZP = iBook.book2D("recHitsGlobalPosZP", "RecHits position Global;Z;#phi", 1000, -60, 60, 200,-3.2,3.2);
+ hBFposZR = iBook.book2D("recHitsGlobalPosZR", "RecHits position Global;Z;R", 1000, -60, 60, 200,-20,20);
+ //Barrel
+ hBposXY = iBook.book2D("recHitsBarrelPosXY", "RecHits position Barrel;X;Y", 200, -20, 20, 200,-20,20);
+ hBposZP = iBook.book2D("recHitsBarrelPosZP", "RecHits position Barrel;Z;#phi", 300, -30, 30, 200,-3.2,3.2);
+ hBcharge = iBook.book1D("recHitsBarrelCharge", "RecHits Charge Barrel;Charge;#events", 250, 0, 100000);
+ hBsizex = iBook.book1D("recHitsBarrelSizex", "RecHits SizeX Barrel;SizeX;#events", 50, 0, 50);
+ hBsizey = iBook.book1D("recHitsBarrelSizey", "RecHits SizeY Barrel;SizeY;#events", 50, 0, 50);
+ //Barrel Layer
+ for(unsigned int il=0;ilnumberOfLayers(PixelSubdetector::PixelBarrel);il++){
+ hBposZPL[il] = iBook.book2D(Form("recHitsBLay%dPosZP",il+1), Form("RecHits position Barrel Layer%d;Z;#phi",il+1), 300, -30, 30, 200,-3.2,3.2);
+ hBchargeL[il] = iBook.book1D(Form("recHitsBLay%dCharge",il+1), Form("RecHits Charge Barrel Layer%d;Charge;#events",il+1), 250, 0, 100000);
+ hBsizexL[il] = iBook.book1D(Form("recHitsBLay%dSizex",il+1), Form("RecHits SizeX Barrel Layer%d;SizeX;#events",il+1), 50, 0, 50);
+ hBsizeyL[il] = iBook.book1D(Form("recHitsBLay%dSizey",il+1), Form("RecHits SizeY Barrel Layer%d;SizeY;#events",il+1), 50, 0, 50);
+ }
+ //Endcaps
+ hFposXY = iBook.book2D("recHitsEndcapsPosXY", "RecHits position Endcaps;X;Y", 200, -20, 20, 200,-20, 20);
+ hFposZP = iBook.book2D("recHitsEndcapsPosZP", "RecHits position Endcaps;Z;#phi", 600, -60, 60, 200,-3.2,3.2);
+ hFcharge = iBook.book1D("recHitsEndcapsCharge", "RecHits Charge Endcaps;Charge;#events", 250, 0, 100000);
+ hFsizex = iBook.book1D("recHitsEndcapsSizex", "RecHits SizeX Endcaps;SizeX;#events", 50, 0, 50);
+ hFsizey = iBook.book1D("recHitsEndcapsSizey", "RecHits SizeY Endcaps;SizeY;#events", 50, 0, 50);
+ //Endcaps Disk
+ for(int is=0;is<2;is++){
+ int sign=is==0? -1:1;
+ for(unsigned int id=0;idnumberOfLayers(PixelSubdetector::PixelEndcap);id++){
+ hFposXYD[is][id] = iBook.book2D(Form("recHitsFDisk%+dPosXY",id*sign+sign), Form("RecHits position Endcaps Disk%+d;X;Y",id*sign+sign), 200, -20, 20, 200,-20,20);
+ hFchargeD[is][id] = iBook.book1D(Form("recHitsFDisk%+dCharge",id*sign+sign), Form("RecHits Charge Endcaps Disk%+d;Charge;#events",id*sign+sign), 250, 0, 100000);
+ hFsizexD[is][id] = iBook.book1D(Form("recHitsFDisk%+dSizex",id*sign+sign), Form("RecHits SizeX Endcaps Disk%+d;SizeX;#events",id*sign+sign), 50, 0, 50);
+ hFsizeyD[is][id] = iBook.book1D(Form("recHitsFDisk%+dSizey",id*sign+sign), Form("RecHits SizeY Endcaps Disk%+d;SizeY;#events",id*sign+sign), 50, 0, 50);
+ }
+ }
+}
+
+template
+void SiPixelMonitorRecHitsSoAAlpaka::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
+ // monitorpixelRecHitsSoA
+ edm::ParameterSetDescription desc;
+ desc.add("pixelHitsSrc", edm::InputTag("siPixelRecHitsPreSplittingAlpaka"));
+ desc.add("TopFolderName", "SiPixelHeterogeneous/PixelRecHitsAlpaka");
+ descriptions.addWithDefaultLabel(desc);
+}
+
+using SiPixelPhase1MonitorRecHitsSoAAlpaka = SiPixelMonitorRecHitsSoAAlpaka;
+using SiPixelPhase2MonitorRecHitsSoAAlpaka = SiPixelMonitorRecHitsSoAAlpaka;
+using SiPixelHIonPhase1MonitorRecHitsSoAAlpaka = SiPixelMonitorRecHitsSoAAlpaka;
+
+#include "FWCore/Framework/interface/MakerMacros.h"
+DEFINE_FWK_MODULE(SiPixelPhase1MonitorRecHitsSoAAlpaka);
+DEFINE_FWK_MODULE(SiPixelPhase2MonitorRecHitsSoAAlpaka);
+DEFINE_FWK_MODULE(SiPixelHIonPhase1MonitorRecHitsSoAAlpaka);
diff --git a/DQM/SiPixelHeterogeneous/plugins/SiPixelMonitorTrackSoAAlpaka.cc b/DQM/SiPixelHeterogeneous/plugins/SiPixelMonitorTrackSoAAlpaka.cc
new file mode 100644
index 0000000000000..fd98957ee8492
--- /dev/null
+++ b/DQM/SiPixelHeterogeneous/plugins/SiPixelMonitorTrackSoAAlpaka.cc
@@ -0,0 +1,197 @@
+// -*- C++ -*-
+// Package: SiPixelMonitorTrackSoAAlpaka
+// Class: SiPixelMonitorTrackSoAAlpaka
+//
+/**\class SiPixelMonitorTrackSoAAlpaka SiPixelMonitorTrackSoAAlpaka.cc
+*/
+//
+// Author: Suvankar Roy Chowdhury
+//
+
+// for string manipulations
+#include
+#include "DataFormats/Common/interface/Handle.h"
+#include "FWCore/Framework/interface/ESHandle.h"
+#include "FWCore/Framework/interface/Event.h"
+#include "FWCore/Framework/interface/Frameworkfwd.h"
+#include "FWCore/Framework/interface/MakerMacros.h"
+#include "FWCore/MessageLogger/interface/MessageLogger.h"
+#include "FWCore/ParameterSet/interface/ParameterSet.h"
+#include "FWCore/ServiceRegistry/interface/Service.h"
+#include "FWCore/Utilities/interface/InputTag.h"
+// DQM Histograming
+#include "DQMServices/Core/interface/MonitorElement.h"
+#include "DQMServices/Core/interface/DQMEDAnalyzer.h"
+#include "DQMServices/Core/interface/DQMStore.h"
+#include "DataFormats/TrackSoA/interface/TracksHost.h"
+
+template
+class SiPixelMonitorTrackSoAAlpaka : public DQMEDAnalyzer {
+public:
+ using PixelTrackHeterogeneous = TracksHost;
+ explicit SiPixelMonitorTrackSoAAlpaka(const edm::ParameterSet&);
+ ~SiPixelMonitorTrackSoAAlpaka() override = default;
+ void bookHistograms(DQMStore::IBooker& ibooker, edm::Run const& iRun, edm::EventSetup const& iSetup) override;
+ void analyze(const edm::Event& iEvent, const edm::EventSetup& iSetup) override;
+ static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
+
+private:
+ edm::EDGetTokenT tokenSoATrack_;
+ std::string topFolderName_;
+ bool useQualityCut_;
+ pixelTrack::Quality minQuality_;
+ MonitorElement* hnTracks;
+ MonitorElement* hnLooseAndAboveTracks;
+ MonitorElement* hnHits;
+ MonitorElement* hnHitsVsPhi;
+ MonitorElement* hnHitsVsEta;
+ MonitorElement* hnLayers;
+ MonitorElement* hnLayersVsPhi;
+ MonitorElement* hnLayersVsEta;
+ MonitorElement* hchi2;
+ MonitorElement* hChi2VsPhi;
+ MonitorElement* hChi2VsEta;
+ MonitorElement* hpt;
+ MonitorElement* heta;
+ MonitorElement* hphi;
+ MonitorElement* hz;
+ MonitorElement* htip;
+ MonitorElement* hquality;
+};
+
+//
+// constructors
+//
+
+template
+SiPixelMonitorTrackSoAAlpaka::SiPixelMonitorTrackSoAAlpaka(const edm::ParameterSet& iConfig) {
+ tokenSoATrack_ = consumes(iConfig.getParameter("pixelTrackSrc"));
+ topFolderName_ = iConfig.getParameter("topFolderName"); //"SiPixelHeterogeneous/PixelTrackSoA";
+ useQualityCut_ = iConfig.getParameter("useQualityCut");
+ minQuality_ = pixelTrack::qualityByName(iConfig.getParameter("minQuality"));
+}
+
+//
+// -- Analyze
+//
+template
+void SiPixelMonitorTrackSoAAlpaka::analyze(const edm::Event& iEvent, const edm::EventSetup& iSetup) {
+ const auto& tsoaHandle = iEvent.getHandle(tokenSoATrack_);
+ if (!tsoaHandle.isValid()) {
+ edm::LogWarning("SiPixelMonitorTrackSoAAlpaka") << "No Track SoA found \n returning!" << std::endl;
+ return;
+ }
+
+ auto const& tsoa = *tsoaHandle.product();
+ auto maxTracks = tsoa.view().metadata().size();
+ auto const* quality = tsoa.view().quality();
+ int32_t nTracks = 0;
+ int32_t nLooseAndAboveTracks = 0;
+
+ for (int32_t it = 0; it < maxTracks; ++it) {
+ auto nHits = tsoa.view().detIndices().size(it);
+ auto nLayers = tsoa.view()[it].nLayers();
+ if (nHits == 0)
+ break; // this is a guard
+ float pt = tsoa.view()[it].pt();
+ if (!(pt > 0.))
+ continue;
+
+ // fill the quality for all tracks
+ pixelTrack::Quality qual = quality[it];
+ hquality->Fill(int(qual));
+ nTracks++;
+
+ if (useQualityCut_ && quality[it] < minQuality_)
+ continue;
+
+ // fill parameters only for quality >= loose
+
+ float chi2 = tsoa.view()[it].chi2();
+ float phi = tsoa.view()[it].state()(0); //TODO: put these numbers in enum
+ float zip = tsoa.view()[it].state()(4);
+ float eta = tsoa.view()[it].eta();
+ float tip = tsoa.view()[it].state()(1);
+
+ hchi2->Fill(chi2);
+ hChi2VsPhi->Fill(phi, chi2);
+ hChi2VsEta->Fill(eta, chi2);
+ hnHits->Fill(nHits);
+ hnLayers->Fill(nLayers);
+ hnHitsVsPhi->Fill(phi, nHits);
+ hnHitsVsEta->Fill(eta, nHits);
+ hnLayersVsPhi->Fill(phi, nLayers);
+ hnLayersVsEta->Fill(eta, nLayers);
+ hpt->Fill(pt);
+ heta->Fill(eta);
+ hphi->Fill(phi);
+ hz->Fill(zip);
+ htip->Fill(tip);
+ nLooseAndAboveTracks++;
+ }
+ hnTracks->Fill(nTracks);
+ hnLooseAndAboveTracks->Fill(nLooseAndAboveTracks);
+}
+
+//
+// -- Book Histograms
+//
+template
+void SiPixelMonitorTrackSoAAlpaka::bookHistograms(DQMStore::IBooker& iBook,
+ edm::Run const& iRun,
+ edm::EventSetup const& iSetup) {
+ iBook.cd();
+ iBook.setCurrentFolder(topFolderName_);
+
+ // clang-format off
+std::string toRep = "Number of tracks";
+hnTracks = iBook.book1D("nTracks", fmt::format(";{} per event;#events",toRep), 1001, -0.5, 1000.5);
+hnLooseAndAboveTracks = iBook.book1D("nLooseAndAboveTracks", fmt::format(";{} (quality #geq loose) per event;#events",toRep), 1001, -0.5, 1000.5);
+
+toRep = "Number of all RecHits per track (quality #geq loose)";
+hnHits = iBook.book1D("nRecHits", fmt::format(";{};#tracks",toRep), 15, -0.5, 14.5);
+hnHitsVsPhi = iBook.bookProfile("nHitsPerTrackVsPhi", fmt::format("{} vs track #phi;Track #phi;{}",toRep,toRep), 30, -M_PI, M_PI,0., 15.);
+hnHitsVsEta = iBook.bookProfile("nHitsPerTrackVsEta", fmt::format("{} vs track #eta;Track #eta;{}",toRep,toRep), 30, -3., 3., 0., 15.);
+
+toRep = "Number of all layers per track (quality #geq loose)";
+hnLayers = iBook.book1D("nLayers", fmt::format(";{};#tracks",toRep), 15, -0.5, 14.5);
+hnLayersVsPhi = iBook.bookProfile("nLayersPerTrackVsPhi", fmt::format("{} vs track #phi;Track #phi;{}",toRep,toRep), 30, -M_PI, M_PI,0., 15.);
+hnLayersVsEta = iBook.bookProfile("nLayersPerTrackVsEta", fmt::format("{} vs track #eta;Track #eta;{}",toRep,toRep), 30, -3., 3., 0., 15.);
+
+toRep = "Track (quality #geq loose) #chi^{2}/ndof";
+hchi2 = iBook.book1D("nChi2ndof", fmt::format(";{};#tracks",toRep), 40, 0., 20.);
+hChi2VsPhi = iBook.bookProfile("nChi2ndofVsPhi", fmt::format("{} vs track #phi;Track #phi;{}",toRep,toRep), 30, -M_PI, M_PI, 0., 20.);
+hChi2VsEta = iBook.bookProfile("nChi2ndofVsEta", fmt::format("{} vs track #eta;Track #eta;{}",toRep,toRep), 30, -3., 3., 0., 20.);
+ // clang-format on
+
+ hpt = iBook.book1D("pt", ";Track (quality #geq loose) p_{T} [GeV];#tracks", 200, 0., 200.);
+ heta = iBook.book1D("eta", ";Track (quality #geq loose) #eta;#tracks", 30, -3., 3.);
+ hphi = iBook.book1D("phi", ";Track (quality #geq loose) #phi;#tracks", 30, -M_PI, M_PI);
+ hz = iBook.book1D("z", ";Track (quality #geq loose) z [cm];#tracks", 30, -30., 30.);
+ htip = iBook.book1D("tip", ";Track (quality #geq loose) TIP [cm];#tracks", 100, -0.5, 0.5);
+ hquality = iBook.book1D("quality", ";Track Quality;#tracks", 7, -0.5, 6.5);
+ uint i = 1;
+ for (const auto& q : pixelTrack::qualityName) {
+ hquality->setBinLabel(i, q.data(), 1);
+ i++;
+ }
+}
+
+template
+void SiPixelMonitorTrackSoAAlpaka::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
+ // monitorpixelTrackSoA
+ edm::ParameterSetDescription desc;
+ desc.add("pixelTrackSrc", edm::InputTag("pixelTracksAlpaka"));
+ desc.add("topFolderName", "SiPixelHeterogeneous/PixelTrackAlpaka");
+ desc.add("useQualityCut", true);
+ desc.add("minQuality", "loose");
+ descriptions.addWithDefaultLabel(desc);
+}
+
+using SiPixelPhase1MonitorTrackSoAAlpaka = SiPixelMonitorTrackSoAAlpaka;
+using SiPixelPhase2MonitorTrackSoAAlpaka = SiPixelMonitorTrackSoAAlpaka;
+using SiPixelHIonPhase1MonitorTrackSoAAlpaka = SiPixelMonitorTrackSoAAlpaka;
+
+DEFINE_FWK_MODULE(SiPixelPhase1MonitorTrackSoAAlpaka);
+DEFINE_FWK_MODULE(SiPixelPhase2MonitorTrackSoAAlpaka);
+DEFINE_FWK_MODULE(SiPixelHIonPhase1MonitorTrackSoAAlpaka);
diff --git a/DQM/SiPixelHeterogeneous/plugins/SiPixelMonitorVertexSoAAlpaka.cc b/DQM/SiPixelHeterogeneous/plugins/SiPixelMonitorVertexSoAAlpaka.cc
new file mode 100644
index 0000000000000..d3121f77bccb8
--- /dev/null
+++ b/DQM/SiPixelHeterogeneous/plugins/SiPixelMonitorVertexSoAAlpaka.cc
@@ -0,0 +1,131 @@
+// -*- C++ -*-
+///bookLayer
+// Package: SiPixelMonitorVertexSoAAlpaka
+// Class: SiPixelMonitorVertexSoAAlpaka
+//
+/**\class SiPixelMonitorVertexSoAAlpaka SiPixelMonitorVertexSoAAlpaka.cc
+*/
+//
+// Author: Suvankar Roy Chowdhury
+//
+#include "FWCore/Framework/interface/Frameworkfwd.h"
+#include "FWCore/Framework/interface/Event.h"
+#include "FWCore/Framework/interface/ESHandle.h"
+#include "FWCore/Framework/interface/MakerMacros.h"
+#include "FWCore/MessageLogger/interface/MessageLogger.h"
+#include "FWCore/ParameterSet/interface/ParameterSet.h"
+#include "FWCore/ServiceRegistry/interface/Service.h"
+#include "FWCore/Utilities/interface/InputTag.h"
+#include "DataFormats/Common/interface/Handle.h"
+// DQM Histograming
+#include "DQMServices/Core/interface/MonitorElement.h"
+#include "DQMServices/Core/interface/DQMEDAnalyzer.h"
+#include "DQMServices/Core/interface/DQMStore.h"
+#include "DataFormats/VertexSoA/interface/ZVertexHost.h"
+#include "DataFormats/BeamSpot/interface/BeamSpot.h"
+
+class SiPixelMonitorVertexSoAAlpaka : public DQMEDAnalyzer {
+public:
+ using IndToEdm = std::vector;
+ explicit SiPixelMonitorVertexSoAAlpaka(const edm::ParameterSet&);
+ ~SiPixelMonitorVertexSoAAlpaka() override = default;
+ void bookHistograms(DQMStore::IBooker& ibooker, edm::Run const& iRun, edm::EventSetup const& iSetup) override;
+ void analyze(const edm::Event& iEvent, const edm::EventSetup& iSetup) override;
+ static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
+
+private:
+ const edm::EDGetTokenT tokenSoAVertex_;
+ const edm::EDGetTokenT tokenBeamSpot_;
+ std::string topFolderName_;
+ MonitorElement* hnVertex;
+ MonitorElement* hx;
+ MonitorElement* hy;
+ MonitorElement* hz;
+ MonitorElement* hchi2;
+ MonitorElement* hchi2oNdof;
+ MonitorElement* hptv2;
+ MonitorElement* hntrks;
+};
+
+//
+// constructors
+//
+
+SiPixelMonitorVertexSoAAlpaka::SiPixelMonitorVertexSoAAlpaka(const edm::ParameterSet& iConfig)
+ : tokenSoAVertex_(consumes(iConfig.getParameter("pixelVertexSrc"))),
+ tokenBeamSpot_(consumes(iConfig.getParameter("beamSpotSrc"))),
+ topFolderName_(iConfig.getParameter("topFolderName")) {}
+
+//
+// -- Analyze
+//
+void SiPixelMonitorVertexSoAAlpaka::analyze(const edm::Event& iEvent, const edm::EventSetup& iSetup) {
+ const auto& vsoaHandle = iEvent.getHandle(tokenSoAVertex_);
+ if (!vsoaHandle.isValid()) {
+ edm::LogWarning("SiPixelMonitorVertexSoAAlpaka") << "No Vertex SoA found \n returning!" << std::endl;
+ return;
+ }
+
+ auto const& vsoa = *vsoaHandle;
+ int nVertices = vsoa.view().nvFinal();
+ auto bsHandle = iEvent.getHandle(tokenBeamSpot_);
+ float x0 = 0., y0 = 0., z0 = 0., dxdz = 0., dydz = 0.;
+ if (!bsHandle.isValid()) {
+ edm::LogWarning("SiPixelMonitorVertexSoAAlpaka") << "No beamspot found. returning vertexes with (0,0,Z) ";
+ } else {
+ const reco::BeamSpot& bs = *bsHandle;
+ x0 = bs.x0();
+ y0 = bs.y0();
+ z0 = bs.z0();
+ dxdz = bs.dxdz();
+ dydz = bs.dydz();
+ }
+
+ for (int iv = 0; iv < nVertices; iv++) {
+ auto si = vsoa.view()[iv].sortInd();
+ auto z = vsoa.view()[si].zv();
+ auto x = x0 + dxdz * z;
+ auto y = y0 + dydz * z;
+
+ z += z0;
+ hx->Fill(x);
+ hy->Fill(y);
+ hz->Fill(z);
+ auto ndof = vsoa.view()[si].ndof();
+ hchi2->Fill(vsoa.view()[si].chi2());
+ hchi2oNdof->Fill(vsoa.view()[si].chi2() / ndof);
+ hptv2->Fill(vsoa.view()[si].ptv2());
+ hntrks->Fill(ndof + 1);
+ }
+ hnVertex->Fill(nVertices);
+}
+
+//
+// -- Book Histograms
+//
+void SiPixelMonitorVertexSoAAlpaka::bookHistograms(DQMStore::IBooker& ibooker,
+ edm::Run const& iRun,
+ edm::EventSetup const& iSetup) {
+ //std::string top_folder = ""//
+ ibooker.cd();
+ ibooker.setCurrentFolder(topFolderName_);
+ hnVertex = ibooker.book1D("nVertex", ";# of Vertices;#entries", 101, -0.5, 100.5);
+ hx = ibooker.book1D("vx", ";Vertex x;#entries", 10, -5., 5.);
+ hy = ibooker.book1D("vy", ";Vertex y;#entries", 10, -5., 5.);
+ hz = ibooker.book1D("vz", ";Vertex z;#entries", 30, -30., 30);
+ hchi2 = ibooker.book1D("chi2", ";Vertex chi-squared;#entries", 40, 0., 20.);
+ hchi2oNdof = ibooker.book1D("chi2oNdof", ";Vertex chi-squared/Ndof;#entries", 40, 0., 20.);
+ hptv2 = ibooker.book1D("ptsq", ";Vertex #sum (p_{T})^{2};#entries", 200, 0., 200.);
+ hntrks = ibooker.book1D("ntrk", ";#tracks associated;#entries", 100, -0.5, 99.5);
+}
+
+void SiPixelMonitorVertexSoAAlpaka::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
+ // monitorpixelVertexSoA
+ edm::ParameterSetDescription desc;
+ desc.add("pixelVertexSrc", edm::InputTag("pixelVerticesAlpaka"));
+ desc.add("beamSpotSrc", edm::InputTag("offlineBeamSpot"));
+ desc.add("topFolderName", "SiPixelHeterogeneous/PixelVertexAlpaka");
+ descriptions.addWithDefaultLabel(desc);
+}
+
+DEFINE_FWK_MODULE(SiPixelMonitorVertexSoAAlpaka);
diff --git a/DQM/SiPixelHeterogeneous/python/SiPixelHeterogenousDQM_FirstStep_cff.py b/DQM/SiPixelHeterogeneous/python/SiPixelHeterogenousDQM_FirstStep_cff.py
index dfb83708c95cf..95245a3fea968 100644
--- a/DQM/SiPixelHeterogeneous/python/SiPixelHeterogenousDQM_FirstStep_cff.py
+++ b/DQM/SiPixelHeterogeneous/python/SiPixelHeterogenousDQM_FirstStep_cff.py
@@ -7,20 +7,35 @@
from DQM.SiPixelHeterogeneous.siPixelPhase2MonitorTrackSoA_cfi import *
from DQM.SiPixelHeterogeneous.siPixelHIonPhase1MonitorTrackSoA_cfi import *
from DQM.SiPixelHeterogeneous.siPixelMonitorVertexSoA_cfi import *
+# Alpaka Modules
+from Configuration.ProcessModifiers.alpaka_cff import alpaka
+from DQM.SiPixelHeterogeneous.siPixelPhase1MonitorRecHitsSoAAlpaka_cfi import *
+from DQM.SiPixelHeterogeneous.siPixelPhase2MonitorRecHitsSoAAlpaka_cfi import *
+from DQM.SiPixelHeterogeneous.siPixelHIonPhase1MonitorRecHitsSoAAlpaka_cfi import *
+from DQM.SiPixelHeterogeneous.siPixelPhase1MonitorTrackSoAAlpaka_cfi import *
+from DQM.SiPixelHeterogeneous.siPixelPhase2MonitorTrackSoAAlpaka_cfi import *
+from DQM.SiPixelHeterogeneous.siPixelHIonPhase1MonitorTrackSoAAlpaka_cfi import *
+from DQM.SiPixelHeterogeneous.siPixelMonitorVertexSoAAlpaka_cfi import *
# Run-3 sequence
monitorpixelSoASource = cms.Sequence(siPixelPhase1MonitorRecHitsSoA * siPixelPhase1MonitorTrackSoA * siPixelMonitorVertexSoA)
-
+# Run-3 Alpaka sequence
+monitorpixelSoASourceAlpaka = cms.Sequence(siPixelPhase1MonitorRecHitsSoAAlpaka * siPixelPhase1MonitorTrackSoAAlpaka * siPixelMonitorVertexSoAAlpaka)
+alpaka.toReplaceWith(monitorpixelSoASource, monitorpixelSoASourceAlpaka)
# Phase-2 sequence
from Configuration.Eras.Modifier_phase2_tracker_cff import phase2_tracker
_monitorpixelSoARecHitsSource = cms.Sequence(siPixelPhase2MonitorRecHitsSoA * siPixelPhase2MonitorTrackSoA * siPixelMonitorVertexSoA)
-phase2_tracker.toReplaceWith(monitorpixelSoASource, _monitorpixelSoARecHitsSource)
+(phase2_tracker & ~alpaka).toReplaceWith(monitorpixelSoASource, _monitorpixelSoARecHitsSource)
+_monitorpixelSoARecHitsSourceAlpaka = cms.Sequence(siPixelPhase2MonitorRecHitsSoAAlpaka * siPixelPhase2MonitorTrackSoAAlpaka * siPixelMonitorVertexSoAAlpaka)
+(phase2_tracker & alpaka).toReplaceWith(monitorpixelSoASource, _monitorpixelSoARecHitsSourceAlpaka)
# HIon Phase 1 sequence
from Configuration.ProcessModifiers.pp_on_AA_cff import pp_on_AA
_monitorpixelSoARecHitsSourceHIon = cms.Sequence(siPixelHIonPhase1MonitorRecHitsSoA * siPixelHIonPhase1MonitorTrackSoA * siPixelMonitorVertexSoA)
(pp_on_AA & ~phase2_tracker).toReplaceWith(monitorpixelSoASource, _monitorpixelSoARecHitsSourceHIon)
+_monitorpixelSoARecHitsSourceHIonAlpaka = cms.Sequence(siPixelHIonPhase1MonitorRecHitsSoAAlpaka * siPixelHIonPhase1MonitorTrackSoAAlpaka * siPixelMonitorVertexSoAAlpaka)
+(pp_on_AA & ~phase2_tracker & alpaka).toReplaceWith(monitorpixelSoASource, _monitorpixelSoARecHitsSourceHIonAlpaka)
#Define the sequence for GPU vs CPU validation
#This should run:- individual monitor for the 2 collections + comparison module
@@ -33,6 +48,14 @@
from DQM.SiPixelHeterogeneous.siPixelCompareVertexSoA_cfi import *
from DQM.SiPixelHeterogeneous.siPixelPhase1RawDataErrorComparator_cfi import *
from DQM.SiPixelPhase1Common.SiPixelPhase1RawData_cfi import *
+#Alpaka
+from DQM.SiPixelHeterogeneous.siPixelPhase1CompareRecHitsSoAAlpaka_cfi import *
+from DQM.SiPixelHeterogeneous.siPixelPhase2CompareRecHitsSoAAlpaka_cfi import *
+from DQM.SiPixelHeterogeneous.siPixelHIonPhase1CompareRecHitsSoAAlpaka_cfi import *
+from DQM.SiPixelHeterogeneous.siPixelPhase1CompareTrackSoAAlpaka_cfi import *
+from DQM.SiPixelHeterogeneous.siPixelPhase2CompareTrackSoAAlpaka_cfi import *
+from DQM.SiPixelHeterogeneous.siPixelHIonPhase1CompareTrackSoAAlpaka_cfi import *
+from DQM.SiPixelHeterogeneous.siPixelCompareVertexSoAAlpaka_cfi import *
# digi errors
SiPixelPhase1RawDataConfForCPU = copy.deepcopy(SiPixelPhase1RawDataConf)
@@ -126,6 +149,43 @@
topFolderName = 'SiPixelHeterogeneous/PixelVertexSoAGPU',
)
+### Alpaka
+
+# PixelRecHits: monitor of CPUSerial product (Alpaka backend: 'serial_sync')
+siPixelRecHitsSoAMonitorSerial = siPixelPhase1MonitorRecHitsSoAAlpaka.clone(
+ pixelHitsSrc = cms.InputTag( 'siPixelRecHitsPreSplittingAlpakaSerial' ),
+ TopFolderName = cms.string( 'SiPixelHeterogeneous/PixelRecHitsSerial' )
+)
+
+# PixelRecHits: monitor of Device product (Alpaka backend: '')
+siPixelRecHitsSoAMonitorDevice = siPixelPhase1MonitorRecHitsSoAAlpaka.clone(
+ pixelHitsSrc = cms.InputTag( 'siPixelRecHitsPreSplittingAlpaka' ),
+ TopFolderName = cms.string( 'SiPixelHeterogeneous/PixelRecHitsDevice' )
+)
+
+# PixelTracks: monitor of CPUSerial product (Alpaka backend: 'serial_sync')
+siPixelTrackSoAMonitorSerial = siPixelPhase1MonitorTrackSoAAlpaka.clone(
+ pixelTrackSrc = cms.InputTag('pixelTracksAlpakaSerial'),
+ topFolderName = cms.string('SiPixelHeterogeneous/PixelTrackSerial')
+)
+
+# PixelTracks: monitor of CPUSerial product (Alpaka backend: 'serial_sync')
+siPixelTrackSoAMonitorDevice = siPixelPhase1MonitorTrackSoAAlpaka.clone(
+ pixelTrackSrc = cms.InputTag('pixelTracksAlpaka'),
+ topFolderName = cms.string('SiPixelHeterogeneous/PixelTrackDevice')
+)
+
+# PixelVertices: monitor of CPUSerial product (Alpaka backend: 'serial_sync')
+siPixelVertexSoAMonitorSerial = siPixelMonitorVertexSoAAlpaka.clone(
+ pixelVertexSrc = cms.InputTag("pixelVerticesAlpakaSerial"),
+ topFolderName = cms.string('SiPixelHeterogeneous/PixelVertexSerial')
+)
+
+siPixelVertexSoAMonitorDevice = siPixelMonitorVertexSoAAlpaka.clone(
+ pixelVertexSrc = cms.InputTag("pixelVerticesAlpaka"),
+ topFolderName = cms.string('SiPixelHeterogeneous/PixelVertexDevice')
+)
+
# Run-3 sequence
monitorpixelSoACompareSource = cms.Sequence(siPixelPhase1MonitorRawDataACPU *
siPixelPhase1MonitorRawDataAGPU *
@@ -139,6 +199,17 @@
siPixelMonitorVertexSoAGPU *
siPixelCompareVertexSoA *
siPixelPhase1RawDataErrorComparator)
+# and the Alpaka version
+monitorpixelSoACompareSourceAlpaka = cms.Sequence(
+ siPixelRecHitsSoAMonitorSerial *
+ siPixelRecHitsSoAMonitorDevice *
+ siPixelPhase1CompareRecHitsSoAAlpaka *
+ siPixelTrackSoAMonitorSerial *
+ siPixelTrackSoAMonitorDevice *
+ siPixelPhase1CompareTrackSoAAlpaka *
+ siPixelVertexSoAMonitorSerial *
+ siPixelVertexSoAMonitorDevice *
+ siPixelCompareVertexSoAAlpaka )
# Phase-2 sequence
_monitorpixelSoACompareSource = cms.Sequence(siPixelPhase2MonitorRecHitsSoACPU *
@@ -166,3 +237,6 @@
from Configuration.ProcessModifiers.gpuValidationPixel_cff import gpuValidationPixel
gpuValidationPixel.toReplaceWith(monitorpixelSoASource, monitorpixelSoACompareSource)
+
+from Configuration.ProcessModifiers.alpakaValidationPixel_cff import alpakaValidationPixel
+(alpakaValidationPixel & ~gpuValidationPixel).toReplaceWith(monitorpixelSoASource, monitorpixelSoACompareSourceAlpaka)
diff --git a/DataFormats/TrackSoA/BuildFile.xml b/DataFormats/TrackSoA/BuildFile.xml
new file mode 100644
index 0000000000000..ac764cf5b95ff
--- /dev/null
+++ b/DataFormats/TrackSoA/BuildFile.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/DataFormats/TrackSoA/README.md b/DataFormats/TrackSoA/README.md
new file mode 100644
index 0000000000000..433dfb0d656c7
--- /dev/null
+++ b/DataFormats/TrackSoA/README.md
@@ -0,0 +1,60 @@
+# TrackSoA Data Formats
+
+`DataFormat`s meant to be used on Host (CPU) or Device (GPU) for
+storing information about `TrackSoA`s created during the Pixel-local Reconstruction
+chain. It stores data in an SoA manner.
+
+The host format is inheriting from `DataFormats/Portable/interface/PortableHostCollection.h`,
+while the device format is inheriting from `DataFormats/Portable/interface/PortableDeviceCollection.h`
+
+Both formats use the same SoA Layout (`TrackSoA::Layout`) which is generated
+via the `GENERATE_SOA_LAYOUT` macro in the `TrackDefinitions.h` file.
+
+## Notes
+
+-`hitIndices` and `detIndices`, instances of `HitContainer`, have been added into the
+layout as `SOA_SCALAR`s, meaning that they manage their own data independently from the SoA
+`Layout`. This could be improved in the future, if `HitContainer` (aka a `OneToManyAssoc` of fixed size)
+is replaced, but there don't seem to be any conflicts in including it in the `Layout` like this.
+- Host and Device classes should **not** be created via inheritance, as they're done here,
+but via composition. See [this discussion](https://github.com/cms-sw/cmssw/pull/40465#discussion_r1066039309).
+
+## TracksHost
+
+The version of the data format to be used for storing `TrackSoA` data on the CPU.
+Instances of this class are to be used for:
+
+- Having a place to copy data to host from device, via `Memcpy`, or
+- Running host-side algorithms using data stored in an SoA manner.
+
+## TracksDevice
+
+The version of the data format to be used for storing `TrackSoA` data on the GPU.
+
+Instances of `TracksDevice` are to be created on host and be
+used on device only. To do so, the instance's `view()` method is to be called
+to pass a `View` to any kernel launched. Accessing data from the `view()` is not
+possible on the host side.
+
+## TracksSoACollection
+
+Depending on the Alpaka accelerator back-end enabled, `TrackSoACollection` is an alias to either the Host or Device SoA:
+
+```cpp
+template
+ using TrackSoACollection = std::conditional_t,
+ TrackSoAHost,
+ TrackSoADevice>;
+```
+
+## Utilities
+
+`alpaka/TrackUtilities.h` contains a collection of methods which were originally
+defined as class methods inside either `TrackSoAHeterogeneousT` and `TrajectoryStateSoAT`
+which have been adapted to operate on `View` instances, so that they are callable
+from within `__global__` kernels, on both CPU and CPU.
+
+## Use case
+
+See `test/TrackSoAHeterogeneous_test.cpp` for a simple example of instantiation,
+processing and copying from device to host.
diff --git a/DataFormats/TrackSoA/interface/TrackDefinitions.h b/DataFormats/TrackSoA/interface/TrackDefinitions.h
new file mode 100644
index 0000000000000..6bd36b5bd3cd1
--- /dev/null
+++ b/DataFormats/TrackSoA/interface/TrackDefinitions.h
@@ -0,0 +1,32 @@
+#ifndef DataFormats_Track_interface_TrackDefinitions_h
+#define DataFormats_Track_interface_TrackDefinitions_h
+#include
+#include
+#include
+
+namespace pixelTrack {
+
+ enum class Quality : uint8_t { bad = 0, edup, dup, loose, strict, tight, highPurity, notQuality };
+ constexpr uint32_t qualitySize{uint8_t(Quality::notQuality)};
+ constexpr std::string_view qualityName[qualitySize]{"bad", "edup", "dup", "loose", "strict", "tight", "highPurity"};
+ inline Quality qualityByName(std::string_view name) {
+ auto qp = std::find(qualityName, qualityName + qualitySize, name) - qualityName;
+ auto ret = static_cast(qp);
+
+ if (ret == pixelTrack::Quality::notQuality)
+ throw std::invalid_argument(std::string(name) + " is not a pixelTrack::Quality!");
+
+ return ret;
+ }
+
+#ifdef GPU_SMALL_EVENTS
+ // kept for testing and debugging
+ constexpr uint32_t maxNumber() { return 2 * 1024; }
+#else
+ // tested on MC events with 55-75 pileup events
+ constexpr uint32_t maxNumber() { return 32 * 1024; }
+#endif
+
+} // namespace pixelTrack
+
+#endif
diff --git a/DataFormats/TrackSoA/interface/TracksDevice.h b/DataFormats/TrackSoA/interface/TracksDevice.h
new file mode 100644
index 0000000000000..6ef28014bab63
--- /dev/null
+++ b/DataFormats/TrackSoA/interface/TracksDevice.h
@@ -0,0 +1,38 @@
+#ifndef DataFormats_Track_interface_TracksDevice_h
+#define DataFormats_Track_interface_TracksDevice_h
+
+#include
+#include
+#include "DataFormats/TrackSoA/interface/TracksSoA.h"
+#include "DataFormats/TrackSoA/interface/TrackDefinitions.h"
+#include "DataFormats/Portable/interface/PortableDeviceCollection.h"
+
+// TODO: The class is created via inheritance of the PortableCollection.
+// This is generally discouraged, and should be done via composition.
+// See: https://github.com/cms-sw/cmssw/pull/40465#discussion_r1067364306
+template
+class TracksDevice : public PortableDeviceCollection, TDev> {
+public:
+ static constexpr int32_t S = TrackerTraits::maxNumberOfTuples; //TODO: this could be made configurable at runtime
+ TracksDevice() = default; // necessary for ROOT dictionaries
+
+ using PortableDeviceCollection, TDev>::view;
+ using PortableDeviceCollection, TDev>::const_view;
+ using PortableDeviceCollection, TDev>::buffer;
+
+ // Constructor which specifies the SoA size
+ template
+ explicit TracksDevice(TQueue& queue)
+ : PortableDeviceCollection, TDev>(S, queue) {}
+};
+
+namespace pixelTrack {
+
+ template
+ using TracksDevicePhase1 = TracksDevice;
+ template
+ using TracksDevicePhase2 = TracksDevice;
+
+} // namespace pixelTrack
+
+#endif // DataFormats_Track_TracksDevice_H
diff --git a/DataFormats/TrackSoA/interface/TracksHost.h b/DataFormats/TrackSoA/interface/TracksHost.h
new file mode 100644
index 0000000000000..a8f459eac066c
--- /dev/null
+++ b/DataFormats/TrackSoA/interface/TracksHost.h
@@ -0,0 +1,42 @@
+#ifndef DataFormats_Track_TracksHost_H
+#define DataFormats_Track_TracksHost_H
+
+#include
+#include
+#include "Geometry/CommonTopologies/interface/SimplePixelTopology.h"
+#include "DataFormats/TrackSoA/interface/TracksSoA.h"
+#include "DataFormats/TrackSoA/interface/TrackDefinitions.h"
+#include "DataFormats/Portable/interface/PortableHostCollection.h"
+
+// TODO: The class is created via inheritance of the PortableHostCollection.
+// This is generally discouraged, and should be done via composition.
+// See: https://github.com/cms-sw/cmssw/pull/40465#discussion_r1067364306
+template
+class TracksHost : public PortableHostCollection> {
+public:
+ static constexpr int32_t S = TrackerTraits::maxNumberOfTuples; //TODO: this could be made configurable at runtime
+ TracksHost() = default; // Needed for the dictionary; not sure if line above is needed anymore
+
+ using PortableHostCollection>::view;
+ using PortableHostCollection>::const_view;
+ using PortableHostCollection>::buffer;
+
+ // Constructor which specifies the SoA size
+ template
+ explicit TracksHost(TQueue& queue)
+ : PortableHostCollection>(S, queue) {}
+
+ // Constructor which specifies the DevHost
+ explicit TracksHost(alpaka_common::DevHost const& host)
+ : PortableHostCollection>(S, host) {}
+};
+
+namespace pixelTrack {
+
+ using TracksHostPhase1 = TracksHost;
+ using TracksHostPhase2 = TracksHost;
+ using TracksHostHIonPhase1 = TracksHost;
+
+} // namespace pixelTrack
+
+#endif // DataFormats_Track_TracksHost_H
diff --git a/DataFormats/TrackSoA/interface/TracksSoA.h b/DataFormats/TrackSoA/interface/TracksSoA.h
new file mode 100644
index 0000000000000..bc3a8c4be9cb5
--- /dev/null
+++ b/DataFormats/TrackSoA/interface/TracksSoA.h
@@ -0,0 +1,56 @@
+#ifndef DataFormats_Track_interface_TrackLayout_h
+#define DataFormats_Track_interface_TrackLayout_h
+
+#include
+#include "HeterogeneousCore/AlpakaInterface/interface/OneToManyAssoc.h"
+#include "Geometry/CommonTopologies/interface/SimplePixelTopology.h"
+#include "DataFormats/SoATemplate/interface/SoALayout.h"
+#include "DataFormats/TrackSoA/interface/TrackDefinitions.h"
+
+namespace reco {
+
+ template
+ struct TrackSoA {
+ static constexpr int32_t S = TrackerTraits::maxNumberOfTuples;
+ static constexpr int32_t H = TrackerTraits::avgHitsPerTrack;
+ // Aliases in order to not confuse the GENERATE_SOA_LAYOUT
+ // macro with weird colons and angled brackets.
+ using Vector5f = Eigen::Matrix;
+ using Vector15f = Eigen::Matrix;
+ using Quality = pixelTrack::Quality;
+
+ using hindex_type = uint32_t;
+
+ using HitContainer = cms::alpakatools::OneToManyAssocSequential;
+
+ GENERATE_SOA_LAYOUT(Layout,
+ SOA_COLUMN(Quality, quality),
+ SOA_COLUMN(float, chi2),
+ SOA_COLUMN(int8_t, nLayers),
+ SOA_COLUMN(float, eta),
+ SOA_COLUMN(float, pt),
+ SOA_EIGEN_COLUMN(Vector5f, state),
+ SOA_EIGEN_COLUMN(Vector15f, covariance),
+ SOA_SCALAR(int, nTracks),
+ SOA_SCALAR(HitContainer, hitIndices),
+ SOA_SCALAR(HitContainer, detIndices))
+ };
+
+ template
+ using TrackLayout = typename reco::TrackSoA::template Layout<>;
+ template
+ using TrackSoAView = typename reco::TrackSoA::template Layout<>::View;
+ template
+ using TrackSoAConstView = typename reco::TrackSoA::template Layout<>::ConstView;
+
+ template
+ ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE static constexpr float charge(const TrackSoAConstView &tracks,
+ int32_t i) {
+ //was: std::copysign(1.f, tracks[i].state()(2)). Will be constexpr with C++23
+ float v = tracks[i].state()(2);
+ return float((0.0f < v) - (v < 0.0f));
+ }
+
+} // namespace reco
+
+#endif
diff --git a/DataFormats/TrackSoA/interface/alpaka/TrackUtilities.h b/DataFormats/TrackSoA/interface/alpaka/TrackUtilities.h
new file mode 100644
index 0000000000000..8affb29845779
--- /dev/null
+++ b/DataFormats/TrackSoA/interface/alpaka/TrackUtilities.h
@@ -0,0 +1,197 @@
+#ifndef DataFormats_Track_interface_alpaka_TrackUtilities_h
+#define DataFormats_Track_interface_alpaka_TrackUtilities_h
+
+#include "Geometry/CommonTopologies/interface/SimplePixelTopology.h"
+#include "DataFormats/TrackSoA/interface/TrackDefinitions.h"
+#include "DataFormats/TrackSoA/interface/TracksSoA.h"
+
+// Methods that operate on View and ConstView of the TrackSoA, and cannot be class methods.
+template
+struct TracksUtilities {
+ using TrackSoAView = typename reco::TrackSoA::template Layout<>::View;
+ using TrackSoAConstView = typename reco::TrackSoA::template Layout<>::ConstView;
+ using hindex_type = typename reco::TrackSoA::hindex_type;
+
+ // State at the Beam spot
+ // phi,tip,1/pt,cotan(theta),zip
+ /* ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE static constexpr float charge(const TrackSoAConstView &tracks, int32_t i) {
+ //was: std::copysign(1.f, tracks[i].state()(2)). Will be constexpr with C++23
+ float v = tracks[i].state()(2);
+ return float((0.0f < v) - (v < 0.0f));
+ }
+*/
+ ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE static constexpr float phi(const TrackSoAConstView &tracks, int32_t i) {
+ return tracks[i].state()(0);
+ }
+
+ ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE static constexpr float tip(const TrackSoAConstView &tracks, int32_t i) {
+ return tracks[i].state()(1);
+ }
+
+ ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE static constexpr float zip(const TrackSoAConstView &tracks, int32_t i) {
+ return tracks[i].state()(4);
+ }
+
+ ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE static constexpr bool isTriplet(const TrackSoAConstView &tracks, int i) {
+ return tracks[i].nLayers() == 3;
+ }
+
+ template
+ ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE static constexpr void copyFromCircle(
+ TrackSoAView &tracks, V3 const &cp, M3 const &ccov, V2 const &lp, M2 const &lcov, float b, int32_t i) {
+ tracks[i].state() << cp.template cast(), lp.template cast();
+
+ tracks[i].state()(2) = tracks[i].state()(2) * b;
+ auto cov = tracks[i].covariance();
+ cov(0) = ccov(0, 0);
+ cov(1) = ccov(0, 1);
+ cov(2) = b * float(ccov(0, 2));
+ cov(4) = cov(3) = 0;
+ cov(5) = ccov(1, 1);
+ cov(6) = b * float(ccov(1, 2));
+ cov(8) = cov(7) = 0;
+ cov(9) = b * b * float(ccov(2, 2));
+ cov(11) = cov(10) = 0;
+ cov(12) = lcov(0, 0);
+ cov(13) = lcov(0, 1);
+ cov(14) = lcov(1, 1);
+ }
+
+ template
+ ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE static constexpr void copyFromDense(TrackSoAView &tracks,
+ V5 const &v,
+ M5 const &cov,
+ int32_t i) {
+ tracks[i].state() = v.template cast();
+ for (int j = 0, ind = 0; j < 5; ++j)
+ for (auto k = j; k < 5; ++k)
+ tracks[i].covariance()(ind++) = cov(j, k);
+ }
+
+ template
+ ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE static constexpr void copyToDense(const TrackSoAConstView &tracks,
+ V5 &v,
+ M5 &cov,
+ int32_t i) {
+ v = tracks[i].state().template cast();
+ for (int j = 0, ind = 0; j < 5; ++j) {
+ cov(j, j) = tracks[i].covariance()(ind++);
+ for (auto k = j + 1; k < 5; ++k)
+ cov(k, j) = cov(j, k) = tracks[i].covariance()(ind++);
+ }
+ }
+
+ ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE static constexpr int computeNumberOfLayers(const TrackSoAConstView &tracks,
+ int32_t i) {
+ auto pdet = tracks.detIndices().begin(i);
+ int nl = 1;
+ auto ol = pixelTopology::getLayer(*pdet);
+ for (; pdet < tracks.detIndices().end(i); ++pdet) {
+ auto il = pixelTopology::getLayer(*pdet);
+ if (il != ol)
+ ++nl;
+ ol = il;
+ }
+ return nl;
+ }
+
+ ALPAKA_FN_HOST_ACC ALPAKA_FN_INLINE static constexpr int nHits(const TrackSoAConstView &tracks, int i) {
+ return tracks.detIndices().size(i);
+ }
+};
+
+namespace pixelTrack {
+
+ template
+ struct QualityCutsT {};
+
+ template
+ struct QualityCutsT> {
+ using TrackSoAView = typename reco::TrackSoA::template Layout<>::View;
+ using TrackSoAConstView = typename reco::TrackSoA::template Layout<>::ConstView;
+ using tracksHelper = TracksUtilities;
+ float chi2Coeff[4];
+ float chi2MaxPt; // GeV
+ float chi2Scale;
+
+ struct Region {
+ float maxTip; // cm
+ float minPt; // GeV
+ float maxZip; // cm
+ };
+
+ Region triplet;
+ Region quadruplet;
+
+ ALPAKA_FN_ACC ALPAKA_FN_INLINE bool isHP(const TrackSoAConstView &tracks, int nHits, int it) const {
+ // impose "region cuts" based on the fit results (phi, Tip, pt, cotan(theta)), Zip)
+ // default cuts:
+ // - for triplets: |Tip| < 0.3 cm, pT > 0.5 GeV, |Zip| < 12.0 cm
+ // - for quadruplets: |Tip| < 0.5 cm, pT > 0.3 GeV, |Zip| < 12.0 cm
+ // (see CAHitNtupletGeneratorGPU.cc)
+ auto const ®ion = (nHits > 3) ? quadruplet : triplet;
+ return (std::abs(tracksHelper::tip(tracks, it)) < region.maxTip) and (tracks.pt(it) > region.minPt) and
+ (std::abs(tracksHelper::zip(tracks, it)) < region.maxZip);
+ }
+
+ ALPAKA_FN_ACC ALPAKA_FN_INLINE bool strictCut(const TrackSoAConstView &tracks, int it) const {
+ auto roughLog = [](float x) {
+ // max diff [0.5,12] at 1.25 0.16143
+ // average diff 0.0662998
+ union IF {
+ uint32_t i;
+ float f;
+ };
+ IF z;
+ z.f = x;
+ uint32_t lsb = 1 < 21;
+ z.i += lsb;
+ z.i >>= 21;
+ auto f = z.i & 3;
+ int ex = int(z.i >> 2) - 127;
+
+ // log2(1+0.25*f)
+ // averaged over bins
+ const float frac[4] = {0.160497f, 0.452172f, 0.694562f, 0.901964f};
+ return float(ex) + frac[f];
+ };
+
+ float pt = std::min(tracks.pt(it), chi2MaxPt);
+ float chi2Cut = chi2Scale * (chi2Coeff[0] + roughLog(pt) * chi2Coeff[1]);
+ if (tracks.chi2(it) >= chi2Cut) {
+#ifdef NTUPLE_FIT_DEBUG
+ printf("Bad chi2 %d pt %f eta %f chi2 %f\n", it, tracks.pt(it), tracks.eta(it), tracks.chi2(it));
+#endif
+ return true;
+ }
+ return false;
+ }
+ };
+
+ template
+ struct QualityCutsT> {
+ using TrackSoAView = typename reco::TrackSoA::template Layout<>::View;
+ using TrackSoAConstView = typename reco::TrackSoA::template Layout<>::ConstView;
+ using tracksHelper = TracksUtilities;
+
+ float maxChi2;
+ float minPt;
+ float maxTip;
+ float maxZip;
+
+ ALPAKA_FN_ACC ALPAKA_FN_INLINE bool isHP(const TrackSoAConstView &tracks, int nHits, int it) const {
+ return (std::abs(tracksHelper::tip(tracks, it)) < maxTip) and (tracks.pt(it) > minPt) and
+ (std::abs(tracksHelper::zip(tracks, it)) < maxZip);
+ }
+ ALPAKA_FN_ACC ALPAKA_FN_INLINE bool strictCut(const TrackSoAConstView &tracks, int it) const {
+ return tracks.chi2(it) >= maxChi2;
+ }
+ };
+
+} // namespace pixelTrack
+
+// TODO: Should those be placed in the ALPAKA_ACCELERATOR_NAMESPACE
+template struct TracksUtilities;
+template struct TracksUtilities;
+
+#endif
diff --git a/DataFormats/TrackSoA/interface/alpaka/TracksSoACollection.h b/DataFormats/TrackSoA/interface/alpaka/TracksSoACollection.h
new file mode 100644
index 0000000000000..62e9f69e34636
--- /dev/null
+++ b/DataFormats/TrackSoA/interface/alpaka/TracksSoACollection.h
@@ -0,0 +1,52 @@
+#ifndef DataFormats_Track_interface_alpaka_TracksSoACollection_h
+#define DataFormats_Track_interface_alpaka_TracksSoACollection_h
+
+#include
+#include
+#include "HeterogeneousCore/AlpakaInterface/interface/config.h"
+#include "DataFormats/Portable/interface/alpaka/PortableCollection.h"
+#include "DataFormats/TrackSoA/interface/TracksSoA.h"
+#include "DataFormats/TrackSoA/interface/TrackDefinitions.h"
+#include "DataFormats/TrackSoA/interface/TracksHost.h"
+#include "DataFormats/TrackSoA/interface/TracksDevice.h"
+#include "HeterogeneousCore/AlpakaInterface/interface/CopyToHost.h"
+
+// TODO: The class is created via inheritance of the PortableCollection.
+// This is generally discouraged, and should be done via composition.
+// See: https://github.com/cms-sw/cmssw/pull/40465#discussion_r1067364306
+
+namespace ALPAKA_ACCELERATOR_NAMESPACE {
+
+ template
+ using TracksSoACollection = std::conditional_t,
+ TracksHost,
+ TracksDevice>;
+
+ //Classes definition for Phase1/Phase2/HIonPhase1, to make the classes_def lighter. Not actually used in the code.
+ namespace pixelTrack {
+ using TracksSoACollectionPhase1 = TracksSoACollection;
+ using TracksSoACollectionPhase2 = TracksSoACollection;
+ using TracksSoACollectionHIonPhase1 = TracksSoACollection;
+ } // namespace pixelTrack
+} // namespace ALPAKA_ACCELERATOR_NAMESPACE
+
+namespace cms::alpakatools {
+ template
+ struct CopyToHost> {
+ template
+ static auto copyAsync(TQueue& queue, TracksDevice const& deviceData) {
+ ::TracksHost hostData(queue);
+ alpaka::memcpy(queue, hostData.buffer(), deviceData.buffer());
+#ifdef GPU_DEBUG
+ printf("TracksSoACollection: I'm copying to host.\n");
+#endif
+ return hostData;
+ }
+ };
+} // namespace cms::alpakatools
+
+ASSERT_DEVICE_MATCHES_HOST_COLLECTION(pixelTrack::TracksSoACollectionPhase1, pixelTrack::TracksHostPhase1);
+ASSERT_DEVICE_MATCHES_HOST_COLLECTION(pixelTrack::TracksSoACollectionPhase2, pixelTrack::TracksHostPhase2);
+ASSERT_DEVICE_MATCHES_HOST_COLLECTION(pixelTrack::TracksSoACollectionHIonPhase1, pixelTrack::TracksHostHIonPhase1);
+
+#endif // DataFormats_Track_interface_alpaka_TracksSoACollection_h
diff --git a/DataFormats/TrackSoA/src/alpaka/classes_cuda.h b/DataFormats/TrackSoA/src/alpaka/classes_cuda.h
new file mode 100644
index 0000000000000..4783184611401
--- /dev/null
+++ b/DataFormats/TrackSoA/src/alpaka/classes_cuda.h
@@ -0,0 +1,14 @@
+
+#ifndef DataFormats_TrackSoA_src_alpaka_classes_cuda_h
+#define DataFormats_TrackSoA_src_alpaka_classes_cuda_h
+
+#include "DataFormats/Common/interface/DeviceProduct.h"
+#include "DataFormats/Common/interface/Wrapper.h"
+#include "DataFormats/TrackSoA/interface/TracksSoA.h"
+#include "DataFormats/TrackSoA/interface/alpaka/TracksSoACollection.h"
+#include "DataFormats/TrackSoA/interface/TracksDevice.h"
+#include "HeterogeneousCore/AlpakaInterface/interface/config.h"
+
+using namespace reco;
+
+#endif // DataFormats_TrackSoA_src_alpaka_classes_cuda_h
diff --git a/DataFormats/TrackSoA/src/alpaka/classes_cuda_def.xml b/DataFormats/TrackSoA/src/alpaka/classes_cuda_def.xml
new file mode 100644
index 0000000000000..c04ca173c49f9
--- /dev/null
+++ b/DataFormats/TrackSoA/src/alpaka/classes_cuda_def.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/DataFormats/TrackSoA/src/alpaka/classes_rocm.h b/DataFormats/TrackSoA/src/alpaka/classes_rocm.h
new file mode 100644
index 0000000000000..38143a6058c36
--- /dev/null
+++ b/DataFormats/TrackSoA/src/alpaka/classes_rocm.h
@@ -0,0 +1,14 @@
+
+#ifndef DataFormats_TrackSoA_src_alpaka_classes_rocm_h
+#define DataFormats_TrackSoA_src_alpaka_classes_rocm_h
+
+#include "DataFormats/Common/interface/DeviceProduct.h"
+#include "DataFormats/Common/interface/Wrapper.h"
+#include "DataFormats/TrackSoA/interface/TracksSoA.h"
+#include "DataFormats/TrackSoA/interface/alpaka/TracksSoACollection.h"
+#include "DataFormats/TrackSoA/interface/TracksDevice.h"
+#include "HeterogeneousCore/AlpakaInterface/interface/config.h"
+
+using namespace reco;
+
+#endif // DataFormats_TrackSoA_src_alpaka_classes_rocm_h
diff --git a/DataFormats/TrackSoA/src/alpaka/classes_rocm_def.xml b/DataFormats/TrackSoA/src/alpaka/classes_rocm_def.xml
new file mode 100644
index 0000000000000..b7e40aedead42
--- /dev/null
+++ b/DataFormats/TrackSoA/src/alpaka/classes_rocm_def.xml
@@ -0,0 +1,10 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/DataFormats/TrackSoA/src/classes.cc b/DataFormats/TrackSoA/src/classes.cc
new file mode 100644
index 0000000000000..97e00cc5b5638
--- /dev/null
+++ b/DataFormats/TrackSoA/src/classes.cc
@@ -0,0 +1,9 @@
+#include "DataFormats/Portable/interface/PortableHostCollectionReadRules.h"
+#include "DataFormats/TrackSoA/interface/TracksSoA.h"
+#include "Geometry/CommonTopologies/interface/SimplePixelTopology.h"
+
+using namespace reco;
+
+SET_PORTABLEHOSTCOLLECTION_READ_RULES(PortableHostCollection>);
+SET_PORTABLEHOSTCOLLECTION_READ_RULES(PortableHostCollection>);
+// SET_PORTABLEHOSTCOLLECTION_READ_RULES(PortableHostCollection>); //TODO: For the moment we live without HIons
diff --git a/DataFormats/TrackSoA/src/classes.h b/DataFormats/TrackSoA/src/classes.h
new file mode 100644
index 0000000000000..43d40e5f8f3ac
--- /dev/null
+++ b/DataFormats/TrackSoA/src/classes.h
@@ -0,0 +1,11 @@
+#ifndef DataFormats_TrackSoA_src_classes_h
+#define DataFormats_TrackSoA_src_classes_h
+
+#include "DataFormats/Common/interface/Wrapper.h"
+#include "DataFormats/TrackSoA/interface/TracksSoA.h"
+#include "DataFormats/TrackSoA/interface/TracksHost.h"
+
+using namespace pixelTopology;
+using namespace reco;
+
+#endif // DataFormats_TrackSoA_src_classes_h
diff --git a/DataFormats/TrackSoA/src/classes_def.xml b/DataFormats/TrackSoA/src/classes_def.xml
new file mode 100644
index 0000000000000..fd8fc0781ee25
--- /dev/null
+++ b/DataFormats/TrackSoA/src/classes_def.xml
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/DataFormats/TrackSoA/test/BuildFile.xml b/DataFormats/TrackSoA/test/BuildFile.xml
new file mode 100644
index 0000000000000..ce2b273d90577
--- /dev/null
+++ b/DataFormats/TrackSoA/test/BuildFile.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/DataFormats/TrackSoA/test/alpaka/TrackSoAHeterogeneous_test.cc b/DataFormats/TrackSoA/test/alpaka/TrackSoAHeterogeneous_test.cc
new file mode 100644
index 0000000000000..f4af0688ca1bf
--- /dev/null
+++ b/DataFormats/TrackSoA/test/alpaka/TrackSoAHeterogeneous_test.cc
@@ -0,0 +1,82 @@
+/**
+ Simple test for the pixelTrack::TrackSoA data structure
+ which inherits from PortableDeviceCollection.
+
+ Creates an instance of the class (automatically allocates
+ memory on device), passes the view of the SoA data to
+ the CUDA kernels which:
+ - Fill the SoA with data.
+ - Verify that the data written is correct.
+
+ Then, the SoA data are copied back to Host, where
+ a temporary host-side view (tmp_view) is created using
+ the same Layout to access the data on host and print it.
+ */
+
+#include
+#include
+#include "DataFormats/TrackSoA/interface/alpaka/TracksSoACollection.h"
+#include "DataFormats/TrackSoA/interface/TracksDevice.h"
+#include "DataFormats/TrackSoA/interface/TracksHost.h"
+#include "HeterogeneousCore/AlpakaInterface/interface/devices.h"
+#include "HeterogeneousCore/AlpakaInterface/interface/host.h"
+#include "HeterogeneousCore/AlpakaInterface/interface/memory.h"
+#include "HeterogeneousCore/AlpakaInterface/interface/config.h"
+#include "HeterogeneousCore/AlpakaInterface/interface/workdivision.h"
+#include "Geometry/CommonTopologies/interface/SimplePixelTopology.h"
+
+using namespace std;
+using namespace reco;
+using namespace ALPAKA_ACCELERATOR_NAMESPACE;
+using namespace ALPAKA_ACCELERATOR_NAMESPACE::pixelTrack;
+
+namespace ALPAKA_ACCELERATOR_NAMESPACE {
+ namespace testTrackSoA {
+
+ template
+ void runKernels(TrackSoAView tracks_view, Queue& queue);
+ }
+} // namespace ALPAKA_ACCELERATOR_NAMESPACE
+
+int main() {
+ const auto host = cms::alpakatools::host();
+ const auto device = cms::alpakatools::devices()[0];
+ Queue queue(device);
+
+ // Inner scope to deallocate memory before destroying the stream
+ {
+ // Instantiate tracks on device. PortableDeviceCollection allocates
+ // SoA on device automatically.
+ TracksSoACollection tracks_d(queue);
+ testTrackSoA::runKernels(tracks_d.view(), queue);
+
+ // Instantate tracks on host. This is where the data will be
+ // copied to from device.
+ TracksHost tracks_h(queue);
+
+ std::cout << tracks_h.view().metadata().size() << std::endl;
+ alpaka::memcpy(queue, tracks_h.buffer(), tracks_d.const_buffer());
+ alpaka::wait(queue);
+
+ // Print results
+ std::cout << "pt"
+ << "\t"
+ << "eta"
+ << "\t"
+ << "chi2"
+ << "\t"
+ << "quality"
+ << "\t"
+ << "nLayers"
+ << "\t"
+ << "hitIndices off" << std::endl;
+
+ for (int i = 0; i < 10; ++i) {
+ std::cout << tracks_h.view()[i].pt() << "\t" << tracks_h.view()[i].eta() << "\t" << tracks_h.view()[i].chi2()
+ << "\t" << (int)tracks_h.view()[i].quality() << "\t" << (int)tracks_h.view()[i].nLayers() << "\t"
+ << tracks_h.view().hitIndices().off[i] << std::endl;
+ }
+ }
+
+ return 0;
+}
diff --git a/DataFormats/TrackSoA/test/alpaka/TrackSoAHeterogeneous_test.dev.cc b/DataFormats/TrackSoA/test/alpaka/TrackSoAHeterogeneous_test.dev.cc
new file mode 100644
index 0000000000000..2c2d0961eb106
--- /dev/null
+++ b/DataFormats/TrackSoA/test/alpaka/TrackSoAHeterogeneous_test.dev.cc
@@ -0,0 +1,74 @@
+#include "Geometry/CommonTopologies/interface/SimplePixelTopology.h"
+#include "DataFormats/TrackSoA/interface/TrackDefinitions.h"
+#include "DataFormats/TrackSoA/interface/alpaka/TracksSoACollection.h"
+#include "DataFormats/TrackSoA/interface/TracksDevice.h"
+#include "DataFormats/TrackSoA/interface/TracksHost.h"
+
+using namespace reco;
+
+using Quality = pixelTrack::Quality;
+namespace ALPAKA_ACCELERATOR_NAMESPACE {
+ using namespace cms::alpakatools;
+ namespace testTrackSoA {
+
+ // Kernel which fills the TrackSoAView with data
+ // to test writing to it
+ template
+ class TestFillKernel {
+ public:
+ template >>
+ ALPAKA_FN_ACC void operator()(TAcc const& acc, TrackSoAView tracks_view) const {
+ if (cms::alpakatools::once_per_grid(acc)) {
+ tracks_view.nTracks() = 420;
+ }
+
+ for (int32_t j : elements_with_stride(acc, tracks_view.metadata().size())) {
+ tracks_view[j].pt() = (float)j;
+ tracks_view[j].eta() = (float)j;
+ tracks_view[j].chi2() = (float)j;
+ tracks_view[j].quality() = (Quality)(j % 256);
+ tracks_view[j].nLayers() = j % 128;
+ tracks_view.hitIndices().off[j] = j;
+ }
+ }
+ };
+
+ // Kernel which reads from the TrackSoAView to verify
+ // that it was written correctly from the fill kernel
+ template