OrbitCollection

Macros

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
#ifndef DataFormats_L1Scouting_OrbitCollection_h
#define DataFormats_L1Scouting_OrbitCollection_h

#include "DataFormats/Common/interface/CMS_CLASS_VERSION.h"
#include "FWCore/MessageLogger/interface/MessageLogger.h"

#include <cstdint>
#include <span>
#include <vector>

template <class T>
class OrbitCollection {
public:
  typedef typename std::vector<T>::iterator iterator;
  typedef typename std::vector<T>::const_iterator const_iterator;
  typedef T value_type;
  typedef typename std::vector<T>::size_type size_type;

  // Initialize the offset vector with 0s from 0 to 3565.
  // BX range is [1,3564], an extra entry is needed for the offserts of the last BX
  OrbitCollection() : bxOffsets_(orbitBufferSize_ + 1, 0), data_(0) {}
  // Construct the flat orbit collection starting from an OrbitBuffer.
  // The method fillAndClear will be used, meaning that, after copying the objects,
  // orbitBuffer's vectors will be cleared.
  OrbitCollection(std::vector<std::vector<T>>& orbitBuffer, unsigned nObjects = 0)
      : bxOffsets_(orbitBufferSize_ + 1, 0), data_(nObjects) {
    fillAndClear(orbitBuffer, nObjects);
  }

  OrbitCollection(const OrbitCollection& other) = default;
  OrbitCollection(OrbitCollection&& other) = default;
  OrbitCollection& operator=(const OrbitCollection& other) = default;
  OrbitCollection& operator=(OrbitCollection&& other) = default;

  // Fill the orbit collection starting from a vector of vectors, one per BX.
  // Objects are copied into a flat data vector, and a second vector is used to keep track
  // of the starting index in the data vector for every BX.
  // After the copy, the original input buffer is cleared.
  // Input vector must be sorted with increasing BX and contain 3565 elements (BX in [1,3564])
  void fillAndClear(std::vector<std::vector<T>>& orbitBuffer, unsigned nObjects = 0) {
    if (orbitBuffer.size() != orbitBufferSize_)
      throw cms::Exception("OrbitCollection::fillAndClear")
          << "Trying to fill the collection by passing an orbit buffer with incorrect size. "
          << "Passed " << orbitBuffer.size() << ", expected 3565";
    data_.reserve(nObjects);
    bxOffsets_[0] = 0;
    unsigned bxIdx = 1;
    for (auto& bxVec : orbitBuffer) {
      // increase offset by the currect vec size
      bxOffsets_[bxIdx] = bxOffsets_[bxIdx - 1] + bxVec.size();

      // if bxVec contains something, copy it into the data_ vector
      // and clear original bxVec objects
      if (bxVec.size() > 0) {
        data_.insert(data_.end(), bxVec.begin(), bxVec.end());
        bxVec.clear();
      }

      // increment bx index
      bxIdx++;
    }
  }

  // iterate over all elements contained in data
  const_iterator begin() const { return data_.begin(); }
  const_iterator end() const { return data_.end(); }

  // iterate over elements of a bx
  std::span<const T> bxIterator(unsigned bx) const {
    if (bx >= orbitBufferSize_)
      throw cms::Exception("OrbitCollection::bxIterator") << "Trying to access and object outside the orbit range. "
                                                          << " BX = " << bx;
    if (getBxSize(bx) > 0) {
      return std::span<const T>(data_.begin() + bxOffsets_[bx], data_.begin() + bxOffsets_[bx + 1]);
    } else {
      return std::span<const T>();
    }
  }

  // get number of objects stored in a BX
  unsigned getBxSize(unsigned bx) const {
    if (bx >= orbitBufferSize_) {
      cms::Exception("OrbitCollection") << "Called getBxSize() of a bx out of the orbit range."
                                        << " BX = " << bx;
      return 0;
    }
    return bxOffsets_[bx + 1] - bxOffsets_[bx];
  }

  // get i-th object from BX
  const T& getBxObject(unsigned bx, unsigned i) const {
    if (bx >= orbitBufferSize_)
      throw cms::Exception("OrbitCollection::getBxObject") << "Trying to access and object outside the orbit range. "
                                                           << " BX = " << bx;
    if (i >= getBxSize(bx))
      throw cms::Exception("OrbitCollection::getBxObject")
          << "Trying to get element " << i << " but for"
          << " BX = " << bx << " there are " << getBxSize(bx) << " elements.";

    return data_[bxOffsets_[bx] + i];
  }

  // get the list of non empty BXs
  std::vector<unsigned> getFilledBxs() const {
    std::vector<unsigned> filledBxVec;
    if (!data_.empty()) {
      for (unsigned bx = 0; bx < orbitBufferSize_; bx++) {
        if ((bxOffsets_[bx + 1] - bxOffsets_[bx]) > 0)
          filledBxVec.push_back(bx);
      }
    }
    return filledBxVec;
  }

  int size() const { return data_.size(); }

  T& operator[](std::size_t i) { return data_[i]; }
  const T& operator[](std::size_t i) const { return data_[i]; }

  // used by ROOT storage
  CMS_CLASS_VERSION(3)

private:
  // store data vector and BX offsets as flat vectors.
  // offset contains one entry per BX, indicating the starting index
  // of the objects for that BX.
  std::vector<unsigned> bxOffsets_;
  std::vector<T> data_;

  // there are 3564 BX in one orbtit [1,3564], one extra
  // count added to keep first entry of the vector
  static constexpr int orbitBufferSize_ = 3565;
};

#endif  // DataFormats_L1Scouting_OrbitCollection_h