Back to home page

Project CMSSW displayed by LXR

 
 

    


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

0001 // -*- C++ -*-
0002 //
0003 // Package:    BSCTrigger
0004 // Class:      BSCTrigger
0005 //
0006 /**\class BSCTrigger BSCTrigger.cc L1TriggerOffline/BSCTriggerSimulation/src/BSCTrigger.cc
0007 
0008 Description: <one line class summary>
0009 
0010 Implementation:
0011 <Notes on implementation>
0012 */
0013 //
0014 // Original Author:  Muriel VANDER DONCKT *:0
0015 //         Created:  Wed Jul 16 16:11:05 CEST 2008
0016 //
0017 //
0018 
0019 // system include files
0020 #include <memory>
0021 
0022 // user include files
0023 #include "FWCore/Framework/interface/Frameworkfwd.h"
0024 #include "FWCore/Framework/interface/global/EDProducer.h"
0025 
0026 #include "FWCore/Framework/interface/Event.h"
0027 #include "FWCore/Framework/interface/MakerMacros.h"
0028 
0029 #include "FWCore/ParameterSet/interface/ParameterSet.h"
0030 #include "SimDataFormats/TrackingHit/interface/PSimHitContainer.h"
0031 #include "DataFormats/L1GlobalTrigger/interface/L1GtTechnicalTrigger.h"
0032 #include "DataFormats/L1GlobalTrigger/interface/L1GtTechnicalTriggerRecord.h"
0033 #include "FWCore/Utilities/interface/InputTag.h"
0034 #include "FWCore/Utilities/interface/EDGetToken.h"
0035 #include "FWCore/Utilities/interface/EDPutToken.h"
0036 
0037 #include "SimDataFormats/CrossingFrame/interface/CrossingFrame.h"
0038 #include "SimDataFormats/CrossingFrame/interface/MixCollection.h"
0039 
0040 //
0041 // class declaration
0042 //
0043 
0044 class BSCTrigger : public edm::global::EDProducer<> {
0045 public:
0046   explicit BSCTrigger(const edm::ParameterSet&);
0047   ~BSCTrigger() override;
0048 
0049 private:
0050   void produce(edm::StreamID, edm::Event&, const edm::EventSetup&) const override;
0051   int getBSCNum(int id, float z) const;
0052   bool isInner(int id) const;
0053   bool isZplus(int id) const;
0054   // ----------member data ---------------------------
0055   const std::vector<unsigned> ttBits_;
0056   const std::vector<std::string> names_;
0057   const double theCoincidence_;
0058   const double theResolution_;
0059   const edm::EDGetTokenT<CrossingFrame<PSimHit>> theHitsToken_;
0060   const edm::EDPutTokenT<L1GtTechnicalTriggerRecord> thePutToken_;
0061 };
0062 
0063 //
0064 // constants, enums and typedefs
0065 //
0066 
0067 //
0068 // static data member definitions
0069 //
0070 
0071 //
0072 // constructors and destructor
0073 //
0074 BSCTrigger::BSCTrigger(const edm::ParameterSet& iConfig)
0075     : ttBits_{iConfig.getParameter<std::vector<unsigned>>("bitNumbers")},
0076       names_{iConfig.getParameter<std::vector<std::string>>("bitNames")},
0077       theCoincidence_{iConfig.getParameter<double>("coincidence")},
0078       theResolution_{iConfig.getParameter<double>("resolution")},
0079       theHitsToken_{consumes<CrossingFrame<PSimHit>>(iConfig.getParameter<edm::InputTag>("theHits"))},
0080       thePutToken_{produces<L1GtTechnicalTriggerRecord>()} {}
0081 
0082 BSCTrigger::~BSCTrigger() {
0083   // do anything here that needs to be done at desctruction time
0084   // (e.g. close files, deallocate resources etc.)
0085 }
0086 
0087 //
0088 // member functions
0089 //
0090 
0091 // ------------ method called to produce the data  ------------
0092 void BSCTrigger::produce(edm::StreamID, edm::Event& iEvent, const edm::EventSetup& iSetup) const {
0093   std::vector<L1GtTechnicalTrigger> ttVec(ttBits_.size());
0094 
0095   edm::Handle<CrossingFrame<PSimHit>> cf;
0096   iEvent.getByToken(theHitsToken_, cf);
0097 
0098   if (!cf.failedToGet()) {
0099     std::vector<float> EnergyBX(32);
0100     std::vector<float> EnergyBXMinusDt(32);
0101 
0102     for (int c = 0; c < 32; ++c) {
0103       EnergyBX[c] = 0;
0104       EnergyBXMinusDt[c] = 0;
0105     }
0106     MixCollection<PSimHit> theBSCHitContainer(cf.product());
0107     const float dt1 = theCoincidence_ / 2 + theResolution_;
0108     const float dt2 = theCoincidence_ / 2 - theResolution_;
0109     if (edm::isDebugEnabled())
0110       LogDebug("BSCTrig") << " ----------------new event ---with " << theBSCHitContainer.size() << " hits in the BSC";
0111 
0112     // collect total deposited energy in BSC segments -> EnergyBX[segment id], in GeV units ---------------------------------------------------------------
0113     for (auto itHit = theBSCHitContainer.begin(); itHit != theBSCHitContainer.end(); ++itHit) {
0114       float zh = itHit->entryPoint().z() / 10;
0115       int id = getBSCNum(itHit->detUnitId(), zh);
0116       if (id > 31)
0117         continue;  // the small 2 paddles further from the IP
0118       float t = itHit->timeOfFlight();
0119 
0120       if (edm::isDebugEnabled()) {
0121         float rh = sqrt(itHit->entryPoint().x() * itHit->entryPoint().x() +
0122                         itHit->entryPoint().y() * itHit->entryPoint().y()) /
0123                    10;
0124         LogTrace("BSCTrig") << " BSC Num " << id << " z=" << zh << " isZplus=" << isZplus(id)
0125                             << " Hit DetId=" << getBSCNum(id, zh) << " r=" << rh << " isInner=" << isInner(id);
0126         LogTrace("BSCTrig") << " Hit time=" << t << " accepted range=[" << dt2 << "," << dt1 << "] from a "
0127                             << abs(itHit->particleType()) << " with energy " << itHit->energyLoss();
0128       }
0129       if (fabs(t) > dt1 || fabs(t) < dt2)
0130         continue;
0131       if (t > 0)
0132         EnergyBX[id] += itHit->energyLoss();
0133       else
0134         EnergyBXMinusDt[id] += itHit->energyLoss();
0135     }
0136 
0137     // count number of segments hit in inner/outer and +z, -z ---------------------------------------------------------------------------------------------
0138     int ZMinnerBX = 0, ZMouterBX = 0;
0139     int ZPinnerBX = 0, ZPouterBX = 0;
0140     int ZMinnerBXMinusDt = 0, ZMouterBXMinusDt = 0;
0141     int ZPinnerBXMinusDt = 0, ZPouterBXMinusDt = 0;
0142 
0143     constexpr float MipFraction = 0.5;
0144     constexpr float MipEnergy = 0.0027;
0145     constexpr float theThreshold = MipFraction * MipEnergy;
0146     for (unsigned int ipad = 0; ipad < 32; ipad++) {
0147       if (edm::isDebugEnabled())
0148         LogTrace("BSCTrig") << " EnergyBX[" << ipad << "]=" << EnergyBX[ipad];
0149       // hits after the bunch crossing
0150       if (EnergyBX[ipad] > theThreshold) {
0151         if (isZplus(ipad)) {
0152           if (isInner(ipad))
0153             ZPinnerBX++;
0154           else
0155             ZPouterBX++;
0156         } else {
0157           if (isInner(ipad))
0158             ZMinnerBX++;
0159           else
0160             ZMouterBX++;
0161         }
0162       }
0163       // hits before the bunch crossing
0164       if (EnergyBXMinusDt[ipad] > theThreshold) {
0165         if (isZplus(ipad)) {
0166           if (isInner(ipad))
0167             ZPinnerBXMinusDt++;
0168           else
0169             ZPouterBXMinusDt++;
0170         } else {
0171           if (isInner(ipad))
0172             ZMinnerBXMinusDt++;
0173           else
0174             ZMouterBXMinusDt++;
0175         }
0176       }
0177     }
0178 
0179     if (edm::isDebugEnabled())
0180       LogTrace("BSCTrig") << " Zplus I=" << ZPinnerBX << " Zminus I=" << ZMinnerBX << " Zplus O=" << ZPouterBX
0181                           << "  Zminus O=" << ZMouterBX;
0182 
0183     // minimum bias technical triggers that are also connected to 'external condition' triggers -----------------
0184     bool bit32 = false;  // min bias inner >=1
0185     if (ZPinnerBX >= 1 && ZMinnerBX >= 1)
0186       bit32 = true;
0187 
0188     bool bit33 = false;  // min bias inner >=2
0189     if (ZPinnerBX >= 2 && ZMinnerBX >= 2)
0190       bit33 = true;
0191 
0192     bool bit34 = false;  // min bias OR
0193     if (ZPinnerBX + ZMinnerBX + ZPouterBX + ZMouterBX >= 1)
0194       bit34 = true;
0195 
0196     bool bit35 = false;  // high multiplicity
0197     if (ZPinnerBX == 8 && ZMinnerBX == 8)
0198       bit35 = true;
0199 
0200     // beam halo technical triggers ----------------------------------------------------------------
0201     bool bit36 = false;  // beam 2 halo inner
0202     if (ZPinnerBX >= 1 && ZMinnerBXMinusDt >= 1)
0203       bit36 = true;
0204 
0205     bool bit37 = false;  // beam 2 halo outer
0206     if (ZPouterBX >= 1 && ZMouterBXMinusDt >= 1)
0207       bit37 = true;
0208 
0209     bool bit38 = false;  // beam 1 halo inner
0210     if (ZMinnerBX >= 1 && ZPinnerBXMinusDt >= 1)
0211       bit38 = true;
0212 
0213     bool bit39 = false;  // beam 1 halo outer
0214     if (ZMouterBX >= 1 && ZPouterBXMinusDt >= 1)
0215       bit39 = true;
0216 
0217     // minimum bias technical triggers ---------------------------------------------------------
0218     bool bit40 = false;  // min bias all >=1
0219     if (ZPinnerBX + ZPouterBX >= 1 && ZMinnerBX + ZMouterBX >= 1)
0220       bit40 = true;
0221 
0222     bool bit41 = false;  // min bias all >=2
0223     if (ZPinnerBX + ZPouterBX >= 2 && ZMinnerBX + ZMouterBX >= 2)
0224       bit41 = true;
0225 
0226     bool bit42 = false;  // beam 1 splash (-z)
0227     if (ZMinnerBX >= 2)
0228       bit42 = true;
0229 
0230     bool bit43 = false;  // beam 2 splash (+z)
0231     if (ZPinnerBX >= 2)
0232       bit43 = true;
0233 
0234     for (unsigned i = 0; i < ttBits_.size(); ++i) {
0235       bool bit = false;
0236       if (names_.at(i) == names_[0])
0237         bit = bit32;
0238       if (names_.at(i) == names_[1])
0239         bit = bit33;
0240       if (names_.at(i) == names_[2])
0241         bit = bit34;
0242       if (names_.at(i) == names_[3])
0243         bit = bit35;
0244       if (names_.at(i) == names_[4])
0245         bit = bit36;
0246       if (names_.at(i) == names_[5])
0247         bit = bit37;
0248       if (names_.at(i) == names_[6])
0249         bit = bit38;
0250       if (names_.at(i) == names_[7])
0251         bit = bit39;
0252       if (names_.at(i) == names_[8])
0253         bit = bit40;
0254       if (names_.at(i) == names_[9])
0255         bit = bit41;
0256       if (names_.at(i) == names_[10])
0257         bit = bit42;
0258       if (names_.at(i) == names_[11])
0259         bit = bit43;
0260       ttVec.at(i) = L1GtTechnicalTrigger(names_.at(i), ttBits_.at(i), 0, bit);
0261       if (edm::isDebugEnabled())
0262         LogTrace("AnaBsc") << "bit: " << ttBits_[i] << " VALUE:" << bit;
0263     }
0264   } else
0265     ttVec.clear();
0266   L1GtTechnicalTriggerRecord output;
0267   output.setGtTechnicalTrigger(ttVec);
0268   iEvent.emplace(thePutToken_, std::move(output));
0269 }
0270 int BSCTrigger::getBSCNum(int id, float z) const {
0271   int zside = 0;
0272   if (z > 0)
0273     zside = 1;
0274   if (edm::isDebugEnabled()) {
0275     int det = (id & 24) >> 3;
0276     int station = id & 7;
0277     LogTrace("BSCTrig") << "id=" << id << " zside=" << zside << " det=" << det << " station=" << station;
0278   }
0279   int BSCNum;
0280   if (id & 16)
0281     BSCNum = 32 + (id & 1) + (zside << 1);  // small paddles further from IP
0282   else
0283     BSCNum = (id & 15) + (zside << 4);  // the BSC on the HF
0284   return BSCNum;
0285 }
0286 
0287 bool BSCTrigger::isInner(int id) const { return ((id & 8) >> 3); }
0288 
0289 bool BSCTrigger::isZplus(int id) const { return ((id & 16) >> 4); }
0290 
0291 //define this as a plug-in
0292 DEFINE_FWK_MODULE(BSCTrigger);