SiStripTrivialDigiSource

Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209
// system includes
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>

// user includes
#include "CLHEP/Random/RandFlat.h"
#include "CLHEP/Random/RandGauss.h"
#include "CondFormats/DataRecord/interface/SiStripFedCablingRcd.h"
#include "CondFormats/SiStripObjects/interface/SiStripFedCabling.h"
#include "DataFormats/Common/interface/DetSetVector.h"
#include "DataFormats/SiStripCommon/interface/SiStripConstants.h"
#include "DataFormats/SiStripDigi/interface/SiStripDigi.h"
#include "DataFormats/SiStripDigi/interface/SiStripRawDigi.h"
#include "FWCore/Framework/interface/ESHandle.h"
#include "FWCore/Framework/interface/Event.h"
#include "FWCore/Framework/interface/EventSetup.h"
#include "FWCore/Framework/interface/global/EDProducer.h"
#include "FWCore/MessageLogger/interface/MessageLogger.h"
#include "FWCore/ParameterSet/interface/ParameterSet.h"

/**
    @file EventFilter/SiStripRawToDigi/test/plugins/SiStripTrivialDigiSource.h
    @class SiStripTrivialDigiSource

    @brief Creates a DetSetVector of SiStripDigis created using random
    number generators and attaches the collection to the Event. Allows
    to test the final DigiToRaw and RawToDigi converters.  
*/
class SiStripTrivialDigiSource : public edm::global::EDProducer<> {
public:
  SiStripTrivialDigiSource(const edm::ParameterSet&);
  ~SiStripTrivialDigiSource();

  virtual void produce(edm::StreamID, edm::Event&, const edm::EventSetup&) const override;

private:
  const edm::ESGetToken<SiStripFedCabling, SiStripFedCablingRcd> esTokenCabling_;
  const float meanOcc_;
  const float rmsOcc_;
  const int ped_;
  const bool raw_;
  const bool useFedKey_;
};

// -----------------------------------------------------------------------------
//
SiStripTrivialDigiSource::SiStripTrivialDigiSource(const edm::ParameterSet& pset)
    : esTokenCabling_(esConsumes()),
      meanOcc_(pset.getUntrackedParameter<double>("MeanOccupancy", 1.)),
      rmsOcc_(pset.getUntrackedParameter<double>("RmsOccupancy", 0.1)),
      ped_(pset.getUntrackedParameter<int>("PedestalLevel", 100)),
      raw_(pset.getUntrackedParameter<bool>("FedRawDataMode", false)),
      useFedKey_(pset.getUntrackedParameter<bool>("UseFedKey", false)) {
  LogTrace("TrivialDigiSource") << "[SiStripTrivialDigiSource::" << __func__ << "]"
                                << " Constructing object...";
  produces<edm::DetSetVector<SiStripDigi>>();
}

// -----------------------------------------------------------------------------
//
SiStripTrivialDigiSource::~SiStripTrivialDigiSource() {
  LogTrace("TrivialDigiSource") << "[SiStripTrivialDigiSource::" << __func__ << "]"
                                << " Destructing object...";
}

// -----------------------------------------------------------------------------
//
void SiStripTrivialDigiSource::produce(edm::StreamID, edm::Event& event, const edm::EventSetup& setup) const {
  LogTrace("TrivialDigiSource") << "[SiStripRawToDigiModule::" << __func__ << "]"
                                << " Analyzing run/event " << event.id().run() << "/" << event.id().event();

  // Retrieve cabling
  edm::ESHandle<SiStripFedCabling> cabling = setup.getHandle(esTokenCabling_);

  // Temp container
  typedef std::vector<edm::DetSet<SiStripDigi>> digi_work_vector;
  digi_work_vector zero_suppr_vector;

  // Some init
  uint32_t nchans = 0;
  uint32_t ndigis = 0;

  // Retrieve fed ids
  auto fed_ids = cabling->fedIds();

  // Iterate through fed ids and channels
  for (auto ifed = fed_ids.begin(); ifed != fed_ids.end(); ifed++) {
    auto conns = cabling->fedConnections(*ifed);
    for (auto iconn = conns.begin(); iconn != conns.end(); iconn++) {
      // Build FED key
      uint32_t fed_key = ((iconn->fedId() & sistrip::invalid_) << 16) | (iconn->fedCh() & sistrip::invalid_);

      // Determine key (FED key or DetId) to index DSV
      uint32_t key = useFedKey_ ? fed_key : iconn->detId();

      // Determine APV pair number
      uint16_t ipair = useFedKey_ ? 0 : iconn->apvPairNumber();

      // Check key is non-zero and valid
      if (!key || (key == sistrip::invalid32_)) {
        continue;
      }

      // Random number of digis
      double tmp = 0.;
      float rdm = 2.56 * CLHEP::RandGauss::shoot(meanOcc_, rmsOcc_);
      bool extra = (CLHEP::RandFlat::shoot() > modf(rdm, &tmp));
      uint16_t ndigi = static_cast<uint16_t>(rdm) + static_cast<uint16_t>(extra);

      // Create DetSet
      if (zero_suppr_vector.empty()) {
        zero_suppr_vector.reserve(40000);
      }
      zero_suppr_vector.push_back(edm::DetSet<SiStripDigi>(key));
      edm::DetSet<SiStripDigi>& zs = zero_suppr_vector.back();
      zs.data.reserve(768);

      // Remember strips used
      std::vector<uint16_t> used_strips;
      used_strips.reserve(ndigi);

      // Create digis
      uint16_t idigi = 0;
      while (idigi < ndigi) {
        // Random values
        uint16_t str = static_cast<uint16_t>(256. * CLHEP::RandFlat::shoot());
        uint16_t adc = static_cast<uint16_t>(256. * CLHEP::RandFlat::shoot());

        // Generate and check strip number
        uint16_t nstrips = iconn->nDetStrips();
        uint16_t strip = str + 256 * ipair;
        if (strip >= nstrips) {
          continue;
        }

        // Create digi object
        std::vector<uint16_t>::iterator iter = find(used_strips.begin(), used_strips.end(), strip);
        if (iter == used_strips.end() && adc) {  // require non-zero adc!
          uint16_t level = raw_ ? ped_ + adc : adc;
          zs.data.push_back(SiStripDigi(strip, level));
          used_strips.push_back(strip);
          ndigis++;
          idigi++;
        }
      }

      // Populate DetSet with remaining "raw" digis
      if (raw_) {
        for (uint16_t istr = 256 * ipair; istr < 256 * (ipair + 1); ++istr) {
          if (find(used_strips.begin(), used_strips.end(), istr) == used_strips.end()) {
            zs.data.push_back(SiStripDigi(istr, ped_));
          }
        }
      }
    }
  }

  // Create final DetSetVector container
  auto collection = std::make_unique<edm::DetSetVector<SiStripDigi>>();

  // Populate final DetSetVector container with ZS data
  if (!zero_suppr_vector.empty()) {
    std::sort(zero_suppr_vector.begin(), zero_suppr_vector.end());
    std::vector<edm::DetSet<SiStripDigi>> sorted_and_merged;
    sorted_and_merged.reserve(zero_suppr_vector.size());

    edm::det_id_type old_id = 0;
    std::vector<edm::DetSet<SiStripDigi>>::iterator ii = zero_suppr_vector.begin();
    std::vector<edm::DetSet<SiStripDigi>>::iterator jj = zero_suppr_vector.end();
    for (; ii != jj; ++ii) {
      if (old_id == ii->detId()) {
        sorted_and_merged.back().data.insert(sorted_and_merged.back().end(), ii->begin(), ii->end());
      } else {
        sorted_and_merged.push_back(*ii);
        old_id = ii->detId();
      }
    }

    std::vector<edm::DetSet<SiStripDigi>>::iterator iii = sorted_and_merged.begin();
    std::vector<edm::DetSet<SiStripDigi>>::iterator jjj = sorted_and_merged.end();
    for (; iii != jjj; ++iii) {
      std::sort(iii->begin(), iii->end());
    }

    edm::DetSetVector<SiStripDigi> zero_suppr_dsv(sorted_and_merged, true);
    collection->swap(zero_suppr_dsv);
  }

  // Put collection in event
  event.put(std::move(collection));

  // Some debug
  if (edm::isDebugEnabled() && nchans) {
    std::stringstream ss;
    ss << "[SiStripTrivialDigiSource::" << __func__ << "]"
       << " Generated " << ndigis << " digis for " << nchans << " channels with a mean occupancy of " << std::dec
       << std::setprecision(2) << (1. / 2.56) * (float)ndigis / (float)nchans << " %";
    LogTrace("TrivialDigiSource") << ss.str();
  }
}

#include "FWCore/PluginManager/interface/ModuleDef.h"
#include "FWCore/Framework/interface/MakerMacros.h"
DEFINE_FWK_MODULE(SiStripTrivialDigiSource);