Skip to content

Commit

Permalink
Merge pull request #14885 from emiglior/phase2ITPixelCluster_cmssw_81…
Browse files Browse the repository at this point in the history
…X_from_newIB

Add phase2 Inner Tracker (IT) pixel cluster to cmssw 81X from new IB
  • Loading branch information
cmsbuild committed Jul 20, 2016
2 parents 1d8f0b9 + 030499c commit 6b27034
Show file tree
Hide file tree
Showing 25 changed files with 2,309 additions and 3 deletions.
5 changes: 5 additions & 0 deletions DataFormats/Phase2ITPixelCluster/BuildFile.xml
@@ -0,0 +1,5 @@
<use name="DataFormats/Common"/>
<use name="rootrflx"/>
<export>
<lib name="1"/>
</export>
10 changes: 10 additions & 0 deletions DataFormats/Phase2ITPixelCluster/README.md
@@ -0,0 +1,10 @@
2016.06 EMigliore+ATricomi (INFN)

DataFormat/Phase2ITPixelCluster: class for clusters made of SiPixelDigis produced by the
phase II PixelDigitizerAlgorithm (InnerPixels)

The new data format is essentially a clone of the present DataFormats/SiPixelCluster
with modifications to the type of some data members to span the full module in case of small pitch pixels
(e.g. pixel with column or row index larger than 2**8-1=255)

The EDProducer is in RecoLocalTracker/Phase2ITPixelClusterizer
268 changes: 268 additions & 0 deletions DataFormats/Phase2ITPixelCluster/interface/Phase2ITPixelCluster.h
@@ -0,0 +1,268 @@
#ifndef DataFormats_Phase2ITPixelCluster_Phase2ITPixelCluster_h
#define DataFormats_Phase2ITPixelCluster_Phase2ITPixelCluster_h

//---------------------------------------------------------------------------
//! \class Phase2ITPixelCluster
//! \brief Pixel cluster -- collection of neighboring pixels above threshold
//!
//! Class to contain and store all the topological information of pixel clusters:
//! charge, global size, size and the barycenter in x and y
//! local directions. It builds a vector of Pixel (which is
//! an inner class) and a container of channels.
//---------------------------------------------------------------------------

#include <vector>
#include "FWCore/Utilities/interface/GCC11Compatibility.h"


#include <cstdint>
#include <cassert>

class PixelDigi;

class Phase2ITPixelCluster {
public:

class Pixel {
public:
constexpr Pixel() : x(0), y(0), adc(0){} // for root
constexpr Pixel(uint32_t pix_x, uint32_t pix_y, uint32_t pix_adc) :
x(pix_x), y(pix_y), adc(pix_adc) {}
uint32_t x;
uint32_t y;
uint32_t adc;
};

//--- Integer shift in x and y directions.
class Shift {
public:
constexpr Shift( int dx, int dy) : dx_(dx), dy_(dy) {}
constexpr Shift() : dx_(0), dy_(0) {}
constexpr int dx() const { return dx_;}
constexpr int dy() const { return dy_;}
private:
int dx_;
int dy_;
};

//--- Position of a SiPixel
class PixelPos {
public:
constexpr PixelPos() : row_(0), col_(0) {}
constexpr PixelPos(int row, int col) : row_(row) , col_(col) {}
constexpr uint32_t row() const { return row_;}
constexpr uint32_t col() const { return col_;}
constexpr PixelPos operator+( const Shift& shift) const {
return PixelPos( row() + shift.dx(), col() + shift.dy());
}
private:
uint32_t row_;
uint32_t col_;
};

typedef std::vector<PixelDigi>::const_iterator PixelDigiIter;
typedef std::pair<PixelDigiIter,PixelDigiIter> PixelDigiRange;

static constexpr unsigned int POSBITS=20;
static constexpr unsigned int SPANBITS=12;
static constexpr unsigned int MAXSPAN=127;
static constexpr unsigned int MAXPOS=2047;

/** Construct from a range of digis that form a cluster and from
* a DetID. The range is assumed to be non-empty.
*/

Phase2ITPixelCluster() : thePixelRow(MAXPOS), thePixelCol(MAXPOS), err_x(-99999.9), err_y(-99999.9) {} // needed by many....

Phase2ITPixelCluster(unsigned int isize, uint32_t const * adcs,
uint32_t const * xpos, uint32_t const * ypos,
uint32_t const xmin, uint32_t const ymin) :
thePixelOffset(2*isize), thePixelADC(adcs,adcs+isize), err_x(-99999.9), err_y(-99999.9) {
uint32_t maxCol = 0;
uint32_t maxRow = 0;
for (unsigned int i=0; i!=isize; ++i) {
uint32_t xoffset = xpos[i]-xmin;
uint32_t yoffset = ypos[i]-ymin;
thePixelOffset[i*2] = std::min(uint32_t(MAXSPAN),xoffset);
thePixelOffset[i*2+1] = std::min(uint32_t(MAXSPAN),yoffset);
if (xoffset > maxRow) maxRow = xoffset;
if (yoffset > maxCol) maxCol = yoffset;
}
packRow(xmin,maxRow);
packCol(ymin,maxCol);
}


// obsolete (only for regression tests)
Phase2ITPixelCluster( const PixelPos& pix, uint32_t adc);
void add( const PixelPos& pix, uint32_t adc);

// Analog linear average position (barycenter)
float x() const {
float qm = 0.0;
int isize = thePixelADC.size();
for (int i=0; i<isize; ++i)
qm += float(thePixelADC[i]) * (thePixelOffset[i*2] + minPixelRow() + 0.5f);
return qm/charge();
}

float y() const {
float qm = 0.0;
int isize = thePixelADC.size();
for (int i=0; i<isize; ++i)
qm += float(thePixelADC[i]) * (thePixelOffset[i*2+1] + minPixelCol() + 0.5f);
return qm/charge();
}

// Return number of pixels.
int size() const { return thePixelADC.size();}

// Return cluster dimension in the x direction.
int sizeX() const {verifyVersion(); return rowSpan() +1;}

// Return cluster dimension in the y direction.
int sizeY() const {verifyVersion(); return colSpan() +1;}


inline float charge() const {
float qm = 0.0;
int isize = thePixelADC.size();
for (int i=0; i<isize; ++i)
qm += float(thePixelADC[i]);
return qm;
} // Return total cluster charge.

inline uint32_t minPixelRow() const { return thePixelRow&MAXPOS;} // The min x index.
inline uint32_t maxPixelRow() const { verifyVersion(); return minPixelRow() + rowSpan();} // The max x index.
inline uint32_t minPixelCol() const { return thePixelCol&MAXPOS;} // The min y index.
inline uint32_t maxPixelCol() const { verifyVersion(); return minPixelCol() + colSpan();} // The max y index.


const std::vector<uint16_t> & pixelOffset() const { return thePixelOffset;}
const std::vector<uint32_t> & pixelADC() const { return thePixelADC;}

// obsolete, use single pixel access below
const std::vector<Pixel> pixels() const {
std::vector<Pixel> oldPixVector;
int isize = thePixelADC.size();
oldPixVector.reserve(isize);
for(int i=0; i<isize; ++i) {
oldPixVector.push_back(pixel(i));
}
return oldPixVector;
}

// infinite faster than above...
Pixel pixel(int i) const {
return Pixel(minPixelRow() + thePixelOffset[i*2],
minPixelCol() + thePixelOffset[i*2+1],
thePixelADC[i]
);
}

private:

static int span_(uint32_t packed) { return packed >> POSBITS;}
static int overflow_(uint32_t packed) { return span_(packed)==uint32_t(MAXSPAN);}
static uint32_t pack_(uint32_t zmin, unsigned int zspan) {
zspan = std::min(zspan, uint32_t(MAXSPAN));
return (zspan<<POSBITS) | zmin;
}
public:

int colSpan() const {return span_(thePixelCol); }

int rowSpan() const { return span_(thePixelRow); }


bool overflowCol() const { return overflow_(thePixelCol); }

bool overflowRow() const { return overflow_(thePixelRow); }

bool overflow() const { return overflowCol() || overflowRow(); }

void packCol(uint32_t ymin, uint32_t yspan) {
thePixelCol = pack_(ymin,yspan);
}
void packRow(uint32_t xmin, uint32_t xspan) {
thePixelRow = pack_(xmin,xspan);
}



/// mostly to be compatible for <610
void verifyVersion() const {
if unlikely( thePixelRow<MAXPOS && thePixelCol<MAXPOS)
const_cast<Phase2ITPixelCluster*>(this)->computeMax();
}

/// moslty to be compatible for <610
void computeMax() {
int maxRow = 0;
int maxCol = 0;
int isize = thePixelADC.size();
for (int i=0; i!=isize; ++i) {
int xsize = thePixelOffset[i*2];
if (xsize > maxRow) maxRow = xsize;
int ysize = thePixelOffset[i*2+1] ;
if (ysize > maxCol) maxCol = ysize;
}
// assume minimum is correct
uint32_t minCol= minPixelCol();
packCol(minCol,maxCol);
uint32_t minRow= minPixelRow();
packRow(minRow,maxRow);
}

// Getters and setters for the newly added data members (err_x and err_y). See below.
void setSplitClusterErrorX( float errx ) { err_x = errx; }
void setSplitClusterErrorY( float erry ) { err_y = erry; }
float getSplitClusterErrorX() const { return err_x; }
float getSplitClusterErrorY() const { return err_y; }


private:

std::vector<uint16_t> thePixelOffset;
std::vector<uint32_t> thePixelADC;


uint32_t thePixelRow; // Minimum and span pixel index in the x direction (low edge).
uint32_t thePixelCol; // Minimum and span pixel index in the y direction (left edge).
// Need 10 bits for Position information. the other 6 used for span

// A rechit from a split cluster should have larger errors than rechits from normal clusters.
// However, when presented with a cluster, the CPE does not know if the cluster comes
// from a splitting procedure or not. That's why we have to instruct the CPE to use
// appropriate errors for split clusters.
float err_x;
float err_y;

};

// Comparison operators (no clue...)
inline bool operator<( const Phase2ITPixelCluster& one, const Phase2ITPixelCluster& other) {
if ( one.minPixelRow() < other.minPixelRow() ) {
return true;
} else if ( one.minPixelRow() > other.minPixelRow() ) {
return false;
} else if ( one.minPixelCol() < other.minPixelCol() ) {
return true;
} else {
return false;
}
}

#include "DataFormats/Common/interface/DetSetVector.h"
#include "DataFormats/Common/interface/DetSetVectorNew.h"
#include "DataFormats/Common/interface/Ref.h"
#include "DataFormats/Common/interface/DetSetRefVector.h"

typedef edm::DetSetVector<Phase2ITPixelCluster> Phase2ITPixelClusterCollection;
typedef edm::Ref<Phase2ITPixelClusterCollection, Phase2ITPixelCluster> Phase2ITPixelClusterRef;
typedef edm::DetSetRefVector<Phase2ITPixelCluster> Phase2ITPixelClusterRefVector;
typedef edm::RefProd<Phase2ITPixelClusterCollection> Phase2ITPixelClusterRefProd;

typedef edmNew::DetSetVector<Phase2ITPixelCluster> Phase2ITPixelClusterCollectionNew;
typedef edm::Ref<Phase2ITPixelClusterCollectionNew, Phase2ITPixelCluster> Phase2ITPixelClusterRefNew;
#endif
@@ -0,0 +1,112 @@
// -*- c++ -*-
#ifndef DataFormats_Phase2ITPixelCluster_Phase2ITPixelClusterShapeData_h
#define DataFormats_Phase2ITPixelCluster_Phase2ITPixelClusterShapeData_h

#include "DataFormats/Provenance/interface/ProductID.h"
#include "DataFormats/Common/interface/HandleBase.h"
#include "DataFormats/Common/interface/Ref.h"
#include "DataFormats/Common/interface/DetSetVectorNew.h"
#include "DataFormats/Phase2ITPixelCluster/interface/Phase2ITPixelCluster.h"

#include <utility>
#include <vector>
#include <algorithm>
#include <cassert>
#include <memory>

class PixelGeomDetUnit;

class Phase2ITPixelClusterShapeData {
public:
typedef std::vector<std::pair<int, int> >::const_iterator const_iterator;
typedef std::pair<const_iterator, const_iterator> Range;
Phase2ITPixelClusterShapeData(const_iterator begin, const_iterator end, bool isStraight, bool isComplete, bool hasBigPixelsOnlyInside):
begin_(begin), end_(end), isStraight_(isStraight), isComplete_(isComplete), hasBigPixelsOnlyInside_(hasBigPixelsOnlyInside)
{}
~Phase2ITPixelClusterShapeData();

Range size() const { return std::make_pair(begin_, end_); }

bool isStraight() const { return isStraight_; }
bool isComplete() const { return isComplete_; }
bool hasBigPixelsOnlyInside() const { return hasBigPixelsOnlyInside_; }

private:
const_iterator begin_, end_;
const bool isStraight_, isComplete_, hasBigPixelsOnlyInside_;
};

class Phase2ITPixelClusterShapeCache {
public:
typedef edm::Ref<edmNew::DetSetVector<Phase2ITPixelCluster>, Phase2ITPixelCluster> ClusterRef;

struct Field {
Field(): offset(0), size(0), straight(false), complete(false), has(false), filled(false) {}

Field(unsigned off, unsigned siz, bool s, bool c, bool h):
offset(off), size(siz), straight(s), complete(c), has(h), filled(true) {}
unsigned offset: 24; // room for 2^24/9 = ~2.8e6 clusters, should be enough
unsigned size: 4; // max 9 elements / cluster (2^4=16)
unsigned straight:1;
unsigned complete:1;
unsigned has:1;
unsigned filled:1;
};

Phase2ITPixelClusterShapeCache() {};
explicit Phase2ITPixelClusterShapeCache(const edm::HandleBase& handle): productId_(handle.id()) {}
explicit Phase2ITPixelClusterShapeCache(const edm::ProductID& id): productId_(id) {}
~Phase2ITPixelClusterShapeCache();

void resize(size_t size) {
data_.resize(size);
sizeData_.reserve(size);
}

void swap(Phase2ITPixelClusterShapeCache& other) {
data_.swap(other.data_);
sizeData_.swap(other.sizeData_);
std::swap(productId_, other.productId_);
}

#if !defined(__CINT__) && !defined(__MAKECINT__) && !defined(__REFLEX__)
void shrink_to_fit() {
data_.shrink_to_fit();
sizeData_.shrink_to_fit();
}

template <typename T>
void insert(const ClusterRef& cluster, const T& data) {
static_assert(T::ArrayType::capacity() <= 16, "T::ArrayType::capacity() more than 16, bit field too narrow");
checkRef(cluster);

data_[cluster.index()] = Field(sizeData_.size(), data.size.size(), data.isStraight, data.isComplete, data.hasBigPixelsOnlyInside);
std::copy(data.size.begin(), data.size.end(), std::back_inserter(sizeData_));
}

bool isFilled(const ClusterRef& cluster) const {
checkRef(cluster);
return data_[cluster.index()].filled;
}

Phase2ITPixelClusterShapeData get(const ClusterRef& cluster, const PixelGeomDetUnit *pixDet) const {
checkRef(cluster);
Field f = data_[cluster.index()];
assert(f.filled);

auto beg = sizeData_.begin()+f.offset;
auto end = beg+f.size;

return Phase2ITPixelClusterShapeData(beg, end, f.straight, f.complete, f.has);
}
#endif

private:
void checkRef(const ClusterRef& cluster) const;

std::vector<Field> data_;
std::vector<std::pair<int, int> > sizeData_;
edm::ProductID productId_;
};

#endif

0 comments on commit 6b27034

Please sign in to comment.