From 03a54fdb313fb507448327269712851bc809b3ca Mon Sep 17 00:00:00 2001 From: Sebouh Paul Date: Wed, 20 Sep 2023 03:23:41 -0400 Subject: [PATCH] Added implementation for hexagonal and cartesianXY staggered segmentation (#1161) --- .../DDSegmentation/CartesianGridXYStaggered.h | 150 ++++++++++++++++++ DDCore/include/DDSegmentation/HexGrid.h | 131 +++++++++++++++ .../CartesianGridXYStaggered.cpp | 102 ++++++++++++ DDCore/src/segmentations/HexGrid.cpp | 149 +++++++++++++++++ 4 files changed, 532 insertions(+) create mode 100644 DDCore/include/DDSegmentation/CartesianGridXYStaggered.h create mode 100644 DDCore/include/DDSegmentation/HexGrid.h create mode 100644 DDCore/src/segmentations/CartesianGridXYStaggered.cpp create mode 100644 DDCore/src/segmentations/HexGrid.cpp diff --git a/DDCore/include/DDSegmentation/CartesianGridXYStaggered.h b/DDCore/include/DDSegmentation/CartesianGridXYStaggered.h new file mode 100644 index 000000000..441026adf --- /dev/null +++ b/DDCore/include/DDSegmentation/CartesianGridXYStaggered.h @@ -0,0 +1,150 @@ +//========================================================================== +// AIDA Detector description implementation +//-------------------------------------------------------------------------- +// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN) +// All rights reserved. +// +// For the licensing terms see $DD4hepINSTALL/LICENSE. +// For the list of contributors see $DD4hepINSTALL/doc/CREDITS. +// +//========================================================================== + + + + +/* + * CartesianGridXYStaggered.h + * + * Created on: September 15, 2023 + * Author: Sebouh J. Paul, UCR + */ + +#ifndef DDSEGMENTATION_CARTESIANGRIDXYSTAGGERED_H +#define DDSEGMENTATION_CARTESIANGRIDXYSTAGGERED_H + +#include "DDSegmentation/CartesianGrid.h" + +namespace dd4hep { + namespace DDSegmentation { + + /// Segmentation base class describing cartesian grid segmentation in the X-Y plane + class CartesianGridXYStaggered: public CartesianGrid { + public: + /// Default constructor passing the encoding string + CartesianGridXYStaggered(const std::string& cellEncoding = ""); + /// Default constructor used by derived classes passing an existing decoder + CartesianGridXYStaggered(const BitFieldCoder* decoder); + /// destructor + virtual ~CartesianGridXYStaggered(); + + /// determine the position based on the cell ID + virtual Vector3D position(const CellID& cellID) const; + /// determine the cell ID based on the position + virtual CellID cellID(const Vector3D& localPosition, const Vector3D& globalPosition, const VolumeID& volumeID) const; + /// access the grid size in X + double gridSizeX() const { + return _gridSizeX; + } + /// access the grid size in Y + double gridSizeY() const { + return _gridSizeY; + } + /// access the coordinate offset in X + double offsetX() const { + return _offsetX; + } + /// access the coordinate offset in Y + double offsetY() const { + return _offsetY; + } + /// access the field name used for X + const std::string& fieldNameX() const { + return _xId; + } + /// access the field name used for Y + const std::string& fieldNameY() const { + return _yId; + } + /// access the staggering option in X + int staggerX() const { + return _staggerX; + } + /// access the staggering option in Y + int staggerY() const { + return _staggerY; + } + /// access the keyword used to determine which volumes to stagger + const std::string& staggerKeyword() const { + return _staggerKeyword; + } + /// set the grid size in X + void setGridSizeX(double cellSize) { + _gridSizeX = cellSize; + } + /// set the grid size in Y + void setGridSizeY(double cellSize) { + _gridSizeY = cellSize; + } + /// set the coordinate offset in X + void setOffsetX(double offset) { + _offsetX = offset; + } + /// set the coordinate offset in Y + void setOffsetY(double offset) { + _offsetY = offset; + } + /// set the field name used for X + void setFieldNameX(const std::string& fieldName) { + _xId = fieldName; + } + /// set the field name used for Y + void setFieldNameY(const std::string& fieldName) { + _yId = fieldName; + } + /// set the staggering option in X + void setStaggerX(int staggerX) { + _staggerX = staggerX; + } + /// set the staggering option in Y + void setStaggerY(int staggerY) { + _staggerY = staggerY; + } + /// set the keyword used to determine which volumes to stagger + void setStaggerKeyword(const std::string& staggerKeyword) { + _staggerKeyword = staggerKeyword; + } + /** \brief Returns a vector of the cellDimensions of the given cell ID + in natural order of dimensions, e.g., dx/dy/dz, or dr/r*dPhi + + Returns a vector of the cellDimensions of the given cell ID + \param cellID is ignored as all cells have the same dimension + \return std::vector size 2: + -# size in x + -# size in y + */ + virtual std::vector cellDimensions(const CellID& cellID) const; + + protected: + /// the grid size in X + double _gridSizeX; + /// the coordinate offset in X + double _offsetX; + /// staggering option in X. 0 = no staggering. 1 = stagger by _gridSizeX/2.0 in odd layers + int _staggerX; + /// the grid size in Y + double _gridSizeY; + /// the coordinate offset in Y + double _offsetY; + /// staggering option in Y. 0 = no staggering. 1 = stagger by _gridSizeY/2.0 in odd layers + int _staggerY; + /// the field name used for X + std::string _xId; + /// the field name used for Y + std::string _yId; + /// the keyword used to determine which volumes to stagger + std::string _staggerKeyword; + }; + + } /* namespace DDSegmentation */ +} /* namespace dd4hep */ +#endif // DDSEGMENTATION_CARTESIANGRIDXYSTAGGERED_H diff --git a/DDCore/include/DDSegmentation/HexGrid.h b/DDCore/include/DDSegmentation/HexGrid.h new file mode 100644 index 000000000..434177790 --- /dev/null +++ b/DDCore/include/DDSegmentation/HexGrid.h @@ -0,0 +1,131 @@ +//========================================================================== +// AIDA Detector description implementation +//-------------------------------------------------------------------------- +// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN) +// All rights reserved. +// +// For the licensing terms see $DD4hepINSTALL/LICENSE. +// For the list of contributors see $DD4hepINSTALL/doc/CREDITS. +// +//========================================================================== + +/* + * HexGrid.h + * + * Created on: August 9, 2023 + * Author: Sebouh J. Paul, UC Riverside + */ + +#ifndef DDSEGMENTATION_HEXGRID_H +#define DDSEGMENTATION_HEXGRID_H + +#include "DDSegmentation/Segmentation.h" + +namespace dd4hep { + namespace DDSegmentation { + + /// Segmentation base class describing hexagonal grid segmentation, with or without staggering + class HexGrid: public Segmentation { + public: + /// Destructor + virtual ~HexGrid(); + //protected: + /// Default constructor used by derived classes passing the encoding string + HexGrid(const std::string& cellEncoding = ""); + /// Default constructor used by derived classes passing an existing decoder + HexGrid(const BitFieldCoder* decoder); + + /// determine the position based on the cell ID + virtual Vector3D position(const CellID& cellID) const; + /// determine the cell ID based on the position + virtual CellID cellID(const Vector3D& localPosition, const Vector3D& globalPosition, const VolumeID& volumeID) const; + // access the stagger mode: 0=no stagger; 1=stagger cycling through 3 offsets + int stagger() const { + return _stagger; + } + + /// access the grid size + double sideLength() const { + return _sideLength; + } + /// access the coordinate offset in X + double offsetX() const { + return _offsetX; + } + /// access the coordinate offset in Y + double offsetY() const { + return _offsetY; + } + /// access the field name used for X + const std::string& fieldNameX() const { + return _xId; + } + /// access the field name used for Y + const std::string& fieldNameY() const { + return _yId; + } + /// access the keyword for staggering + const std::string& staggerKeyword() const { + return _staggerKeyword; + } + + /// set the stagger mode: 0=no stagger; 1=stagger cycling through 3 offsets + void setStagger(int stagger) { + _stagger= stagger; + } + /// set the grid size in X + void setSideLength(double cellSize) { + _sideLength = cellSize; + } + /// set the coordinate offset in X + void setOffsetX(double offset) { + _offsetX = offset; + } + /// set the coordinate offset in Y + void setOffsetY(double offset) { + _offsetY = offset; + } + /// set the field name used for X + void setFieldNameX(const std::string& fieldName) { + _xId = fieldName; + } + /// set the field name used for Y + void setFieldNameY(const std::string& fieldName) { + _yId = fieldName; + } + /// set the keyword used to determine which volumes to stagger + void setStaggerKeyword(const std::string& staggerKeyword) { + _staggerKeyword = staggerKeyword; + } + /** \brief Returns a vector of the cellDimensions of the given cell ID + in natural order of dimensions, e.g., dx/dy/dz, or dr/r*dPhi + + Returns a vector of the cellDimensions of the given cell ID + \param cellID is ignored as all cells have the same dimension + \return std::vector size 2: + -# size in x + -# size in y + */ + virtual std::vector cellDimensions(const CellID& cellID) const; + + protected: + /// the stagger mode: 0=off ; 1=cycle through 3 different offsets (H3) + // 2=cycle through 4 differnt offsets (H4) + int _stagger; + /// the length of one side of a hexagon + double _sideLength; + /// the coordinate offset in X + double _offsetX; + /// the coordinate offset in Y + double _offsetY; + /// the field name used for X + std::string _xId; + /// the field name used for Y + std::string _yId; + /// the keyword used to determine which volumes to stagger + std::string _staggerKeyword; + }; + + } /* namespace DDSegmentation */ +} /* namespace dd4hep */ +#endif // DDSEGMENTATION_HEXGRID_H diff --git a/DDCore/src/segmentations/CartesianGridXYStaggered.cpp b/DDCore/src/segmentations/CartesianGridXYStaggered.cpp new file mode 100644 index 000000000..871958ffe --- /dev/null +++ b/DDCore/src/segmentations/CartesianGridXYStaggered.cpp @@ -0,0 +1,102 @@ +/* + * CartesianGridXYStaggered.cpp + * + * Created on: Sept 15, 2023 + * Author: Sebouh J. Paul, UCR + */ + +#include "DDSegmentation/CartesianGridXYStaggered.h" + +namespace dd4hep { +namespace DDSegmentation { + +/// default constructor using an encoding string +CartesianGridXYStaggered::CartesianGridXYStaggered(const std::string& cellEncoding) : + CartesianGrid(cellEncoding) { + // define type and description + _type = "CartesianGridXYStaggered"; + _description = "Cartesian segmentation in the local XY-plane, with options for staggering"; + + // register all necessary parameters + registerParameter("grid_size_x", "Cell size in X", _gridSizeX, 1., SegmentationParameter::LengthUnit); + registerParameter("grid_size_y", "Cell size in Y", _gridSizeY, 1., SegmentationParameter::LengthUnit); + registerParameter("offset_x", "Cell offset in X", _offsetX, 0., SegmentationParameter::LengthUnit, true); + registerParameter("offset_y", "Cell offset in Y", _offsetY, 0., SegmentationParameter::LengthUnit, true); + registerParameter("stagger_x", "Option to stagger the layers in x (ie, add grid_size_x/2 to offset_x for odd layers)", _staggerX, 0, + SegmentationParameter::NoUnit, true); + registerParameter("stagger_y", "Option to stagger the layers in y (ie, add grid_size_y/2 to offset_y for odd layers)", _staggerY, 0, + SegmentationParameter::NoUnit, true); + registerIdentifier("identifier_x", "Cell ID identifier for X", _xId, "x"); + registerIdentifier("identifier_y", "Cell ID identifier for Y", _yId, "y"); + registerParameter("stagger_keyword", "Volume ID identifier used for determining which volumes to stagger", _staggerKeyword, (std::string)"layer", + SegmentationParameter::NoUnit, true); +} + +/// Default constructor used by derived classes passing an existing decoder +CartesianGridXYStaggered::CartesianGridXYStaggered(const BitFieldCoder* decode) : + CartesianGrid(decode) +{ + // define type and description + _type = "CartesianGridXYStaggered"; + _description = "Cartesian segmentation in the local XY-plane, with options for staggering"; + + // register all necessary parameters + registerParameter("grid_size_x", "Cell size in X", _gridSizeX, 1., SegmentationParameter::LengthUnit); + registerParameter("grid_size_y", "Cell size in Y", _gridSizeY, 1., SegmentationParameter::LengthUnit); + registerParameter("offset_x", "Cell offset in X", _offsetX, 0., SegmentationParameter::LengthUnit, true); + registerParameter("offset_y", "Cell offset in Y", _offsetY, 0., SegmentationParameter::LengthUnit, true); + registerParameter("stagger_x", "Option to stagger the layers in x (ie, add grid_size_x/2 to offset_x for odd layers)", _staggerX, 0, + SegmentationParameter::NoUnit, true); + registerParameter("stagger_y", "Option to stagger the layers in y (ie, add grid_size_y/2 to offset_y for odd layers)", _staggerY, 0, + SegmentationParameter::NoUnit, true); + registerIdentifier("identifier_x", "Cell ID identifier for X", _xId, "x"); + registerIdentifier("identifier_y", "Cell ID identifier for Y", _yId, "y"); + registerParameter("stagger_keyword", "Volume ID identifier used for determining which volumes to stagger", _staggerKeyword, (std::string)"layer", + SegmentationParameter::NoUnit, true); +} + +/// destructor +CartesianGridXYStaggered::~CartesianGridXYStaggered() { + +} + +/// determine the position based on the cell ID +Vector3D CartesianGridXYStaggered::position(const CellID& cID) const { + Vector3D cellPosition; + if (_staggerX || _staggerY){ + int layer= _decoder->get(cID,_staggerKeyword); + cellPosition.X = binToPosition( _decoder->get(cID,_xId ), _gridSizeX, _offsetX+_staggerX*_gridSizeX*(layer%2)/2.); + cellPosition.Y = binToPosition( _decoder->get(cID,_yId ), _gridSizeY, _offsetY+_staggerY*_gridSizeY*(layer%2)/2.); + } else { + cellPosition.X = binToPosition( _decoder->get(cID,_xId ), _gridSizeX, _offsetX); + cellPosition.Y = binToPosition( _decoder->get(cID,_yId ), _gridSizeY, _offsetY); + } + return cellPosition; +} + +/// determine the cell ID based on the position + CellID CartesianGridXYStaggered::cellID(const Vector3D& localPosition, const Vector3D& /* globalPosition */, const VolumeID& vID) const { + CellID cID = vID ; + if (_staggerX || _staggerY){ + int layer= _decoder->get(cID,_staggerKeyword); + _decoder->set( cID,_xId, positionToBin(localPosition.X, _gridSizeX, _offsetX+_staggerX*_gridSizeX*(layer%2)/2) ); + _decoder->set( cID,_yId, positionToBin(localPosition.Y, _gridSizeY, _offsetY+_staggerY*_gridSizeY*(layer%2)/2) ); + } else { + _decoder->set( cID,_xId, positionToBin(localPosition.X, _gridSizeX, _offsetX)); + _decoder->set( cID,_yId, positionToBin(localPosition.Y, _gridSizeY, _offsetY)); + } + return cID ; +} + + +std::vector CartesianGridXYStaggered::cellDimensions(const CellID& cellID) const { + return {_gridSizeX, _gridSizeY}; +} + + +} /* namespace DDSegmentation */ +} /* namespace dd4hep */ + +// This is done DDCore/src/plugins/ReadoutSegmentations.cpp so the plugin is not part of libDDCore +// needs also #include "DD4hep/Factories.h" +// DECLARE_SEGMENTATION(CartesianGridXYStaggered,dd4hep::create_segmentation) diff --git a/DDCore/src/segmentations/HexGrid.cpp b/DDCore/src/segmentations/HexGrid.cpp new file mode 100644 index 000000000..f051a8f61 --- /dev/null +++ b/DDCore/src/segmentations/HexGrid.cpp @@ -0,0 +1,149 @@ +/* + * AIDA Detector description implementation + * + * Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN) + * All rights reserved. + * + * For the licensing terms see $DD4hepINSTALL/LICENSE. + * For the list of contributors see $DD4hepINSTALL/doc/CREDITS. + * + * HexGrid.cpp + * + * Created on: August 9, 2023 + * Author: Sebouh J. Paul, UC Riverside + */ +#include "DD4hep/Factories.h" +#include "DDSegmentation/HexGrid.h" + +namespace dd4hep { + namespace DDSegmentation { + + /// Default constructor used by derived classes passing the encoding string + HexGrid::HexGrid(const std::string& cellEncoding) : + Segmentation(cellEncoding) { + _type = "HexGridXY"; + _description = "Hexagonal segmentation in the local XY-plane"; + + // register all necessary parameters + registerParameter("stagger", "stagger mode", _stagger, 1); + registerParameter("side_length", "Cell size", _sideLength, 1., SegmentationParameter::LengthUnit); + registerParameter("offset_x", "Cell offset in X", _offsetX, 0., SegmentationParameter::LengthUnit, true); + registerParameter("offset_y", "Cell offset in Y", _offsetY, 0., SegmentationParameter::LengthUnit, true); + registerIdentifier("identifier_x", "Cell ID identifier for X", _xId, "x"); + registerIdentifier("identifier_y", "Cell ID identifier for Y", _yId, "y"); + registerParameter("stagger_keyword", "Volume ID identifier used for determining which volumes to stagger", _staggerKeyword, (std::string)"layer", SegmentationParameter::NoUnit, true); + } + + /// Default constructor used by derived classes passing an existing decoder + HexGrid::HexGrid(const BitFieldCoder* decode) : Segmentation(decode) { + // define type and description + _type = "HexGridXY"; + _description = "Hexagonal segmentation in the local XY-plane"; + + // register all necessary parameters + registerParameter("stagger", "stagger mode", _stagger, 1); + registerParameter("side_length", "Cell size", _sideLength, 1., SegmentationParameter::LengthUnit); + registerParameter("offset_x", "Cell offset in X", _offsetX, 0., SegmentationParameter::LengthUnit, true); + registerParameter("offset_y", "Cell offset in Y", _offsetY, 0., SegmentationParameter::LengthUnit, true); + registerIdentifier("identifier_x", "Cell ID identifier for X", _xId, "x"); + registerIdentifier("identifier_y", "Cell ID identifier for Y", _yId, "y"); + registerParameter("stagger_keyword", "Volume ID identifier used for determining which volumes to stagger", _staggerKeyword, (std::string)"layer", SegmentationParameter::NoUnit, true); + + } + + /// Destructor + HexGrid::~HexGrid() { + } + + /// determine the position based on the cell ID + Vector3D HexGrid::position(const CellID& cID) const { + int layer=0; + if (_stagger) layer= _decoder->get(cID,_staggerKeyword); + + Vector3D cellPosition; + cellPosition.X = _decoder->get(cID,_xId )*1.5*_sideLength+_offsetX+_sideLength/2.; + cellPosition.Y = _decoder->get(cID,_yId )*std::sqrt(3)/2.*_sideLength+ _offsetY+_sideLength*std::sqrt(3)/2.; + if (_stagger==0) + cellPosition.X+=_sideLength; + else if (_stagger==1) + cellPosition.X+=(layer%3)*_sideLength; + else if (_stagger==2){ + switch (layer%4){ + case 0: + cellPosition.X-=0.75*_sideLength; + break; + case 1: + cellPosition.Y+=std::sqrt(3)/4*_sideLength; + break; + case 2: + cellPosition.Y-=std::sqrt(3)/4*_sideLength; + break; + case 3: + cellPosition.X+=0.75*_sideLength; + break; + } + } + return cellPosition; + } + + inline double positive_modulo(double i, double n) { + return std::fmod(std::fmod(i,n) + n,n); + } + + + /// determine the cell ID based on the position + CellID HexGrid::cellID(const Vector3D& localPosition, const Vector3D& /* globalPosition */, const VolumeID& vID) const { + CellID cID = vID ; + int layer=0; + if (_stagger) layer= _decoder->get(cID,_staggerKeyword); + + double x=localPosition.X-_offsetX; + double y=localPosition.Y-_offsetY; + if (_stagger==0) + x-=_sideLength; + else if (_stagger==1) + x-=(layer%3)*_sideLength; + else if (_stagger==2){ + switch (layer%4){ + case 0: + x+=0.75*_sideLength; + break; + case 1: + y-=std::sqrt(3)/4*_sideLength; + break; + case 2: + y+=std::sqrt(3)/4*_sideLength; + break; + case 3: + x-=0.75*_sideLength; + break; + } + } + + double a=positive_modulo(y/(std::sqrt(3)*_sideLength),1); + double b=positive_modulo(x/(3*_sideLength),1); + int ix = std::floor(x/(3*_sideLength/2.))+ + (b<0.5)*(-abs(a-.5)<(b-.5)*3)+(b>0.5)*(abs(a-.5)-.5<(b-1)*3); + int iy=std::floor(y/(std::sqrt(3)*_sideLength/2.)); + iy-=(ix+iy)&1; + + _decoder->set( cID,_xId, ix ); + _decoder->set( cID,_yId, iy ); + return cID ; + } + + std::vector HexGrid::cellDimensions(const CellID&) const { +#if __cplusplus >= 201103L + return {2*_sideLength, std::sqrt(3)*_sideLength}; +#else + std::vector cellDims(2,0.0); + cellDims[0] = 2*_sideLength; + cellDims[1] = std::sqrt(3)*_sideLength; + return cellDims; +#endif +} + + } /* namespace DDSegmentation */ +} /* namespace dd4hep */ + +DECLARE_SEGMENTATION(HexGrid, create_segmentation)