Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-07-02 00:53:55

0001 #include "DataFormats/ForwardDetId/interface/ForwardSubdetector.h"
0002 #include "DataFormats/ForwardDetId/interface/HFNoseTriggerDetId.h"
0003 #include "DataFormats/ForwardDetId/interface/HGCScintillatorDetId.h"
0004 #include "DataFormats/ForwardDetId/interface/HGCSiliconDetIdToROC.h"
0005 #include "DataFormats/ForwardDetId/interface/HGCalDetId.h"
0006 #include "DataFormats/ForwardDetId/interface/HGCalTriggerDetId.h"
0007 #include "FWCore/ParameterSet/interface/FileInPath.h"
0008 #include "L1Trigger/L1THGCal/interface/HGCalTriggerGeometryBase.h"
0009 #include "DataFormats/ForwardDetId/interface/HFNoseDetIdToModule.h"
0010 
0011 #include "oneapi/tbb/concurrent_unordered_set.h"
0012 #include <fstream>
0013 #include <iostream>
0014 #include <regex>
0015 #include <vector>
0016 
0017 class HGCalTriggerGeometryV9Imp2 : public HGCalTriggerGeometryBase {
0018 public:
0019   HGCalTriggerGeometryV9Imp2(const edm::ParameterSet& conf);
0020 
0021   void initialize(const HGCalGeometry*, const HGCalGeometry*, const HGCalGeometry*) final;
0022   void initialize(const HGCalGeometry*, const HGCalGeometry*, const HGCalGeometry*, const HGCalGeometry*) final;
0023   void reset() final;
0024 
0025   unsigned getTriggerCellFromCell(const unsigned) const final;
0026   unsigned getModuleFromCell(const unsigned) const final;
0027   unsigned getModuleFromTriggerCell(const unsigned) const final;
0028 
0029   geom_set getCellsFromTriggerCell(const unsigned) const final;
0030   geom_set getCellsFromModule(const unsigned) const final;
0031   geom_set getTriggerCellsFromModule(const unsigned) const final;
0032 
0033   geom_ordered_set getOrderedCellsFromModule(const unsigned) const final;
0034   geom_ordered_set getOrderedTriggerCellsFromModule(const unsigned) const final;
0035 
0036   geom_set getNeighborsFromTriggerCell(const unsigned) const final;
0037 
0038   geom_set getStage1FpgasFromStage2Fpga(const unsigned) const final;
0039   geom_set getStage2FpgasFromStage1Fpga(const unsigned) const final;
0040 
0041   geom_set getStage1LinksFromStage2Fpga(const unsigned) const final;
0042   unsigned getStage1FpgaFromStage1Link(const unsigned) const final;
0043   unsigned getStage2FpgaFromStage1Link(const unsigned) const final;
0044   geom_set getStage1LinksFromStage1Fpga(const unsigned) const final;
0045   std::vector<unsigned> getLpgbtsFromStage1Fpga(const unsigned) const final;
0046   unsigned getStage1FpgaFromLpgbt(const unsigned) const final;
0047   geom_set getModulesFromLpgbt(const unsigned) const final;
0048   geom_set getLpgbtsFromModule(const unsigned) const final;
0049   unsigned getStage1FpgaFromModule(const unsigned module_id) const final;
0050 
0051   unsigned getLinksInModule(const unsigned module_id) const final;
0052   unsigned getModuleSize(const unsigned module_id) const final;
0053 
0054   GlobalPoint getTriggerCellPosition(const unsigned) const final;
0055   GlobalPoint getModulePosition(const unsigned) const final;
0056 
0057   bool validCell(const unsigned) const final;
0058   bool validTriggerCell(const unsigned) const final;
0059   bool disconnectedModule(const unsigned) const final;
0060   unsigned lastTriggerLayer() const final { return last_trigger_layer_; }
0061   unsigned triggerLayer(const unsigned) const final;
0062 
0063 private:
0064   // HSc trigger cell grouping
0065   unsigned hSc_triggercell_size_ = 2;
0066   unsigned hSc_module_size_ = 12;  // in TC units (144 TC / panel = 36 e-links)
0067   unsigned hSc_links_per_module_ = 1;
0068   unsigned hSc_wafers_per_module_ = 3;
0069 
0070   unsigned sector0_mask_ = 0x7f;  // 7 bits to encode module number in 60deg sector
0071 
0072   edm::FileInPath l1tModulesMapping_;
0073   edm::FileInPath l1tLinksMapping_;
0074 
0075   // module related maps
0076   std::unordered_map<unsigned, unsigned> wafer_to_module_;
0077   std::unordered_multimap<unsigned, unsigned> module_to_wafers_;
0078   std::unordered_map<unsigned, unsigned> links_per_module_;
0079   mutable tbb::concurrent_unordered_set<unsigned> cache_missing_wafers_;
0080 
0081   // Disconnected modules and layers
0082   std::unordered_set<unsigned> disconnected_modules_;
0083   std::unordered_set<unsigned> disconnected_layers_;
0084   std::vector<unsigned> trigger_layers_;
0085   std::vector<unsigned> trigger_nose_layers_;
0086   unsigned last_trigger_layer_ = 0;
0087 
0088   // layer offsets
0089   unsigned heOffset_ = 0;
0090   unsigned noseLayers_ = 0;
0091   unsigned totalLayers_ = 0;
0092 
0093   void fillMaps();
0094   bool validCellId(unsigned det, unsigned cell_id) const;
0095   bool validTriggerCellFromCells(const unsigned) const;
0096 
0097   int detIdWaferType(unsigned det, unsigned layer, short waferU, short waferV) const;
0098   unsigned packWaferId(int waferU, int waferV) const;
0099   unsigned packLayerWaferId(unsigned layer, int waferU, int waferV) const;
0100   unsigned packLayerModuleId(unsigned layer, unsigned wafer) const;
0101   void unpackWaferId(unsigned wafer, int& waferU, int& waferV) const;
0102 
0103   unsigned layerWithOffset(unsigned) const;
0104 };
0105 
0106 HGCalTriggerGeometryV9Imp2::HGCalTriggerGeometryV9Imp2(const edm::ParameterSet& conf)
0107     : HGCalTriggerGeometryBase(conf),
0108       hSc_triggercell_size_(conf.getParameter<unsigned>("ScintillatorTriggerCellSize")),
0109       hSc_module_size_(conf.getParameter<unsigned>("ScintillatorModuleSize")),
0110       hSc_links_per_module_(conf.getParameter<unsigned>("ScintillatorLinksPerModule")),
0111       l1tModulesMapping_(conf.getParameter<edm::FileInPath>("L1TModulesMapping")),
0112       l1tLinksMapping_(conf.getParameter<edm::FileInPath>("L1TLinksMapping")) {
0113   const unsigned ntc_per_wafer = 48;
0114   hSc_wafers_per_module_ = std::round(hSc_module_size_ * hSc_module_size_ / float(ntc_per_wafer));
0115   if (ntc_per_wafer * hSc_wafers_per_module_ < hSc_module_size_ * hSc_module_size_) {
0116     hSc_wafers_per_module_++;
0117   }
0118   std::vector<unsigned> tmp_vector = conf.getParameter<std::vector<unsigned>>("DisconnectedModules");
0119   std::move(tmp_vector.begin(), tmp_vector.end(), std::inserter(disconnected_modules_, disconnected_modules_.end()));
0120   tmp_vector = conf.getParameter<std::vector<unsigned>>("DisconnectedLayers");
0121   std::move(tmp_vector.begin(), tmp_vector.end(), std::inserter(disconnected_layers_, disconnected_layers_.end()));
0122 }
0123 
0124 void HGCalTriggerGeometryV9Imp2::reset() {
0125   wafer_to_module_.clear();
0126   module_to_wafers_.clear();
0127   cache_missing_wafers_.clear();
0128 }
0129 
0130 void HGCalTriggerGeometryV9Imp2::initialize(const HGCalGeometry* hgc_ee_geometry,
0131                                             const HGCalGeometry* hgc_hsi_geometry,
0132                                             const HGCalGeometry* hgc_hsc_geometry) {
0133   setEEGeometry(hgc_ee_geometry);
0134   setHSiGeometry(hgc_hsi_geometry);
0135   setHScGeometry(hgc_hsc_geometry);
0136   heOffset_ = eeTopology().dddConstants().layers(true);
0137   totalLayers_ = heOffset_ + hsiTopology().dddConstants().layers(true);
0138   trigger_layers_.resize(totalLayers_ + 1);
0139   trigger_layers_[0] = 0;  // layer number 0 doesn't exist
0140   unsigned trigger_layer = 1;
0141   for (unsigned layer = 1; layer < trigger_layers_.size(); layer++) {
0142     if (disconnected_layers_.find(layer) == disconnected_layers_.end()) {
0143       // Increase trigger layer number if the layer is not disconnected
0144       trigger_layers_[layer] = trigger_layer;
0145       trigger_layer++;
0146     } else {
0147       trigger_layers_[layer] = 0;
0148     }
0149   }
0150   last_trigger_layer_ = trigger_layer - 1;
0151   fillMaps();
0152 }
0153 
0154 void HGCalTriggerGeometryV9Imp2::initialize(const HGCalGeometry* hgc_ee_geometry,
0155                                             const HGCalGeometry* hgc_hsi_geometry,
0156                                             const HGCalGeometry* hgc_hsc_geometry,
0157                                             const HGCalGeometry* hgc_nose_geometry) {
0158   setEEGeometry(hgc_ee_geometry);
0159   setHSiGeometry(hgc_hsi_geometry);
0160   setHScGeometry(hgc_hsc_geometry);
0161   setNoseGeometry(hgc_nose_geometry);
0162 
0163   heOffset_ = eeTopology().dddConstants().layers(true);
0164   totalLayers_ = heOffset_ + hsiTopology().dddConstants().layers(true);
0165 
0166   trigger_layers_.resize(totalLayers_ + 1);
0167   trigger_layers_[0] = 0;  // layer number 0 doesn't exist
0168   unsigned trigger_layer = 1;
0169   for (unsigned layer = 1; layer < trigger_layers_.size(); layer++) {
0170     if (disconnected_layers_.find(layer) == disconnected_layers_.end()) {
0171       // Increase trigger layer number if the layer is not disconnected
0172       trigger_layers_[layer] = trigger_layer;
0173       trigger_layer++;
0174     } else {
0175       trigger_layers_[layer] = 0;
0176     }
0177   }
0178   last_trigger_layer_ = trigger_layer - 1;
0179   fillMaps();
0180 
0181   noseLayers_ = noseTopology().dddConstants().layers(true);
0182 
0183   trigger_nose_layers_.resize(noseLayers_ + 1);
0184   trigger_nose_layers_[0] = 0;  // layer number 0 doesn't exist
0185   unsigned trigger_nose_layer = 1;
0186   for (unsigned layer = 1; layer < trigger_nose_layers_.size(); layer++) {
0187     trigger_nose_layers_[layer] = trigger_nose_layer;
0188     trigger_nose_layer++;
0189   }
0190 }
0191 
0192 unsigned HGCalTriggerGeometryV9Imp2::getTriggerCellFromCell(const unsigned cell_id) const {
0193   unsigned det = DetId(cell_id).det();
0194   unsigned trigger_cell_id = 0;
0195   // Scintillator
0196   if (det == DetId::HGCalHSc) {
0197     // Very rough mapping from cells to TC
0198     HGCScintillatorDetId cell_sc_id(cell_id);
0199     int ieta = ((cell_sc_id.ietaAbs() - 1) / hSc_triggercell_size_ + 1) * cell_sc_id.zside();
0200     int iphi = (cell_sc_id.iphi() - 1) / hSc_triggercell_size_ + 1;
0201     trigger_cell_id = HGCScintillatorDetId(cell_sc_id.type(), cell_sc_id.layer(), ieta, iphi);
0202   }
0203   // HFNose
0204   else if (det == DetId::Forward && DetId(cell_id).subdetId() == ForwardSubdetector::HFNose) {
0205     HFNoseDetId cell_nose_id(cell_id);
0206     trigger_cell_id = HFNoseTriggerDetId(HGCalTriggerSubdetector::HFNoseTrigger,
0207                                          cell_nose_id.zside(),
0208                                          cell_nose_id.type(),
0209                                          cell_nose_id.layer(),
0210                                          cell_nose_id.waferU(),
0211                                          cell_nose_id.waferV(),
0212                                          cell_nose_id.triggerCellU(),
0213                                          cell_nose_id.triggerCellV());
0214   }
0215   // Silicon
0216   else if (det == DetId::HGCalEE || det == DetId::HGCalHSi) {
0217     HGCSiliconDetId cell_si_id(cell_id);
0218     trigger_cell_id = HGCalTriggerDetId(
0219         det == DetId::HGCalEE ? HGCalTriggerSubdetector::HGCalEETrigger : HGCalTriggerSubdetector::HGCalHSiTrigger,
0220         cell_si_id.zside(),
0221         cell_si_id.type(),
0222         cell_si_id.layer(),
0223         cell_si_id.waferU(),
0224         cell_si_id.waferV(),
0225         cell_si_id.triggerCellU(),
0226         cell_si_id.triggerCellV());
0227   }
0228   return trigger_cell_id;
0229 }
0230 
0231 unsigned HGCalTriggerGeometryV9Imp2::getModuleFromCell(const unsigned cell_id) const {
0232   return getModuleFromTriggerCell(getTriggerCellFromCell(cell_id));
0233 }
0234 
0235 unsigned HGCalTriggerGeometryV9Imp2::getModuleFromTriggerCell(const unsigned trigger_cell_id) const {
0236   unsigned det = DetId(trigger_cell_id).det();
0237   unsigned module = 0;
0238   unsigned subdet_old = 0;
0239   int zside = 0;
0240   unsigned tc_type = 1;
0241   unsigned layer = 0;
0242   unsigned module_id = 0;
0243   // Scintillator
0244   if (det == DetId::HGCalHSc) {
0245     HGCScintillatorDetId trigger_cell_sc_id(trigger_cell_id);
0246     tc_type = trigger_cell_sc_id.type();
0247     layer = trigger_cell_sc_id.layer();
0248     zside = trigger_cell_sc_id.zside();
0249     int ietamin = hscTopology().dddConstants().getREtaRange(layer).first;
0250     int ietamin_tc = ((ietamin - 1) / hSc_triggercell_size_ + 1);
0251     int ieta = ((trigger_cell_sc_id.ietaAbs() - ietamin_tc) / hSc_module_size_ + 1) * zside;
0252     int iphi = (trigger_cell_sc_id.iphi() - 1) / hSc_module_size_ + 1;
0253     module_id = HGCScintillatorDetId(tc_type, layer, ieta, iphi);
0254   }
0255   // HFNose
0256   else if (det == DetId::HGCalTrigger and
0257            HGCalTriggerDetId(trigger_cell_id).subdet() == HGCalTriggerSubdetector::HFNoseTrigger) {
0258     HFNoseTriggerDetId trigger_cell_trig_id(trigger_cell_id);
0259     tc_type = trigger_cell_trig_id.type();
0260     layer = trigger_cell_trig_id.layer();
0261     zside = trigger_cell_trig_id.zside();
0262     int waferu = trigger_cell_trig_id.waferU();
0263     int waferv = trigger_cell_trig_id.waferV();
0264 
0265     HFNoseDetIdToModule hfn;
0266     module_id = hfn.getModule(HFNoseDetId(zside, layer, tc_type, waferu, waferv, 0, 0)).rawId();
0267   }
0268   // Silicon
0269   else {
0270     HGCalTriggerDetId trigger_cell_trig_id(trigger_cell_id);
0271     unsigned subdet = trigger_cell_trig_id.subdet();
0272     subdet_old =
0273         (subdet == HGCalTriggerSubdetector::HGCalEETrigger ? ForwardSubdetector::HGCEE : ForwardSubdetector::HGCHEF);
0274     layer = trigger_cell_trig_id.layer();
0275     zside = trigger_cell_trig_id.zside();
0276     if (subdet == HGCalTriggerSubdetector::HGCalEETrigger || subdet == HGCalTriggerSubdetector::HGCalHSiTrigger) {
0277       int waferu = trigger_cell_trig_id.waferU();
0278       int waferv = trigger_cell_trig_id.waferV();
0279       unsigned layer_with_offset = layerWithOffset(trigger_cell_id);
0280       unsigned packed_wafer = packLayerWaferId(layer_with_offset, waferu, waferv);
0281       auto module_itr = wafer_to_module_.find(packed_wafer);
0282       if (module_itr == wafer_to_module_.end()) {
0283         // return missing modules as disconnected (id=0)
0284         module = 0;
0285         auto insert_itr = cache_missing_wafers_.emplace(packed_wafer);
0286         if (insert_itr.second) {
0287           edm::LogWarning("HGCalTriggerGeometry")
0288               << "Found missing wafer (layer=" << layer_with_offset << " u=" << waferu << " v=" << waferv
0289               << ") in trigger modules mapping";
0290         }
0291       } else {
0292         module = module_itr->second;
0293       }
0294     }
0295     module_id =
0296         HGCalDetId((ForwardSubdetector)subdet_old, zside, layer, tc_type, module, HGCalDetId::kHGCalCellMask).rawId();
0297   }
0298   return module_id;
0299 }
0300 
0301 HGCalTriggerGeometryBase::geom_set HGCalTriggerGeometryV9Imp2::getCellsFromTriggerCell(
0302     const unsigned trigger_cell_id) const {
0303   DetId trigger_cell_det_id(trigger_cell_id);
0304   unsigned det = trigger_cell_det_id.det();
0305   geom_set cell_det_ids;
0306   // Scintillator
0307   if (det == DetId::HGCalHSc) {
0308     HGCScintillatorDetId trigger_cell_sc_id(trigger_cell_id);
0309     int ieta0 = (trigger_cell_sc_id.ietaAbs() - 1) * hSc_triggercell_size_ + 1;
0310     int iphi0 = (trigger_cell_sc_id.iphi() - 1) * hSc_triggercell_size_ + 1;
0311     for (int ietaAbs = ieta0; ietaAbs < ieta0 + (int)hSc_triggercell_size_; ietaAbs++) {
0312       int ieta = ietaAbs * trigger_cell_sc_id.zside();
0313       for (int iphi = iphi0; iphi < iphi0 + (int)hSc_triggercell_size_; iphi++) {
0314         unsigned cell_id = HGCScintillatorDetId(trigger_cell_sc_id.type(), trigger_cell_sc_id.layer(), ieta, iphi);
0315         if (validCellId(DetId::HGCalHSc, cell_id))
0316           cell_det_ids.emplace(cell_id);
0317       }
0318     }
0319   }
0320   // HFNose
0321   else if (det == DetId::HGCalTrigger and
0322            HGCalTriggerDetId(trigger_cell_id).subdet() == HGCalTriggerSubdetector::HFNoseTrigger) {
0323     HFNoseTriggerDetId trigger_cell_nose_id(trigger_cell_id);
0324     int layer = trigger_cell_nose_id.layer();
0325     int zside = trigger_cell_nose_id.zside();
0326     int type = trigger_cell_nose_id.type();
0327     int waferu = trigger_cell_nose_id.waferU();
0328     int waferv = trigger_cell_nose_id.waferV();
0329     std::vector<int> cellus = trigger_cell_nose_id.cellU();
0330     std::vector<int> cellvs = trigger_cell_nose_id.cellV();
0331     for (unsigned ic = 0; ic < cellus.size(); ic++) {
0332       HFNoseDetId cell_det_id(zside, type, layer, waferu, waferv, cellus[ic], cellvs[ic]);
0333       cell_det_ids.emplace(cell_det_id);
0334     }
0335   }
0336   // Silicon
0337   else {
0338     HGCalTriggerDetId trigger_cell_trig_id(trigger_cell_id);
0339     unsigned subdet = trigger_cell_trig_id.subdet();
0340     if (subdet == HGCalTriggerSubdetector::HGCalEETrigger || subdet == HGCalTriggerSubdetector::HGCalHSiTrigger) {
0341       DetId::Detector cell_det = (subdet == HGCalTriggerSubdetector::HGCalEETrigger ? DetId::HGCalEE : DetId::HGCalHSi);
0342       int layer = trigger_cell_trig_id.layer();
0343       int zside = trigger_cell_trig_id.zside();
0344       int type = trigger_cell_trig_id.type();
0345       int waferu = trigger_cell_trig_id.waferU();
0346       int waferv = trigger_cell_trig_id.waferV();
0347       std::vector<int> cellus = trigger_cell_trig_id.cellU();
0348       std::vector<int> cellvs = trigger_cell_trig_id.cellV();
0349       for (unsigned ic = 0; ic < cellus.size(); ic++) {
0350         HGCSiliconDetId cell_det_id(cell_det, zside, type, layer, waferu, waferv, cellus[ic], cellvs[ic]);
0351         cell_det_ids.emplace(cell_det_id);
0352       }
0353     }
0354   }
0355   return cell_det_ids;
0356 }
0357 
0358 HGCalTriggerGeometryBase::geom_set HGCalTriggerGeometryV9Imp2::getCellsFromModule(const unsigned module_id) const {
0359   geom_set cell_det_ids;
0360   geom_set trigger_cells = getTriggerCellsFromModule(module_id);
0361   for (auto trigger_cell_id : trigger_cells) {
0362     geom_set cells = getCellsFromTriggerCell(trigger_cell_id);
0363     cell_det_ids.insert(cells.begin(), cells.end());
0364   }
0365   return cell_det_ids;
0366 }
0367 
0368 HGCalTriggerGeometryBase::geom_ordered_set HGCalTriggerGeometryV9Imp2::getOrderedCellsFromModule(
0369     const unsigned module_id) const {
0370   geom_ordered_set cell_det_ids;
0371   geom_ordered_set trigger_cells = getOrderedTriggerCellsFromModule(module_id);
0372   for (auto trigger_cell_id : trigger_cells) {
0373     geom_set cells = getCellsFromTriggerCell(trigger_cell_id);
0374     cell_det_ids.insert(cells.begin(), cells.end());
0375   }
0376   return cell_det_ids;
0377 }
0378 
0379 HGCalTriggerGeometryBase::geom_set HGCalTriggerGeometryV9Imp2::getTriggerCellsFromModule(
0380     const unsigned module_id) const {
0381   DetId module_det_id(module_id);
0382   unsigned det = module_det_id.det();
0383   geom_set trigger_cell_det_ids;
0384   // Scintillator
0385   if (det == DetId::HGCalHSc) {
0386     HGCScintillatorDetId module_sc_id(module_id);
0387     int ietamin = hscTopology().dddConstants().getREtaRange(module_sc_id.layer()).first;
0388     int ietamin_tc = ((ietamin - 1) / hSc_triggercell_size_ + 1);
0389     int ieta0 = (module_sc_id.ietaAbs() - 1) * hSc_module_size_ + ietamin_tc;
0390     int iphi0 = (module_sc_id.iphi() - 1) * hSc_module_size_ + 1;
0391     for (int ietaAbs = ieta0; ietaAbs < ieta0 + (int)hSc_module_size_; ietaAbs++) {
0392       int ieta = ietaAbs * module_sc_id.zside();
0393       for (int iphi = iphi0; iphi < iphi0 + (int)hSc_module_size_; iphi++) {
0394         unsigned trigger_cell_id = HGCScintillatorDetId(module_sc_id.type(), module_sc_id.layer(), ieta, iphi);
0395         if (validTriggerCellFromCells(trigger_cell_id))
0396           trigger_cell_det_ids.emplace(trigger_cell_id);
0397       }
0398     }
0399   }
0400   // HFNose
0401   else if (det == DetId::Forward && module_det_id.subdetId() == ForwardSubdetector::HFNose) {
0402     HFNoseDetId module_nose_id(module_id);
0403     HFNoseDetIdToModule hfn;
0404     std::vector<HFNoseTriggerDetId> ids = hfn.getTriggerDetIds(module_nose_id);
0405     for (auto const& idx : ids) {
0406       if (validTriggerCellFromCells(idx.rawId()))
0407         trigger_cell_det_ids.emplace(idx);
0408     }
0409   }
0410   // Silicon
0411   else {
0412     HGCalDetId module_si_id(module_id);
0413     unsigned module = module_si_id.wafer();
0414     HGCSiliconDetIdToROC tc2roc;
0415     auto wafer_itrs = module_to_wafers_.equal_range(packLayerModuleId(layerWithOffset(module_id), module));
0416     // loop on the wafers included in the module
0417     for (auto wafer_itr = wafer_itrs.first; wafer_itr != wafer_itrs.second; wafer_itr++) {
0418       int waferu = 0;
0419       int waferv = 0;
0420       unpackWaferId(wafer_itr->second, waferu, waferv);
0421       DetId::Detector det = (module_si_id.subdetId() == ForwardSubdetector::HGCEE ? DetId::HGCalEE : DetId::HGCalHSi);
0422       HGCalTriggerSubdetector subdet =
0423           (module_si_id.subdetId() == ForwardSubdetector::HGCEE ? HGCalTriggerSubdetector::HGCalEETrigger
0424                                                                 : HGCalTriggerSubdetector::HGCalHSiTrigger);
0425       unsigned layer = module_si_id.layer();
0426       unsigned wafer_type = detIdWaferType(det, layer, waferu, waferv);
0427       int nroc = (((wafer_type == HGCSiliconDetId::HGCalHD120) || (wafer_type == HGCSiliconDetId::HGCalHD200)) ? 6 : 3);
0428       // Loop on ROCs in wafer
0429       for (int roc = 1; roc <= nroc; roc++) {
0430         // loop on TCs in ROC
0431         auto tc_uvs = tc2roc.getTriggerId(roc, wafer_type);
0432         for (const auto& tc_uv : tc_uvs) {
0433           HGCalTriggerDetId trigger_cell_id(
0434               subdet, module_si_id.zside(), wafer_type, layer, waferu, waferv, tc_uv.first, tc_uv.second);
0435           if (validTriggerCellFromCells(trigger_cell_id.rawId()))
0436             trigger_cell_det_ids.emplace(trigger_cell_id);
0437         }
0438       }
0439     }
0440   }
0441 
0442   return trigger_cell_det_ids;
0443 }
0444 
0445 HGCalTriggerGeometryBase::geom_ordered_set HGCalTriggerGeometryV9Imp2::getOrderedTriggerCellsFromModule(
0446     const unsigned module_id) const {
0447   DetId module_det_id(module_id);
0448   unsigned det = module_det_id.det();
0449   geom_ordered_set trigger_cell_det_ids;
0450   // Scintillator
0451   if (det == DetId::HGCalHSc) {
0452     HGCScintillatorDetId module_sc_id(module_id);
0453     int ieta0 = (module_sc_id.ietaAbs() - 1) * hSc_module_size_ + 1;
0454     int iphi0 = (module_sc_id.iphi() - 1) * hSc_module_size_ + 1;
0455     for (int ietaAbs = ieta0; ietaAbs < ieta0 + (int)hSc_module_size_; ietaAbs++) {
0456       int ieta = ietaAbs * module_sc_id.zside();
0457       for (int iphi = iphi0; iphi < iphi0 + (int)hSc_module_size_; iphi++) {
0458         unsigned trigger_cell_id = HGCScintillatorDetId(module_sc_id.type(), module_sc_id.layer(), ieta, iphi);
0459         if (validTriggerCellFromCells(trigger_cell_id))
0460           trigger_cell_det_ids.emplace(trigger_cell_id);
0461       }
0462     }
0463   }
0464   // HFNose
0465   else if (det == DetId::Forward && DetId(module_det_id).subdetId() == ForwardSubdetector::HFNose) {
0466     HFNoseDetId module_nose_id(module_id);
0467     HFNoseDetIdToModule hfn;
0468     std::vector<HFNoseTriggerDetId> ids = hfn.getTriggerDetIds(module_nose_id);
0469     for (auto const& idx : ids) {
0470       if (validTriggerCellFromCells(idx.rawId()))
0471         trigger_cell_det_ids.emplace(idx);
0472     }
0473   }
0474   // EE or FH
0475   else {
0476     HGCalDetId module_si_id(module_id);
0477     unsigned module = module_si_id.wafer();
0478     HGCSiliconDetIdToROC tc2roc;
0479     auto wafer_itrs = module_to_wafers_.equal_range(packLayerModuleId(layerWithOffset(module_id), module));
0480     // loop on the wafers included in the module
0481     for (auto wafer_itr = wafer_itrs.first; wafer_itr != wafer_itrs.second; wafer_itr++) {
0482       int waferu = 0;
0483       int waferv = 0;
0484       unpackWaferId(wafer_itr->second, waferu, waferv);
0485       DetId::Detector det = (module_si_id.subdetId() == ForwardSubdetector::HGCEE ? DetId::HGCalEE : DetId::HGCalHSi);
0486       HGCalTriggerSubdetector subdet =
0487           (module_si_id.subdetId() == ForwardSubdetector::HGCEE ? HGCalTriggerSubdetector::HGCalEETrigger
0488                                                                 : HGCalTriggerSubdetector::HGCalHSiTrigger);
0489       unsigned layer = module_si_id.layer();
0490       unsigned wafer_type = detIdWaferType(det, layer, waferu, waferv);
0491       int nroc = (((wafer_type == HGCSiliconDetId::HGCalHD120) || (wafer_type == HGCSiliconDetId::HGCalHD200)) ? 6 : 3);
0492       // Loop on ROCs in wafer
0493       for (int roc = 1; roc <= nroc; roc++) {
0494         // loop on TCs in ROC
0495         auto tc_uvs = tc2roc.getTriggerId(roc, wafer_type);
0496         for (const auto& tc_uv : tc_uvs) {
0497           HGCalTriggerDetId trigger_cell_id(
0498               subdet, module_si_id.zside(), wafer_type, layer, waferu, waferv, tc_uv.first, tc_uv.second);
0499           trigger_cell_det_ids.emplace(trigger_cell_id);
0500         }
0501       }
0502     }
0503   }
0504   return trigger_cell_det_ids;
0505 }
0506 
0507 HGCalTriggerGeometryBase::geom_set HGCalTriggerGeometryV9Imp2::getNeighborsFromTriggerCell(
0508     const unsigned trigger_cell_id) const {
0509   throw cms::Exception("FeatureNotImplemented") << "Neighbor search is not implemented in HGCalTriggerGeometryV9Imp2";
0510 }
0511 
0512 unsigned HGCalTriggerGeometryV9Imp2::getLinksInModule(const unsigned module_id) const {
0513   DetId module_det_id(module_id);
0514   unsigned links = 0;
0515   // Scintillator
0516   if (module_det_id.det() == DetId::HGCalHSc) {
0517     links = hSc_links_per_module_;
0518   } else if (module_det_id.det() == DetId::Forward && module_det_id.subdetId() == ForwardSubdetector::HFNose) {
0519     links = 1;
0520   }
0521   // TO ADD HFNOSE : getLinksInModule
0522   // Silicon
0523   else {
0524     HGCalDetId module_det_id_si(module_id);
0525     unsigned module = module_det_id_si.wafer();
0526     unsigned layer = layerWithOffset(module_id);
0527     module = (module & sector0_mask_);
0528     links = links_per_module_.at(packLayerModuleId(layer, module));
0529   }
0530   return links;
0531 }
0532 
0533 unsigned HGCalTriggerGeometryV9Imp2::getModuleSize(const unsigned module_id) const {
0534   DetId module_det_id(module_id);
0535   unsigned nWafers = 1;
0536   // Scintillator
0537   if (module_det_id.det() == DetId::HGCalHSc) {
0538     nWafers = hSc_wafers_per_module_;
0539   }
0540   // Check for HFNOSE : getModuleSize
0541   // Silicon
0542   else {
0543     HGCalDetId module_det_id_si(module_id);
0544     unsigned module = module_det_id_si.wafer();
0545     unsigned layer = layerWithOffset(module_id);
0546     nWafers = module_to_wafers_.count(packLayerModuleId(layer, module));
0547   }
0548   return nWafers;
0549 }
0550 
0551 GlobalPoint HGCalTriggerGeometryV9Imp2::getTriggerCellPosition(const unsigned trigger_cell_det_id) const {
0552   unsigned det = DetId(trigger_cell_det_id).det();
0553   // Position: barycenter of the trigger cell.
0554   Basic3DVector<float> triggerCellVector(0., 0., 0.);
0555   const auto cell_ids = getCellsFromTriggerCell(trigger_cell_det_id);
0556   // Scintillator
0557   if (det == DetId::HGCalHSc) {
0558     for (const auto& cell : cell_ids) {
0559       triggerCellVector += hscGeometry()->getPosition(cell).basicVector();
0560     }
0561   }
0562   // HFNose
0563   else if (det == DetId::HGCalTrigger and
0564            HGCalTriggerDetId(trigger_cell_det_id).subdet() == HGCalTriggerSubdetector::HFNoseTrigger) {
0565     for (const auto& cell : cell_ids) {
0566       HFNoseDetId cellDetId(cell);
0567       triggerCellVector += noseGeometry()->getPosition(cellDetId).basicVector();
0568     }
0569   }
0570   // Silicon
0571   else {
0572     for (const auto& cell : cell_ids) {
0573       HGCSiliconDetId cellDetId(cell);
0574       triggerCellVector += (cellDetId.det() == DetId::HGCalEE ? eeGeometry()->getPosition(cellDetId)
0575                                                               : hsiGeometry()->getPosition(cellDetId))
0576                                .basicVector();
0577     }
0578   }
0579   return GlobalPoint(triggerCellVector / cell_ids.size());
0580 }
0581 
0582 GlobalPoint HGCalTriggerGeometryV9Imp2::getModulePosition(const unsigned module_det_id) const {
0583   unsigned det = DetId(module_det_id).det();
0584   // Position: barycenter of the module.
0585   Basic3DVector<float> moduleVector(0., 0., 0.);
0586   const auto cell_ids = getCellsFromModule(module_det_id);
0587   // Scintillator
0588   if (det == DetId::HGCalHSc) {
0589     for (const auto& cell : cell_ids) {
0590       moduleVector += hscGeometry()->getPosition(cell).basicVector();
0591     }
0592   }
0593   // HFNose
0594   else if (det == DetId::Forward && DetId(module_det_id).subdetId() == ForwardSubdetector::HFNose) {
0595     for (const auto& cell : cell_ids) {
0596       HFNoseDetId cellDetId(cell);
0597       moduleVector += noseGeometry()->getPosition(cellDetId).basicVector();
0598     }
0599   }  // Silicon
0600   else {
0601     for (const auto& cell : cell_ids) {
0602       HGCSiliconDetId cellDetId(cell);
0603       moduleVector += (cellDetId.det() == DetId::HGCalEE ? eeGeometry()->getPosition(cellDetId)
0604                                                          : hsiGeometry()->getPosition(cellDetId))
0605                           .basicVector();
0606     }
0607   }
0608 
0609   return GlobalPoint(moduleVector / cell_ids.size());
0610 }
0611 
0612 void HGCalTriggerGeometryV9Imp2::fillMaps() {
0613   // read module mapping file
0614   std::ifstream l1tModulesMappingStream(l1tModulesMapping_.fullPath());
0615   if (!l1tModulesMappingStream.is_open()) {
0616     throw cms::Exception("MissingDataFile") << "Cannot open HGCalTriggerGeometry L1TModulesMapping file\n";
0617   }
0618 
0619   short waferu = 0;
0620   short waferv = 0;
0621   short module = 0;
0622   short layer = 0;
0623   for (; l1tModulesMappingStream >> layer >> waferu >> waferv >> module;) {
0624     wafer_to_module_.emplace(packLayerWaferId(layer, waferu, waferv), module);
0625     module_to_wafers_.emplace(packLayerModuleId(layer, module), packWaferId(waferu, waferv));
0626   }
0627   if (!l1tModulesMappingStream.eof()) {
0628     throw cms::Exception("BadGeometryFile")
0629         << "Error reading L1TModulesMapping '" << layer << " " << waferu << " " << waferv << " " << module << "' \n";
0630   }
0631   l1tModulesMappingStream.close();
0632   // read links mapping file
0633   std::ifstream l1tLinksMappingStream(l1tLinksMapping_.fullPath());
0634   if (!l1tLinksMappingStream.is_open()) {
0635     throw cms::Exception("MissingDataFile") << "Cannot open HGCalTriggerGeometry L1TLinksMapping file\n";
0636   }
0637   short links = 0;
0638   const short max_modules_60deg_sector = 127;
0639   for (; l1tLinksMappingStream >> layer >> module >> links;) {
0640     if (module_to_wafers_.find(packLayerModuleId(layer, module)) == module_to_wafers_.end()) {
0641       links = 0;
0642     }
0643     if (module > max_modules_60deg_sector)
0644       sector0_mask_ = 0xff;  // Use 8 bits to encode module number in 120deg sector
0645     links_per_module_.emplace(packLayerModuleId(layer, module), links);
0646   }
0647   if (!l1tLinksMappingStream.eof()) {
0648     throw cms::Exception("BadGeometryFile")
0649         << "Error reading L1TLinksMapping '" << layer << " " << module << " " << links << "' \n";
0650   }
0651   l1tLinksMappingStream.close();
0652 }
0653 
0654 unsigned HGCalTriggerGeometryV9Imp2::packWaferId(int waferU, int waferV) const {
0655   unsigned packed_value = 0;
0656   unsigned waferUsign = (waferU >= 0) ? 0 : 1;
0657   unsigned waferVsign = (waferV >= 0) ? 0 : 1;
0658   packed_value |= ((std::abs(waferU) & HGCSiliconDetId::kHGCalWaferUMask) << HGCSiliconDetId::kHGCalWaferUOffset);
0659   packed_value |= ((waferUsign & HGCSiliconDetId::kHGCalWaferUSignMask) << HGCSiliconDetId::kHGCalWaferUSignOffset);
0660   packed_value |= ((std::abs(waferV) & HGCSiliconDetId::kHGCalWaferVMask) << HGCSiliconDetId::kHGCalWaferVOffset);
0661   packed_value |= ((waferVsign & HGCSiliconDetId::kHGCalWaferVSignMask) << HGCSiliconDetId::kHGCalWaferVSignOffset);
0662   return packed_value;
0663 }
0664 
0665 unsigned HGCalTriggerGeometryV9Imp2::packLayerWaferId(unsigned layer, int waferU, int waferV) const {
0666   unsigned packed_value = 0;
0667   unsigned subdet = ForwardSubdetector::HGCEE;
0668   if (layer > heOffset_) {
0669     layer -= heOffset_;
0670     subdet = ForwardSubdetector::HGCHEF;
0671   }
0672   unsigned waferUsign = (waferU >= 0) ? 0 : 1;
0673   unsigned waferVsign = (waferV >= 0) ? 0 : 1;
0674   packed_value |= ((std::abs(waferU) & HGCSiliconDetId::kHGCalWaferUMask) << HGCSiliconDetId::kHGCalWaferUOffset);
0675   packed_value |= ((waferUsign & HGCSiliconDetId::kHGCalWaferUSignMask) << HGCSiliconDetId::kHGCalWaferUSignOffset);
0676   packed_value |= ((std::abs(waferV) & HGCSiliconDetId::kHGCalWaferVMask) << HGCSiliconDetId::kHGCalWaferVOffset);
0677   packed_value |= ((waferVsign & HGCSiliconDetId::kHGCalWaferVSignMask) << HGCSiliconDetId::kHGCalWaferVSignOffset);
0678   packed_value |= ((layer & HGCSiliconDetId::kHGCalLayerMask) << HGCSiliconDetId::kHGCalLayerOffset);
0679   packed_value |= ((subdet & DetId::kSubdetMask) << DetId::kSubdetOffset);
0680   return packed_value;
0681 }
0682 
0683 unsigned HGCalTriggerGeometryV9Imp2::packLayerModuleId(unsigned layer, unsigned module) const {
0684   unsigned packed_value = 0;
0685   unsigned subdet = ForwardSubdetector::HGCEE;
0686   if (layer > heOffset_) {
0687     layer -= heOffset_;
0688     subdet = ForwardSubdetector::HGCHEF;
0689   }
0690   packed_value |= ((layer & HGCalDetId::kHGCalLayerMask) << HGCalDetId::kHGCalLayerOffset);
0691   packed_value |= ((module & HGCalDetId::kHGCalWaferMask) << HGCalDetId::kHGCalWaferOffset);
0692   packed_value |= ((subdet & DetId::kSubdetMask) << DetId::kSubdetOffset);
0693   return packed_value;
0694 }
0695 
0696 void HGCalTriggerGeometryV9Imp2::unpackWaferId(unsigned wafer, int& waferU, int& waferV) const {
0697   unsigned waferUAbs = (wafer >> HGCSiliconDetId::kHGCalWaferUOffset) & HGCSiliconDetId::kHGCalWaferUMask;
0698   unsigned waferVAbs = (wafer >> HGCSiliconDetId::kHGCalWaferVOffset) & HGCSiliconDetId::kHGCalWaferVMask;
0699   waferU = (((wafer >> HGCSiliconDetId::kHGCalWaferUSignOffset) & HGCSiliconDetId::kHGCalWaferUSignMask) ? -waferUAbs
0700                                                                                                          : waferUAbs);
0701   waferV = (((wafer >> HGCSiliconDetId::kHGCalWaferVSignOffset) & HGCSiliconDetId::kHGCalWaferVSignMask) ? -waferVAbs
0702                                                                                                          : waferVAbs);
0703 }
0704 
0705 bool HGCalTriggerGeometryV9Imp2::validTriggerCell(const unsigned trigger_cell_id) const {
0706   return validTriggerCellFromCells(trigger_cell_id);
0707 }
0708 
0709 bool HGCalTriggerGeometryV9Imp2::disconnectedModule(const unsigned module_id) const {
0710   bool disconnected = false;
0711   if (disconnected_modules_.find(HGCalDetId(module_id).wafer()) != disconnected_modules_.end())
0712     disconnected = true;
0713   if (disconnected_layers_.find(layerWithOffset(module_id)) != disconnected_layers_.end())
0714     disconnected = true;
0715   return disconnected;
0716 }
0717 
0718 unsigned HGCalTriggerGeometryV9Imp2::triggerLayer(const unsigned id) const {
0719   unsigned layer = layerWithOffset(id);
0720 
0721   if (DetId(id).det() == DetId::HGCalTrigger and
0722       HGCalTriggerDetId(id).subdet() == HGCalTriggerSubdetector::HFNoseTrigger) {
0723     if (layer >= trigger_nose_layers_.size())
0724       return 0;
0725     return trigger_nose_layers_[layer];
0726   }
0727   if (layer >= trigger_layers_.size())
0728     return 0;
0729   return trigger_layers_[layer];
0730 }
0731 
0732 bool HGCalTriggerGeometryV9Imp2::validCell(unsigned cell_id) const {
0733   bool is_valid = false;
0734   unsigned det = DetId(cell_id).det();
0735   switch (det) {
0736     case DetId::HGCalEE:
0737       is_valid = eeTopology().valid(cell_id);
0738       break;
0739     case DetId::HGCalHSi:
0740       is_valid = hsiTopology().valid(cell_id);
0741       break;
0742     case DetId::HGCalHSc:
0743       is_valid = hscTopology().valid(cell_id);
0744       break;
0745     case DetId::Forward:
0746       is_valid = noseTopology().valid(cell_id);
0747       break;
0748     default:
0749       is_valid = false;
0750       break;
0751   }
0752   return is_valid;
0753 }
0754 
0755 bool HGCalTriggerGeometryV9Imp2::validTriggerCellFromCells(const unsigned trigger_cell_id) const {
0756   // Check the validity of a trigger cell with the
0757   // validity of the cells. One valid cell in the
0758   // trigger cell is enough to make the trigger cell
0759   // valid.
0760   const geom_set cells = getCellsFromTriggerCell(trigger_cell_id);
0761   bool is_valid = false;
0762   for (const auto cell_id : cells) {
0763     unsigned det = DetId(cell_id).det();
0764     is_valid |= validCellId(det, cell_id);
0765     if (is_valid)
0766       break;
0767   }
0768   return is_valid;
0769 }
0770 
0771 bool HGCalTriggerGeometryV9Imp2::validCellId(unsigned subdet, unsigned cell_id) const {
0772   bool is_valid = false;
0773   switch (subdet) {
0774     case DetId::HGCalEE:
0775       is_valid = eeTopology().valid(cell_id);
0776       break;
0777     case DetId::HGCalHSi:
0778       is_valid = hsiTopology().valid(cell_id);
0779       break;
0780     case DetId::HGCalHSc:
0781       is_valid = hscTopology().valid(cell_id);
0782       break;
0783     case DetId::Forward:
0784       is_valid = noseTopology().valid(cell_id);
0785       break;
0786     default:
0787       is_valid = false;
0788       break;
0789   }
0790   return is_valid;
0791 }
0792 
0793 int HGCalTriggerGeometryV9Imp2::detIdWaferType(unsigned det, unsigned layer, short waferU, short waferV) const {
0794   int wafer_type = 0;
0795   switch (det) {
0796     case DetId::HGCalEE:
0797       wafer_type = eeTopology().dddConstants().getTypeHex(layer, waferU, waferV);
0798       break;
0799     case DetId::HGCalHSi:
0800       wafer_type = hsiTopology().dddConstants().getTypeHex(layer, waferU, waferV);
0801       break;
0802     default:
0803       break;
0804   };
0805   return wafer_type;
0806 }
0807 
0808 unsigned HGCalTriggerGeometryV9Imp2::layerWithOffset(unsigned id) const {
0809   unsigned det = DetId(id).det();
0810   unsigned layer = 0;
0811 
0812   if (det == DetId::HGCalTrigger) {
0813     unsigned subdet = HGCalTriggerDetId(id).subdet();
0814     if (subdet == HGCalTriggerSubdetector::HGCalEETrigger) {
0815       layer = HGCalTriggerDetId(id).layer();
0816     } else if (subdet == HGCalTriggerSubdetector::HGCalHSiTrigger) {
0817       layer = heOffset_ + HGCalTriggerDetId(id).layer();
0818     } else if (subdet == HGCalTriggerSubdetector::HFNoseTrigger) {
0819       layer = HFNoseTriggerDetId(id).layer();
0820     }
0821   } else if (det == DetId::HGCalHSc) {
0822     layer = heOffset_ + HGCScintillatorDetId(id).layer();
0823   } else if (det == DetId::Forward) {
0824     unsigned subdet = HGCalDetId(id).subdetId();
0825     if (subdet == ForwardSubdetector::HGCEE) {
0826       layer = HGCalDetId(id).layer();
0827     } else if (subdet == ForwardSubdetector::HGCHEF || subdet == ForwardSubdetector::HGCHEB) {
0828       layer = heOffset_ + HGCalDetId(id).layer();
0829     } else if (subdet == ForwardSubdetector::HFNose) {
0830       layer = HFNoseDetId(id).layer();
0831     }
0832   }
0833   return layer;
0834 }
0835 
0836 HGCalTriggerGeometryBase::geom_set HGCalTriggerGeometryV9Imp2::getStage1FpgasFromStage2Fpga(const unsigned) const {
0837   geom_set stage1_ids;
0838   return stage1_ids;
0839 }
0840 
0841 HGCalTriggerGeometryBase::geom_set HGCalTriggerGeometryV9Imp2::getStage2FpgasFromStage1Fpga(const unsigned) const {
0842   geom_set stage2_ids;
0843   return stage2_ids;
0844 }
0845 
0846 HGCalTriggerGeometryBase::geom_set HGCalTriggerGeometryV9Imp2::getStage1LinksFromStage2Fpga(const unsigned) const {
0847   geom_set stage1link_ids;
0848   return stage1link_ids;
0849 }
0850 
0851 unsigned HGCalTriggerGeometryV9Imp2::getStage1FpgaFromStage1Link(const unsigned) const {
0852   unsigned stage1_id = 0;
0853   return stage1_id;
0854 }
0855 
0856 unsigned HGCalTriggerGeometryV9Imp2::getStage2FpgaFromStage1Link(const unsigned) const {
0857   unsigned stage2_id = 0;
0858   return stage2_id;
0859 }
0860 
0861 HGCalTriggerGeometryBase::geom_set HGCalTriggerGeometryV9Imp2::getStage1LinksFromStage1Fpga(const unsigned) const {
0862   geom_set stage1link_ids;
0863   return stage1link_ids;
0864 }
0865 
0866 std::vector<unsigned> HGCalTriggerGeometryV9Imp2::getLpgbtsFromStage1Fpga(const unsigned) const {
0867   std::vector<unsigned> lpgbt_ids;
0868   return lpgbt_ids;
0869 }
0870 
0871 unsigned HGCalTriggerGeometryV9Imp2::getStage1FpgaFromLpgbt(const unsigned) const {
0872   unsigned stage1_id = 0;
0873   return stage1_id;
0874 }
0875 
0876 HGCalTriggerGeometryBase::geom_set HGCalTriggerGeometryV9Imp2::getModulesFromLpgbt(const unsigned) const {
0877   geom_set modules;
0878   return modules;
0879 }
0880 
0881 HGCalTriggerGeometryBase::geom_set HGCalTriggerGeometryV9Imp2::getLpgbtsFromModule(const unsigned) const {
0882   geom_set lpgbt_ids;
0883   return lpgbt_ids;
0884 }
0885 
0886 unsigned HGCalTriggerGeometryV9Imp2::getStage1FpgaFromModule(const unsigned) const {
0887   unsigned stage1_id = 0;
0888   return stage1_id;
0889 }
0890 
0891 DEFINE_EDM_PLUGIN(HGCalTriggerGeometryFactory, HGCalTriggerGeometryV9Imp2, "HGCalTriggerGeometryV9Imp2");