Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:22:11

0001 #include "L1Trigger/TrackTrigger/interface/Setup.h"
0002 #include "FWCore/Utilities/interface/Exception.h"
0003 #include "DataFormats/Provenance/interface/ProcessConfiguration.h"
0004 #include "DataFormats/L1TrackTrigger/interface/TTBV.h"
0005 #include "DataFormats/L1TrackTrigger/interface/TTTypes.h"
0006 
0007 #include <cmath>
0008 #include <algorithm>
0009 #include <vector>
0010 #include <set>
0011 #include <unordered_map>
0012 #include <string>
0013 #include <sstream>
0014 
0015 using namespace std;
0016 using namespace edm;
0017 
0018 namespace tt {
0019 
0020   Setup::Setup(const ParameterSet& iConfig,
0021                const MagneticField& magneticField,
0022                const TrackerGeometry& trackerGeometry,
0023                const TrackerTopology& trackerTopology,
0024                const TrackerDetToDTCELinkCablingMap& cablingMap,
0025                const StubAlgorithmOfficial& stubAlgorithm,
0026                const ParameterSet& pSetStubAlgorithm,
0027                const ParameterSet& pSetGeometryConfiguration,
0028                const ParameterSetID& pSetIdTTStubAlgorithm,
0029                const ParameterSetID& pSetIdGeometryConfiguration)
0030       : magneticField_(&magneticField),
0031         trackerGeometry_(&trackerGeometry),
0032         trackerTopology_(&trackerTopology),
0033         cablingMap_(&cablingMap),
0034         stubAlgorithm_(&stubAlgorithm),
0035         pSetSA_(&pSetStubAlgorithm),
0036         pSetGC_(&pSetGeometryConfiguration),
0037         pSetIdTTStubAlgorithm_(pSetIdTTStubAlgorithm),
0038         pSetIdGeometryConfiguration_(pSetIdGeometryConfiguration),
0039         // DD4hep
0040         fromDD4hep_(iConfig.getParameter<bool>("fromDD4hep")),
0041         // Parameter to check if configured Tracker Geometry is supported
0042         pSetSG_(iConfig.getParameter<ParameterSet>("UnSupportedGeometry")),
0043         sgXMLLabel_(pSetSG_.getParameter<string>("XMLLabel")),
0044         sgXMLPath_(pSetSG_.getParameter<string>("XMLPath")),
0045         sgXMLFile_(pSetSG_.getParameter<string>("XMLFile")),
0046         sgXMLVersions_(pSetSG_.getParameter<vector<string>>("XMLVersions")),
0047         // Parameter to check if Process History is consistent with process configuration
0048         pSetPH_(iConfig.getParameter<ParameterSet>("ProcessHistory")),
0049         phGeometryConfiguration_(pSetPH_.getParameter<string>("GeometryConfiguration")),
0050         phTTStubAlgorithm_(pSetPH_.getParameter<string>("TTStubAlgorithm")),
0051         // Common track finding parameter
0052         pSetTF_(iConfig.getParameter<ParameterSet>("TrackFinding")),
0053         beamWindowZ_(pSetTF_.getParameter<double>("BeamWindowZ")),
0054         matchedLayers_(pSetTF_.getParameter<int>("MatchedLayers")),
0055         matchedLayersPS_(pSetTF_.getParameter<int>("MatchedLayersPS")),
0056         unMatchedStubs_(pSetTF_.getParameter<int>("UnMatchedStubs")),
0057         unMatchedStubsPS_(pSetTF_.getParameter<int>("UnMatchedStubsPS")),
0058         scattering_(pSetTF_.getParameter<double>("Scattering")),
0059         // TMTT specific parameter
0060         pSetTMTT_(iConfig.getParameter<ParameterSet>("TMTT")),
0061         minPt_(pSetTMTT_.getParameter<double>("MinPt")),
0062         maxEta_(pSetTMTT_.getParameter<double>("MaxEta")),
0063         chosenRofPhi_(pSetTMTT_.getParameter<double>("ChosenRofPhi")),
0064         numLayers_(pSetTMTT_.getParameter<int>("NumLayers")),
0065         tmttWidthR_(pSetTMTT_.getParameter<int>("WidthR")),
0066         tmttWidthPhi_(pSetTMTT_.getParameter<int>("WidthPhi")),
0067         tmttWidthZ_(pSetTMTT_.getParameter<int>("WidthZ")),
0068         // Hybrid specific parameter
0069         pSetHybrid_(iConfig.getParameter<ParameterSet>("Hybrid")),
0070         hybridMinPtStub_(pSetHybrid_.getParameter<double>("MinPtStub")),
0071         hybridMinPtCand_(pSetHybrid_.getParameter<double>("MinPtCand")),
0072         hybridMaxEta_(pSetHybrid_.getParameter<double>("MaxEta")),
0073         hybridChosenRofPhi_(pSetHybrid_.getParameter<double>("ChosenRofPhi")),
0074         hybridNumLayers_(pSetHybrid_.getParameter<int>("NumLayers")),
0075         hybridNumRingsPS_(pSetHybrid_.getParameter<vector<int>>("NumRingsPS")),
0076         hybridWidthsR_(pSetHybrid_.getParameter<vector<int>>("WidthsR")),
0077         hybridWidthsZ_(pSetHybrid_.getParameter<vector<int>>("WidthsZ")),
0078         hybridWidthsPhi_(pSetHybrid_.getParameter<vector<int>>("WidthsPhi")),
0079         hybridWidthsAlpha_(pSetHybrid_.getParameter<vector<int>>("WidthsAlpha")),
0080         hybridWidthsBend_(pSetHybrid_.getParameter<vector<int>>("WidthsBend")),
0081         hybridRangesR_(pSetHybrid_.getParameter<vector<double>>("RangesR")),
0082         hybridRangesZ_(pSetHybrid_.getParameter<vector<double>>("RangesZ")),
0083         hybridRangesAlpha_(pSetHybrid_.getParameter<vector<double>>("RangesAlpha")),
0084         hybridLayerRs_(pSetHybrid_.getParameter<vector<double>>("LayerRs")),
0085         hybridDiskZs_(pSetHybrid_.getParameter<vector<double>>("DiskZs")),
0086         hybridDisk2SRsSet_(pSetHybrid_.getParameter<vector<ParameterSet>>("Disk2SRsSet")),
0087         tbInnerRadius_(pSetHybrid_.getParameter<double>("InnerRadius")),
0088         tbWidthsR_(pSetHybrid_.getParameter<vector<int>>("WidthsRTB")),
0089         // Parameter specifying TrackingParticle used for Efficiency measurements
0090         pSetTP_(iConfig.getParameter<ParameterSet>("TrackingParticle")),
0091         tpMinPt_(pSetTP_.getParameter<double>("MinPt")),
0092         tpMaxEta_(pSetTP_.getParameter<double>("MaxEta")),
0093         tpMaxVertR_(pSetTP_.getParameter<double>("MaxVertR")),
0094         tpMaxVertZ_(pSetTP_.getParameter<double>("MaxVertZ")),
0095         tpMaxD0_(pSetTP_.getParameter<double>("MaxD0")),
0096         tpMinLayers_(pSetTP_.getParameter<int>("MinLayers")),
0097         tpMinLayersPS_(pSetTP_.getParameter<int>("MinLayersPS")),
0098         tpMaxBadStubs2S_(pSetTP_.getParameter<int>("MaxBadStubs2S")),
0099         tpMaxBadStubsPS_(pSetTP_.getParameter<int>("MaxBadStubsPS")),
0100         // Fimrware specific Parameter
0101         pSetFW_(iConfig.getParameter<ParameterSet>("Firmware")),
0102         widthDSPa_(pSetFW_.getParameter<int>("WidthDSPa")),
0103         widthDSPb_(pSetFW_.getParameter<int>("WidthDSPb")),
0104         widthDSPc_(pSetFW_.getParameter<int>("WidthDSPc")),
0105         widthAddrBRAM36_(pSetFW_.getParameter<int>("WidthAddrBRAM36")),
0106         widthAddrBRAM18_(pSetFW_.getParameter<int>("WidthAddrBRAM18")),
0107         numFramesInfra_(pSetFW_.getParameter<int>("NumFramesInfra")),
0108         freqLHC_(pSetFW_.getParameter<double>("FreqLHC")),
0109         freqBE_(pSetFW_.getParameter<double>("FreqBE")),
0110         tmpFE_(pSetFW_.getParameter<int>("TMP_FE")),
0111         tmpTFP_(pSetFW_.getParameter<int>("TMP_TFP")),
0112         speedOfLight_(pSetFW_.getParameter<double>("SpeedOfLight")),
0113         bField_(pSetFW_.getParameter<double>("BField")),
0114         bFieldError_(pSetFW_.getParameter<double>("BFieldError")),
0115         outerRadius_(pSetFW_.getParameter<double>("OuterRadius")),
0116         innerRadius_(pSetFW_.getParameter<double>("InnerRadius")),
0117         halfLength_(pSetFW_.getParameter<double>("HalfLength")),
0118         tiltApproxSlope_(pSetFW_.getParameter<double>("TiltApproxSlope")),
0119         tiltApproxIntercept_(pSetFW_.getParameter<double>("TiltApproxIntercept")),
0120         tiltUncertaintyR_(pSetFW_.getParameter<double>("TiltUncertaintyR")),
0121         mindPhi_(pSetFW_.getParameter<double>("MindPhi")),
0122         maxdPhi_(pSetFW_.getParameter<double>("MaxdPhi")),
0123         mindZ_(pSetFW_.getParameter<double>("MindZ")),
0124         maxdZ_(pSetFW_.getParameter<double>("MaxdZ")),
0125         pitch2S_(pSetFW_.getParameter<double>("Pitch2S")),
0126         pitchPS_(pSetFW_.getParameter<double>("PitchPS")),
0127         length2S_(pSetFW_.getParameter<double>("Length2S")),
0128         lengthPS_(pSetFW_.getParameter<double>("LengthPS")),
0129         tiltedLayerLimitsZ_(pSetFW_.getParameter<vector<double>>("TiltedLayerLimitsZ")),
0130         psDiskLimitsR_(pSetFW_.getParameter<vector<double>>("PSDiskLimitsR")),
0131         // Parmeter specifying front-end
0132         pSetFE_(iConfig.getParameter<ParameterSet>("FrontEnd")),
0133         widthBend_(pSetFE_.getParameter<int>("WidthBend")),
0134         widthCol_(pSetFE_.getParameter<int>("WidthCol")),
0135         widthRow_(pSetFE_.getParameter<int>("WidthRow")),
0136         baseBend_(pSetFE_.getParameter<double>("BaseBend")),
0137         baseCol_(pSetFE_.getParameter<double>("BaseCol")),
0138         baseRow_(pSetFE_.getParameter<double>("BaseRow")),
0139         baseWindowSize_(pSetFE_.getParameter<double>("BaseWindowSize")),
0140         bendCut_(pSetFE_.getParameter<double>("BendCut")),
0141         // Parmeter specifying DTC
0142         pSetDTC_(iConfig.getParameter<ParameterSet>("DTC")),
0143         numRegions_(pSetDTC_.getParameter<int>("NumRegions")),
0144         numOverlappingRegions_(pSetDTC_.getParameter<int>("NumOverlappingRegions")),
0145         numATCASlots_(pSetDTC_.getParameter<int>("NumATCASlots")),
0146         numDTCsPerRegion_(pSetDTC_.getParameter<int>("NumDTCsPerRegion")),
0147         numModulesPerDTC_(pSetDTC_.getParameter<int>("NumModulesPerDTC")),
0148         dtcNumRoutingBlocks_(pSetDTC_.getParameter<int>("NumRoutingBlocks")),
0149         dtcDepthMemory_(pSetDTC_.getParameter<int>("DepthMemory")),
0150         dtcWidthRowLUT_(pSetDTC_.getParameter<int>("WidthRowLUT")),
0151         dtcWidthInv2R_(pSetDTC_.getParameter<int>("WidthInv2R")),
0152         offsetDetIdDSV_(pSetDTC_.getParameter<int>("OffsetDetIdDSV")),
0153         offsetDetIdTP_(pSetDTC_.getParameter<int>("OffsetDetIdTP")),
0154         offsetLayerDisks_(pSetDTC_.getParameter<int>("OffsetLayerDisks")),
0155         offsetLayerId_(pSetDTC_.getParameter<int>("OffsetLayerId")),
0156         numBarrelLayer_(pSetDTC_.getParameter<int>("NumBarrelLayer")),
0157         slotLimitPS_(pSetDTC_.getParameter<int>("SlotLimitPS")),
0158         slotLimit10gbps_(pSetDTC_.getParameter<int>("SlotLimit10gbps")),
0159         // Parmeter specifying TFP
0160         pSetTFP_(iConfig.getParameter<ParameterSet>("TFP")),
0161         tfpWidthPhi0_(pSetTFP_.getParameter<int>("WidthPhi0")),
0162         tfpWidthInv2R_(pSetTFP_.getParameter<int>("WidthInv2R")),
0163         tfpWidthCot_(pSetTFP_.getParameter<int>("WidthCot")),
0164         tfpWidthZ0_(pSetTFP_.getParameter<int>("WidthZ0")),
0165         tfpNumChannel_(pSetTFP_.getParameter<int>("NumChannel")),
0166         // Parmeter specifying GeometricProcessor
0167         pSetGP_(iConfig.getParameter<ParameterSet>("GeometricProcessor")),
0168         numSectorsPhi_(pSetGP_.getParameter<int>("NumSectorsPhi")),
0169         chosenRofZ_(pSetGP_.getParameter<double>("ChosenRofZ")),
0170         neededRangeChiZ_(pSetGP_.getParameter<double>("RangeChiZ")),
0171         gpDepthMemory_(pSetGP_.getParameter<int>("DepthMemory")),
0172         boundariesEta_(pSetGP_.getParameter<vector<double>>("BoundariesEta")),
0173         // Parmeter specifying HoughTransform
0174         pSetHT_(iConfig.getParameter<ParameterSet>("HoughTransform")),
0175         htNumBinsInv2R_(pSetHT_.getParameter<int>("NumBinsInv2R")),
0176         htNumBinsPhiT_(pSetHT_.getParameter<int>("NumBinsPhiT")),
0177         htMinLayers_(pSetHT_.getParameter<int>("MinLayers")),
0178         htDepthMemory_(pSetHT_.getParameter<int>("DepthMemory")),
0179         // Parmeter specifying MiniHoughTransform
0180         pSetMHT_(iConfig.getParameter<ParameterSet>("MiniHoughTransform")),
0181         mhtNumBinsInv2R_(pSetMHT_.getParameter<int>("NumBinsInv2R")),
0182         mhtNumBinsPhiT_(pSetMHT_.getParameter<int>("NumBinsPhiT")),
0183         mhtNumDLBs_(pSetMHT_.getParameter<int>("NumDLBs")),
0184         mhtNumDLBNodes_(pSetMHT_.getParameter<int>("NumDLBNodes")),
0185         mhtNumDLBChannel_(pSetMHT_.getParameter<int>("NumDLBChannel")),
0186         mhtMinLayers_(pSetMHT_.getParameter<int>("MinLayers")),
0187         // Parmeter specifying ZHoughTransform
0188         pSetZHT_(iConfig.getParameter<ParameterSet>("ZHoughTransform")),
0189         zhtNumBinsZT_(pSetZHT_.getParameter<int>("NumBinsZT")),
0190         zhtNumBinsCot_(pSetZHT_.getParameter<int>("NumBinsCot")),
0191         zhtNumStages_(pSetZHT_.getParameter<int>("NumStages")),
0192         zhtMinLayers_(pSetZHT_.getParameter<int>("MinLayers")),
0193         zhtMaxTracks_(pSetZHT_.getParameter<int>("MaxTracks")),
0194         zhtMaxStubsPerLayer_(pSetZHT_.getParameter<int>("MaxStubsPerLayer")),
0195         // Parameter specifying KalmanFilter Input Formatter
0196         pSetKFin_(iConfig.getParameter<ParameterSet>("KalmanFilterIn")),
0197         kfinShiftRangePhi_(pSetKFin_.getParameter<int>("ShiftRangePhi")),
0198         kfinShiftRangeZ_(pSetKFin_.getParameter<int>("ShiftRangeZ")),
0199         // Parmeter specifying KalmanFilter
0200         pSetKF_(iConfig.getParameter<ParameterSet>("KalmanFilter")),
0201         kfNumWorker_(pSetKF_.getParameter<int>("NumWorker")),
0202         kfMinLayers_(pSetKF_.getParameter<int>("MinLayers")),
0203         kfMaxLayers_(pSetKF_.getParameter<int>("MaxLayers")),
0204         kfRangeFactor_(pSetKF_.getParameter<double>("RangeFactor")),
0205         kfShiftInitialC00_(pSetKF_.getParameter<int>("ShiftInitialC00")),
0206         kfShiftInitialC11_(pSetKF_.getParameter<int>("ShiftInitialC11")),
0207         kfShiftInitialC22_(pSetKF_.getParameter<int>("ShiftInitialC22")),
0208         kfShiftInitialC33_(pSetKF_.getParameter<int>("ShiftInitialC33")),
0209         // Parmeter specifying KalmanFilter Output Formatter
0210         pSetKFOut_(iConfig.getParameter<ParameterSet>("KalmanFilterOut")),
0211         kfoutchi2rphiConv_(pSetKFOut_.getParameter<int>("Chi2rphiConv")),
0212         kfoutchi2rzConv_(pSetKFOut_.getParameter<int>("Chi2rzConv")),
0213         weightBinFraction_(pSetKFOut_.getParameter<int>("WeightBinFraction")),
0214         dzTruncation_(pSetKFOut_.getParameter<int>("DzTruncation")),
0215         dphiTruncation_(pSetKFOut_.getParameter<int>("DphiTruncation")),
0216         // Parmeter specifying DuplicateRemoval
0217         pSetDR_(iConfig.getParameter<ParameterSet>("DuplicateRemoval")),
0218         drDepthMemory_(pSetDR_.getParameter<int>("DepthMemory")) {
0219     configurationSupported_ = true;
0220     // check if bField is supported
0221     checkMagneticField();
0222     // check if geometry is supported
0223     checkGeometry();
0224     if (!configurationSupported_)
0225       return;
0226     // derive constants
0227     calculateConstants();
0228     // convert configuration of TTStubAlgorithm
0229     consumeStubAlgorithm();
0230     // create all possible encodingsBend
0231     encodingsBendPS_.reserve(maxWindowSize_ + 1);
0232     encodingsBend2S_.reserve(maxWindowSize_ + 1);
0233     encodeBend(encodingsBendPS_, true);
0234     encodeBend(encodingsBend2S_, false);
0235     // create sensor modules
0236     produceSensorModules();
0237     // configure TPSelector
0238     configureTPSelector();
0239   }
0240 
0241   // checks current configuration vs input sample configuration
0242   void Setup::checkHistory(const ProcessHistory& processHistory) const {
0243     const pset::Registry* psetRegistry = pset::Registry::instance();
0244     // check used TTStubAlgorithm in input producer
0245     checkHistory(processHistory, psetRegistry, phTTStubAlgorithm_, pSetIdTTStubAlgorithm_);
0246     // check used GeometryConfiguration in input producer
0247     checkHistory(processHistory, psetRegistry, phGeometryConfiguration_, pSetIdGeometryConfiguration_);
0248   }
0249 
0250   // checks consitency between history and current configuration for a specific module
0251   void Setup::checkHistory(const ProcessHistory& ph,
0252                            const pset::Registry* pr,
0253                            const string& label,
0254                            const ParameterSetID& pSetId) const {
0255     vector<pair<string, ParameterSet>> pSets;
0256     pSets.reserve(ph.size());
0257     for (const ProcessConfiguration& pc : ph) {
0258       const ParameterSet* pSet = pr->getMapped(pc.parameterSetID());
0259       if (pSet && pSet->exists(label))
0260         pSets.emplace_back(pc.processName(), pSet->getParameterSet(label));
0261     }
0262     if (pSets.empty()) {
0263       cms::Exception exception("BadConfiguration");
0264       exception << label << " not found in process history.";
0265       exception.addContext("tt::Setup::checkHistory");
0266       throw exception;
0267     }
0268     auto consistent = [&pSetId](const pair<string, ParameterSet>& p) { return p.second.id() == pSetId; };
0269     if (!all_of(pSets.begin(), pSets.end(), consistent)) {
0270       const ParameterSet& pSetProcess = getParameterSet(pSetId);
0271       cms::Exception exception("BadConfiguration");
0272       exception.addContext("tt::Setup::checkHistory");
0273       exception << label << " inconsistent with History." << endl;
0274       exception << "Current Configuration:" << endl << pSetProcess.dump() << endl;
0275       for (const pair<string, ParameterSet>& p : pSets)
0276         if (!consistent(p))
0277           exception << "Process " << p.first << " Configuration:" << endl << dumpDiff(p.second, pSetProcess) << endl;
0278       throw exception;
0279     }
0280   }
0281 
0282   // dumps pSetHistory where incosistent lines with pSetProcess are highlighted
0283   string Setup::dumpDiff(const ParameterSet& pSetHistory, const ParameterSet& pSetProcess) const {
0284     stringstream ssHistory, ssProcess, ss;
0285     ssHistory << pSetHistory.dump();
0286     ssProcess << pSetProcess.dump();
0287     string lineHistory, lineProcess;
0288     for (; getline(ssHistory, lineHistory) && getline(ssProcess, lineProcess);)
0289       ss << (lineHistory != lineProcess ? "\033[1;31m" : "") << lineHistory << "\033[0m" << endl;
0290     return ss.str();
0291   }
0292 
0293   // converts tk layout id into dtc id
0294   int Setup::dtcId(int tkLayoutId) const {
0295     checkTKLayoutId(tkLayoutId);
0296     const int tkId = tkLayoutId - 1;
0297     const int side = tkId / (numRegions_ * numATCASlots_);
0298     const int region = (tkId % (numRegions_ * numATCASlots_)) / numATCASlots_;
0299     const int slot = tkId % numATCASlots_;
0300     return region * numDTCsPerRegion_ + side * numATCASlots_ + slot;
0301   }
0302 
0303   // converts dtc id into tk layout id
0304   int Setup::tkLayoutId(int dtcId) const {
0305     checkDTCId(dtcId);
0306     const int slot = dtcId % numATCASlots_;
0307     const int region = dtcId / numDTCsPerRegion_;
0308     const int side = (dtcId % numDTCsPerRegion_) / numATCASlots_;
0309     return (side * numRegions_ + region) * numATCASlots_ + slot + 1;
0310   }
0311 
0312   // converts TFP identifier (region[0-8], channel[0-47]) into dtc id
0313   int Setup::dtcId(int tfpRegion, int tfpChannel) const {
0314     checkTFPIdentifier(tfpRegion, tfpChannel);
0315     const int dtcChannel = numOverlappingRegions_ - (tfpChannel / numDTCsPerRegion_) - 1;
0316     const int dtcBoard = tfpChannel % numDTCsPerRegion_;
0317     const int dtcRegion = tfpRegion - dtcChannel >= 0 ? tfpRegion - dtcChannel : tfpRegion - dtcChannel + numRegions_;
0318     return dtcRegion * numDTCsPerRegion_ + dtcBoard;
0319   }
0320 
0321   // checks if given DTC id is connected to PS or 2S sensormodules
0322   bool Setup::psModule(int dtcId) const {
0323     checkDTCId(dtcId);
0324     // from tklayout: first 3 are 10 gbps PS, next 3 are 5 gbps PS and residual 6 are 5 gbps 2S modules
0325     return slot(dtcId) < slotLimitPS_;
0326   }
0327 
0328   // return sensor moduel type
0329   SensorModule::Type Setup::type(const TTStubRef& ttStubRef) const {
0330     const bool barrel = this->barrel(ttStubRef);
0331     const bool psModule = this->psModule(ttStubRef);
0332     SensorModule::Type type;
0333     if (barrel && psModule)
0334       type = SensorModule::BarrelPS;
0335     if (barrel && !psModule)
0336       type = SensorModule::Barrel2S;
0337     if (!barrel && psModule)
0338       type = SensorModule::DiskPS;
0339     if (!barrel && !psModule)
0340       type = SensorModule::Disk2S;
0341     return type;
0342   }
0343 
0344   // checks if given dtcId is connected via 10 gbps link
0345   bool Setup::gbps10(int dtcId) const {
0346     checkDTCId(dtcId);
0347     return slot(dtcId) < slotLimit10gbps_;
0348   }
0349 
0350   // checks if given dtcId is connected to -z (false) or +z (true)
0351   bool Setup::side(int dtcId) const {
0352     checkDTCId(dtcId);
0353     const int side = (dtcId % numDTCsPerRegion_) / numATCASlots_;
0354     // from tkLayout: first 12 +z, next 12 -z
0355     return side == 0;
0356   }
0357 
0358   // ATCA slot number [0-11] of given dtcId
0359   int Setup::slot(int dtcId) const {
0360     checkDTCId(dtcId);
0361     return dtcId % numATCASlots_;
0362   }
0363 
0364   // sensor module for det id
0365   SensorModule* Setup::sensorModule(const DetId& detId) const {
0366     const auto it = detIdToSensorModule_.find(detId);
0367     if (it == detIdToSensorModule_.end()) {
0368       cms::Exception exception("NullPtr");
0369       exception << "Unknown DetId used.";
0370       exception.addContext("tt::Setup::sensorModule");
0371       throw exception;
0372     }
0373     return it->second;
0374   }
0375 
0376   // index = encoded bend, value = decoded bend for given window size and module type
0377   const vector<double>& Setup::encodingBend(int windowSize, bool psModule) const {
0378     const vector<vector<double>>& encodingsBend = psModule ? encodingsBendPS_ : encodingsBend2S_;
0379     return encodingsBend.at(windowSize);
0380   }
0381 
0382   // check if bField is supported
0383   void Setup::checkMagneticField() {
0384     const double bFieldES = magneticField_->inTesla(GlobalPoint(0., 0., 0.)).z();
0385     if (abs(bField_ - bFieldES) > bFieldError_) {
0386       configurationSupported_ = false;
0387       LogWarning("ConfigurationNotSupported")
0388           << "Magnetic Field from EventSetup (" << bFieldES << ") differs more then " << bFieldError_
0389           << " from supported value (" << bField_ << "). ";
0390     }
0391   }
0392 
0393   // check if geometry is supported
0394   void Setup::checkGeometry() {
0395     //FIX ME: Can we assume that geometry used in dd4hep wf supports L1Track?
0396     if (!fromDD4hep_) {
0397       const vector<string>& geomXMLFiles = pSetGC_->getParameter<vector<string>>(sgXMLLabel_);
0398       string version;
0399       for (const string& geomXMLFile : geomXMLFiles) {
0400         const auto begin = geomXMLFile.find(sgXMLPath_) + sgXMLPath_.size();
0401         const auto end = geomXMLFile.find(sgXMLFile_);
0402         if (begin != string::npos && end != string::npos)
0403           version = geomXMLFile.substr(begin, end - begin - 1);
0404       }
0405       if (version.empty()) {
0406         cms::Exception exception("LogicError");
0407         exception << "No " << sgXMLPath_ << "*/" << sgXMLFile_ << " found in GeometryConfiguration";
0408         exception.addContext("tt::Setup::checkGeometry");
0409         throw exception;
0410       }
0411       if (find(sgXMLVersions_.begin(), sgXMLVersions_.end(), version) != sgXMLVersions_.end()) {
0412         configurationSupported_ = false;
0413         LogWarning("ConfigurationNotSupported")
0414             << "Geometry Configuration " << sgXMLPath_ << version << "/" << sgXMLFile_ << " is not supported. ";
0415       }
0416     }
0417   }
0418 
0419   // convert configuration of TTStubAlgorithm
0420   void Setup::consumeStubAlgorithm() {
0421     numTiltedLayerRings_ = pSetSA_->getParameter<vector<double>>("NTiltedRings");
0422     windowSizeBarrelLayers_ = pSetSA_->getParameter<vector<double>>("BarrelCut");
0423     const auto& pSetsTiltedLayer = pSetSA_->getParameter<vector<ParameterSet>>("TiltedBarrelCutSet");
0424     const auto& pSetsEncapDisks = pSetSA_->getParameter<vector<ParameterSet>>("EndcapCutSet");
0425     windowSizeTiltedLayerRings_.reserve(pSetsTiltedLayer.size());
0426     for (const auto& pSet : pSetsTiltedLayer)
0427       windowSizeTiltedLayerRings_.emplace_back(pSet.getParameter<vector<double>>("TiltedCut"));
0428     windowSizeEndcapDisksRings_.reserve(pSetsEncapDisks.size());
0429     for (const auto& pSet : pSetsEncapDisks)
0430       windowSizeEndcapDisksRings_.emplace_back(pSet.getParameter<vector<double>>("EndcapCut"));
0431     maxWindowSize_ = -1;
0432     for (const auto& windowss : {windowSizeTiltedLayerRings_, windowSizeEndcapDisksRings_, {windowSizeBarrelLayers_}})
0433       for (const auto& windows : windowss)
0434         for (const auto& window : windows)
0435           maxWindowSize_ = max(maxWindowSize_, (int)(window / baseWindowSize_));
0436   }
0437 
0438   // create bend encodings
0439   void Setup::encodeBend(vector<vector<double>>& encodings, bool ps) const {
0440     for (int window = 0; window < maxWindowSize_ + 1; window++) {
0441       set<double> encoding;
0442       for (int bend = 0; bend < window + 1; bend++)
0443         encoding.insert(stubAlgorithm_->degradeBend(ps, window, bend));
0444       encodings.emplace_back(encoding.begin(), encoding.end());
0445     }
0446   }
0447 
0448   // create sensor modules
0449   void Setup::produceSensorModules() {
0450     sensorModules_.reserve(numModules_);
0451     dtcModules_ = vector<vector<SensorModule*>>(numDTCs_);
0452     for (vector<SensorModule*>& dtcModules : dtcModules_)
0453       dtcModules.reserve(numModulesPerDTC_);
0454     enum SubDetId { pixelBarrel = 1, pixelDisks = 2 };
0455     // loop over all tracker modules
0456     for (const DetId& detId : trackerGeometry_->detIds()) {
0457       // skip pixel detector
0458       if (detId.subdetId() == pixelBarrel || detId.subdetId() == pixelDisks)
0459         continue;
0460       // skip multiple detIds per module
0461       if (!trackerTopology_->isLower(detId))
0462         continue;
0463       // lowerDetId - 1 = tk layout det id
0464       const DetId detIdTkLayout = detId + offsetDetIdTP_;
0465       // tk layout dtc id, lowerDetId - 1 = tk lyout det id
0466       const int tklId = cablingMap_->detIdToDTCELinkId(detIdTkLayout).first->second.dtc_id();
0467       // track trigger dtc id [0-215]
0468       const int dtcId = Setup::dtcId(tklId);
0469       // collection of so far connected modules to this dtc
0470       vector<SensorModule*>& dtcModules = dtcModules_[dtcId];
0471       // construct sendor module
0472       sensorModules_.emplace_back(this, detId, dtcId, dtcModules.size());
0473       SensorModule* sensorModule = &sensorModules_.back();
0474       // store connection between detId and sensor module
0475       detIdToSensorModule_.emplace(detId, sensorModule);
0476       // store connection between dtcId and sensor module
0477       dtcModules.push_back(sensorModule);
0478     }
0479     for (vector<SensorModule*>& dtcModules : dtcModules_) {
0480       dtcModules.shrink_to_fit();
0481       // check configuration
0482       if ((int)dtcModules.size() > numModulesPerDTC_) {
0483         cms::Exception exception("overflow");
0484         exception << "Cabling map connects more than " << numModulesPerDTC_ << " modules to a DTC.";
0485         exception.addContext("tt::Setup::Setup");
0486         throw exception;
0487       }
0488     }
0489   }
0490 
0491   // configure TPSelector
0492   void Setup::configureTPSelector() {
0493     // configure TrackingParticleSelector
0494     const double ptMin = tpMinPt_;
0495     constexpr double ptMax = 9.e9;
0496     const double etaMax = tpMaxEta_;
0497     const double tip = tpMaxVertR_;
0498     const double lip = tpMaxVertZ_;
0499     constexpr int minHit = 0;
0500     constexpr bool signalOnly = true;
0501     constexpr bool intimeOnly = true;
0502     constexpr bool chargedOnly = true;
0503     constexpr bool stableOnly = false;
0504     tpSelector_ = TrackingParticleSelector(
0505         ptMin, ptMax, -etaMax, etaMax, tip, lip, minHit, signalOnly, intimeOnly, chargedOnly, stableOnly);
0506     tpSelectorLoose_ =
0507         TrackingParticleSelector(ptMin, ptMax, -etaMax, etaMax, tip, lip, minHit, false, false, false, stableOnly);
0508   }
0509 
0510   // stub layer id (barrel: 1 - 6, endcap: 11 - 15)
0511   int Setup::layerId(const TTStubRef& ttStubRef) const {
0512     const DetId& detId = ttStubRef->getDetId();
0513     return detId.subdetId() == StripSubdetector::TOB ? trackerTopology_->layer(detId)
0514                                                      : trackerTopology_->tidWheel(detId) + offsetLayerDisks_;
0515   }
0516 
0517   // return tracklet layerId (barrel: [0-5], endcap: [6-10]) for given TTStubRef
0518   int Setup::trackletLayerId(const TTStubRef& ttStubRef) const {
0519     return this->layerId(ttStubRef) - (this->barrel(ttStubRef) ? offsetLayerId_ : numBarrelLayer_ - offsetLayerId_);
0520   }
0521 
0522   // return index layerId (barrel: [0-5], endcap: [0-6]) for given TTStubRef
0523   int Setup::indexLayerId(const TTStubRef& ttStubRef) const {
0524     return this->layerId(ttStubRef) - (this->barrel(ttStubRef) ? offsetLayerId_ : offsetLayerId_ + offsetLayerDisks_);
0525   }
0526 
0527   // true if stub from barrel module
0528   bool Setup::barrel(const TTStubRef& ttStubRef) const {
0529     const DetId& detId = ttStubRef->getDetId();
0530     return detId.subdetId() == StripSubdetector::TOB;
0531   }
0532 
0533   // true if stub from barrel module
0534   bool Setup::psModule(const TTStubRef& ttStubRef) const {
0535     const DetId& detId = ttStubRef->getDetId();
0536     return trackerGeometry_->getDetectorType(detId) == TrackerGeometry::ModuleType::Ph2PSP;
0537   }
0538 
0539   //
0540   TTBV Setup::layerMap(const vector<int>& ints) const {
0541     TTBV ttBV;
0542     for (int layer = numLayers_ - 1; layer >= 0; layer--) {
0543       const int i = ints[layer];
0544       ttBV += TTBV(i, kfWidthLayerCount_);
0545     }
0546     return ttBV;
0547   }
0548 
0549   //
0550   TTBV Setup::layerMap(const TTBV& hitPattern, const vector<int>& ints) const {
0551     TTBV ttBV;
0552     for (int layer = numLayers_ - 1; layer >= 0; layer--) {
0553       const int i = ints[layer];
0554       ttBV += TTBV((hitPattern[layer] ? i - 1 : 0), kfWidthLayerCount_);
0555     }
0556     return ttBV;
0557   }
0558 
0559   //
0560   vector<int> Setup::layerMap(const TTBV& hitPattern, const TTBV& ttBV) const {
0561     TTBV bv(ttBV);
0562     vector<int> ints(numLayers_, 0);
0563     for (int layer = 0; layer < numLayers_; layer++) {
0564       const int i = bv.extract(kfWidthLayerCount_);
0565       ints[layer] = i + (hitPattern[layer] ? 1 : 0);
0566     }
0567     return ints;
0568   }
0569 
0570   //
0571   vector<int> Setup::layerMap(const TTBV& ttBV) const {
0572     TTBV bv(ttBV);
0573     vector<int> ints(numLayers_, 0);
0574     for (int layer = 0; layer < numLayers_; layer++)
0575       ints[layer] = bv.extract(kfWidthLayerCount_);
0576     return ints;
0577   }
0578 
0579   // stub projected phi uncertainty
0580   double Setup::dPhi(const TTStubRef& ttStubRef, double inv2R) const {
0581     const DetId& detId = ttStubRef->getDetId();
0582     SensorModule* sm = sensorModule(detId + 1);
0583     const double r = stubPos(ttStubRef).perp();
0584     const double sigma = sm->pitchRow() / r;
0585     const double scat = scattering_ * abs(inv2R);
0586     const double extra = sm->barrel() ? 0. : sm->pitchCol() * abs(inv2R);
0587     const double digi = tmttBasePhi_;
0588     const double dPhi = sigma + scat + extra + digi;
0589     if (dPhi >= maxdPhi_ || dPhi < mindPhi_) {
0590       cms::Exception exception("out_of_range");
0591       exception.addContext("tt::Setup::dPhi");
0592       exception << "Stub phi uncertainty " << dPhi << " "
0593                 << "is out of range " << mindPhi_ << " to " << maxdPhi_ << ".";
0594       throw exception;
0595     }
0596     return dPhi;
0597   }
0598 
0599   // stub projected z uncertainty
0600   double Setup::dZ(const TTStubRef& ttStubRef, double cot) const {
0601     const DetId& detId = ttStubRef->getDetId();
0602     SensorModule* sm = sensorModule(detId + 1);
0603     const double sigma = sm->pitchCol() * sm->tiltCorrection(cot);
0604     const double digi = tmttBaseZ_;
0605     const double dZ = sigma + digi;
0606     if (dZ >= maxdZ_ || dZ < mindZ_) {
0607       cms::Exception exception("out_of_range");
0608       exception.addContext("tt::Setup::dZ");
0609       exception << "Stub z uncertainty " << dZ << " "
0610                 << "is out of range " << mindZ_ << " to " << maxdZ_ << ".";
0611       throw exception;
0612     }
0613     return dZ;
0614   }
0615 
0616   // stub projected chi2phi wheight
0617   double Setup::v0(const TTStubRef& ttStubRef, double inv2R) const {
0618     const DetId& detId = ttStubRef->getDetId();
0619     SensorModule* sm = sensorModule(detId + 1);
0620     const double r = stubPos(ttStubRef).perp();
0621     const double sigma = pow(sm->pitchRow() / r, 2) / 12.;
0622     const double scat = pow(scattering_ * inv2R, 2);
0623     const double extra = sm->barrel() ? 0. : pow(sm->pitchCol() * inv2R, 2);
0624     const double digi = pow(tmttBasePhi_ / 12., 2);
0625     return sigma + scat + extra + digi;
0626   }
0627 
0628   // stub projected chi2z wheight
0629   double Setup::v1(const TTStubRef& ttStubRef, double cot) const {
0630     const DetId& detId = ttStubRef->getDetId();
0631     SensorModule* sm = sensorModule(detId + 1);
0632     const double sigma = pow(sm->pitchCol() * sm->tiltCorrection(cot), 2) / 12.;
0633     const double digi = pow(tmttBaseZ_ / 12., 2);
0634     return sigma + digi;
0635   }
0636 
0637   // checks if stub collection is considered forming a reconstructable track
0638   bool Setup::reconstructable(const vector<TTStubRef>& ttStubRefs) const {
0639     set<int> hitPattern;
0640     for (const TTStubRef& ttStubRef : ttStubRefs)
0641       hitPattern.insert(layerId(ttStubRef));
0642     return (int)hitPattern.size() >= tpMinLayers_;
0643   }
0644 
0645   // checks if tracking particle is selected for efficiency measurements
0646   bool Setup::useForAlgEff(const TrackingParticle& tp) const {
0647     const bool selected = tpSelector_(tp);
0648     const double cot = sinh(tp.eta());
0649     const double s = sin(tp.phi());
0650     const double c = cos(tp.phi());
0651     const TrackingParticle::Point& v = tp.vertex();
0652     const double z0 = v.z() - (v.x() * c + v.y() * s) * cot;
0653     const double d0 = v.x() * s - v.y() * c;
0654     return selected && (abs(d0) < tpMaxD0_) && (abs(z0) < tpMaxVertZ_);
0655   }
0656 
0657   // derive constants
0658   void Setup::calculateConstants() {
0659     // emp
0660     const int numFramesPerBX = freqBE_ / freqLHC_;
0661     numFrames_ = numFramesPerBX * tmpTFP_ - 1;
0662     numFramesIO_ = numFramesPerBX * tmpTFP_ - numFramesInfra_;
0663     numFramesFE_ = numFramesPerBX * tmpFE_ - numFramesInfra_;
0664     // dsp
0665     widthDSPab_ = widthDSPa_ - 1;
0666     widthDSPau_ = widthDSPab_ - 1;
0667     widthDSPbb_ = widthDSPb_ - 1;
0668     widthDSPbu_ = widthDSPbb_ - 1;
0669     widthDSPcb_ = widthDSPc_ - 1;
0670     widthDSPcu_ = widthDSPcb_ - 1;
0671     // firmware
0672     maxPitch_ = max(pitchPS_, pitch2S_);
0673     maxLength_ = max(lengthPS_, length2S_);
0674     // common track finding
0675     invPtToDphi_ = speedOfLight_ * bField_ / 2000.;
0676     baseRegion_ = 2. * M_PI / numRegions_;
0677     // gp
0678     baseSector_ = baseRegion_ / numSectorsPhi_;
0679     maxCot_ = sinh(maxEta_);
0680     maxZT_ = maxCot_ * chosenRofZ_;
0681     numSectorsEta_ = boundariesEta_.size() - 1;
0682     numSectors_ = numSectorsPhi_ * numSectorsEta_;
0683     sectorCots_.reserve(numSectorsEta_);
0684     for (int eta = 0; eta < numSectorsEta_; eta++)
0685       sectorCots_.emplace_back((sinh(boundariesEta_.at(eta)) + sinh(boundariesEta_.at(eta + 1))) / 2.);
0686     // tmtt
0687     const double rangeInv2R = 2. * invPtToDphi_ / minPt_;
0688     tmttBaseInv2R_ = rangeInv2R / htNumBinsInv2R_;
0689     tmttBasePhiT_ = baseSector_ / htNumBinsPhiT_;
0690     const double baseRgen = tmttBasePhiT_ / tmttBaseInv2R_;
0691     const double rangeR = 2. * max(abs(outerRadius_ - chosenRofPhi_), abs(innerRadius_ - chosenRofPhi_));
0692     const int baseShiftR = ceil(log2(rangeR / baseRgen / pow(2., tmttWidthR_)));
0693     tmttBaseR_ = baseRgen * pow(2., baseShiftR);
0694     const double rangeZ = 2. * halfLength_;
0695     const int baseShiftZ = ceil(log2(rangeZ / tmttBaseR_ / pow(2., tmttWidthZ_)));
0696     tmttBaseZ_ = tmttBaseR_ * pow(2., baseShiftZ);
0697     const double rangePhi = baseRegion_ + rangeInv2R * rangeR / 2.;
0698     const int baseShiftPhi = ceil(log2(rangePhi / tmttBasePhiT_ / pow(2., tmttWidthPhi_)));
0699     tmttBasePhi_ = tmttBasePhiT_ * pow(2., baseShiftPhi);
0700     tmttWidthLayer_ = ceil(log2(numLayers_));
0701     tmttWidthSectorEta_ = ceil(log2(numSectorsEta_));
0702     tmttWidthInv2R_ = ceil(log2(htNumBinsInv2R_));
0703     tmttNumUnusedBits_ = TTBV::S_ - tmttWidthLayer_ - 2 * tmttWidthSectorEta_ - tmttWidthR_ - tmttWidthPhi_ -
0704                          tmttWidthZ_ - 2 * tmttWidthInv2R_ - numSectorsPhi_ - 1;
0705     // hybrid
0706     const double hybridRangeInv2R = 2. * invPtToDphi_ / hybridMinPtStub_;
0707     const double hybridRangeR =
0708         2. * max(abs(outerRadius_ - hybridChosenRofPhi_), abs(innerRadius_ - hybridChosenRofPhi_));
0709     hybridRangePhi_ = baseRegion_ + (hybridRangeR * hybridRangeInv2R) / 2.;
0710     hybridWidthLayerId_ = ceil(log2(hybridNumLayers_));
0711     hybridBasesZ_.reserve(SensorModule::NumTypes);
0712     for (int type = 0; type < SensorModule::NumTypes; type++)
0713       hybridBasesZ_.emplace_back(hybridRangesZ_.at(type) / pow(2., hybridWidthsZ_.at(type)));
0714     hybridBasesR_.reserve(SensorModule::NumTypes);
0715     for (int type = 0; type < SensorModule::NumTypes; type++)
0716       hybridBasesR_.emplace_back(hybridRangesR_.at(type) / pow(2., hybridWidthsR_.at(type)));
0717     hybridBasesR_[SensorModule::Disk2S] = 1.;
0718     hybridBasesPhi_.reserve(SensorModule::NumTypes);
0719     for (int type = 0; type < SensorModule::NumTypes; type++)
0720       hybridBasesPhi_.emplace_back(hybridRangePhi_ / pow(2., hybridWidthsPhi_.at(type)));
0721     hybridBasesAlpha_.reserve(SensorModule::NumTypes);
0722     for (int type = 0; type < SensorModule::NumTypes; type++)
0723       hybridBasesAlpha_.emplace_back(hybridRangesAlpha_.at(type) / pow(2., hybridWidthsAlpha_.at(type)));
0724     hybridNumsUnusedBits_.reserve(SensorModule::NumTypes);
0725     for (int type = 0; type < SensorModule::NumTypes; type++)
0726       hybridNumsUnusedBits_.emplace_back(TTBV::S_ - hybridWidthsR_.at(type) - hybridWidthsZ_.at(type) -
0727                                          hybridWidthsPhi_.at(type) - hybridWidthsAlpha_.at(type) -
0728                                          hybridWidthsBend_.at(type) - hybridWidthLayerId_ - 1);
0729     hybridMaxCot_ = sinh(hybridMaxEta_);
0730     disk2SRs_.reserve(hybridDisk2SRsSet_.size());
0731     for (const auto& pSet : hybridDisk2SRsSet_)
0732       disk2SRs_.emplace_back(pSet.getParameter<vector<double>>("Disk2SRs"));
0733     // dtc
0734     numDTCs_ = numRegions_ * numDTCsPerRegion_;
0735     numDTCsPerTFP_ = numDTCsPerRegion_ * numOverlappingRegions_;
0736     numModules_ = numDTCs_ * numModulesPerDTC_;
0737     dtcNumModulesPerRoutingBlock_ = numModulesPerDTC_ / dtcNumRoutingBlocks_;
0738     dtcNumMergedRows_ = pow(2, widthRow_ - dtcWidthRowLUT_);
0739     const double maxRangeInv2R = max(rangeInv2R, hybridRangeInv2R);
0740     const int baseShiftInv2R = ceil(log2(htNumBinsInv2R_)) - dtcWidthInv2R_ + ceil(log2(maxRangeInv2R / rangeInv2R));
0741     dtcBaseInv2R_ = tmttBaseInv2R_ * pow(2., baseShiftInv2R);
0742     const int baseDiffM = dtcWidthRowLUT_ - widthRow_;
0743     dtcBaseM_ = tmttBasePhi_ * pow(2., baseDiffM);
0744     const double x1 = pow(2, widthRow_) * baseRow_ * maxPitch_ / 2.;
0745     const double x0 = x1 - pow(2, dtcWidthRowLUT_) * baseRow_ * maxPitch_;
0746     const double maxM = atan2(x1, innerRadius_) - atan2(x0, innerRadius_);
0747     dtcWidthM_ = ceil(log2(maxM / dtcBaseM_));
0748     dtcNumStreams_ = numDTCs_ * numOverlappingRegions_;
0749     // mht
0750     mhtNumCells_ = mhtNumBinsInv2R_ * mhtNumBinsPhiT_;
0751     // zht
0752     zhtNumCells_ = zhtNumBinsCot_ * zhtNumBinsZT_;
0753     //
0754     kfWidthLayerCount_ = ceil(log2(zhtMaxStubsPerLayer_));
0755   }
0756 
0757   // returns bit accurate hybrid stub radius for given TTStubRef and h/w bit word
0758   double Setup::stubR(const TTBV& hw, const TTStubRef& ttStubRef) const {
0759     const bool barrel = this->barrel(ttStubRef);
0760     const int layerId = this->indexLayerId(ttStubRef);
0761     const SensorModule::Type type = this->type(ttStubRef);
0762     const int widthR = hybridWidthsR_.at(type);
0763     const double baseR = hybridBasesR_.at(type);
0764     const TTBV hwR(hw, widthR, 0, barrel);
0765     double r = hwR.val(baseR) + (barrel ? hybridLayerRs_.at(layerId) : 0.);
0766     if (type == SensorModule::Disk2S)
0767       r = disk2SRs_.at(layerId).at((int)r);
0768     return r;
0769   }
0770 
0771   // returns bit accurate position of a stub from a given tfp region [0-8]
0772   GlobalPoint Setup::stubPos(bool hybrid, const FrameStub& frame, int region) const {
0773     GlobalPoint p;
0774     if (frame.first.isNull())
0775       return p;
0776     TTBV bv(frame.second);
0777     if (hybrid) {
0778       const bool barrel = this->barrel(frame.first);
0779       const int layerId = this->indexLayerId(frame.first);
0780       const GlobalPoint gp = this->stubPos(frame.first);
0781       const bool side = gp.z() > 0.;
0782       const SensorModule::Type type = this->type(frame.first);
0783       const int widthBend = hybridWidthsBend_.at(type);
0784       const int widthAlpha = hybridWidthsAlpha_.at(type);
0785       const int widthPhi = hybridWidthsPhi_.at(type);
0786       const int widthZ = hybridWidthsZ_.at(type);
0787       const int widthR = hybridWidthsR_.at(type);
0788       const double basePhi = hybridBasesPhi_.at(type);
0789       const double baseZ = hybridBasesZ_.at(type);
0790       const double baseR = hybridBasesR_.at(type);
0791       // parse bit vector
0792       bv >>= 1 + hybridWidthLayerId_ + widthBend + widthAlpha;
0793       double phi = bv.val(basePhi, widthPhi) - hybridRangePhi_ / 2.;
0794       bv >>= widthPhi;
0795       double z = bv.val(baseZ, widthZ, 0, true);
0796       bv >>= widthZ;
0797       double r = bv.val(baseR, widthR, 0, barrel);
0798       if (barrel)
0799         r += hybridLayerRs_.at(layerId);
0800       else
0801         z += hybridDiskZs_.at(layerId) * (side ? 1. : -1.);
0802       phi = deltaPhi(phi + region * baseRegion_);
0803       if (type == SensorModule::Disk2S) {
0804         r = bv.val(widthR);
0805         r = disk2SRs_.at(layerId).at((int)r);
0806       }
0807       p = GlobalPoint(GlobalPoint::Cylindrical(r, phi, z));
0808     } else {
0809       bv >>= 2 * tmttWidthInv2R_ + 2 * tmttWidthSectorEta_ + numSectorsPhi_ + tmttWidthLayer_;
0810       double z = (bv.val(tmttWidthZ_, 0, true) + .5) * tmttBaseZ_;
0811       bv >>= tmttWidthZ_;
0812       double phi = (bv.val(tmttWidthPhi_, 0, true) + .5) * tmttBasePhi_;
0813       bv >>= tmttWidthPhi_;
0814       double r = (bv.val(tmttWidthR_, 0, true) + .5) * tmttBaseR_;
0815       bv >>= tmttWidthR_;
0816       r = r + chosenRofPhi_;
0817       phi = deltaPhi(phi + region * baseRegion_);
0818       p = GlobalPoint(GlobalPoint::Cylindrical(r, phi, z));
0819     }
0820     return p;
0821   }
0822 
0823   // returns global TTStub position
0824   GlobalPoint Setup::stubPos(const TTStubRef& ttStubRef) const {
0825     const DetId detId = ttStubRef->getDetId() + offsetDetIdDSV_;
0826     const GeomDetUnit* det = trackerGeometry_->idToDetUnit(detId);
0827     const PixelTopology* topol =
0828         dynamic_cast<const PixelTopology*>(&(dynamic_cast<const PixelGeomDetUnit*>(det)->specificTopology()));
0829     const Plane& plane = dynamic_cast<const PixelGeomDetUnit*>(det)->surface();
0830     const MeasurementPoint& mp = ttStubRef->clusterRef(0)->findAverageLocalCoordinatesCentered();
0831     return plane.toGlobal(topol->localPosition(mp));
0832   }
0833 
0834   // range check of dtc id
0835   void Setup::checkDTCId(int dtcId) const {
0836     if (dtcId < 0 || dtcId >= numDTCsPerRegion_ * numRegions_) {
0837       cms::Exception exception("out_of_range");
0838       exception.addContext("tt::Setup::checkDTCId");
0839       exception << "Used DTC Id (" << dtcId << ") "
0840                 << "is out of range 0 to " << numDTCsPerRegion_ * numRegions_ - 1 << ".";
0841       throw exception;
0842     }
0843   }
0844 
0845   // range check of tklayout id
0846   void Setup::checkTKLayoutId(int tkLayoutId) const {
0847     if (tkLayoutId <= 0 || tkLayoutId > numDTCsPerRegion_ * numRegions_) {
0848       cms::Exception exception("out_of_range");
0849       exception.addContext("tt::Setup::checkTKLayoutId");
0850       exception << "Used TKLayout Id (" << tkLayoutId << ") "
0851                 << "is out of range 1 to " << numDTCsPerRegion_ * numRegions_ << ".";
0852       throw exception;
0853     }
0854   }
0855 
0856   // range check of tfp identifier
0857   void Setup::checkTFPIdentifier(int tfpRegion, int tfpChannel) const {
0858     const bool oorRegion = tfpRegion >= numRegions_ || tfpRegion < 0;
0859     const bool oorChannel = tfpChannel >= numDTCsPerTFP_ || tfpChannel < 0;
0860     if (oorRegion || oorChannel) {
0861       cms::Exception exception("out_of_range");
0862       exception.addContext("tt::Setup::checkTFPIdentifier");
0863       if (oorRegion)
0864         exception << "Requested Processing Region "
0865                   << "(" << tfpRegion << ") "
0866                   << "is out of range 0 to " << numRegions_ - 1 << ".";
0867       if (oorChannel)
0868         exception << "Requested TFP Channel "
0869                   << "(" << tfpChannel << ") "
0870                   << "is out of range 0 to " << numDTCsPerTFP_ - 1 << ".";
0871       throw exception;
0872     }
0873   }
0874 }  // namespace tt