Loading src/core/geometry/DetectorModel.cpp +0 −86 Original line number Diff line number Diff line Loading @@ -41,18 +41,6 @@ DetectorModel::DetectorModel(std::string type, ConfigReader reader) : type_(std: using namespace ROOT::Math; auto config = reader_.getHeaderConfiguration(); // Number of pixels setNPixels(config.get<DisplacementVector2D<Cartesian2D<unsigned int>>>("number_of_pixels")); // Size of the pixels auto pixel_size = config.get<XYVector>("pixel_size"); setPixelSize(pixel_size); // Size of the collection diode implant on each pixels, defaults to the full pixel size when not specified auto implant_size = config.get<XYVector>("implant_size", pixel_size); if(implant_size.x() > pixel_size.x() || implant_size.y() > pixel_size.y()) { throw InvalidValueError(config, "implant_size", "implant size cannot be larger than pixel pitch"); } setImplantSize(implant_size); // Sensor thickness setSensorThickness(config.get<double>("sensor_thickness")); // Excess around the sensor from the pixel grid Loading Loading @@ -195,77 +183,3 @@ std::vector<DetectorModel::SupportLayer> DetectorModel::getSupportLayers() const return ret_layers; } /** * The definition of inside the sensor is determined by the detector model */ bool DetectorModel::isWithinSensor(const ROOT::Math::XYZPoint& local_pos) const { auto sensor_center = getSensorCenter(); auto sensor_size = getSensorSize(); return (2 * std::fabs(local_pos.z() - sensor_center.z()) <= sensor_size.z()) && (2 * std::fabs(local_pos.y() - sensor_center.y()) <= sensor_size.y()) && (2 * std::fabs(local_pos.x() - sensor_center.x()) <= sensor_size.x()); } /** * The definition of inside the implant region is determined by the detector model * * @note The pixel implant currently is always positioned symmetrically, in the center of the pixel cell. */ bool DetectorModel::isWithinImplant(const ROOT::Math::XYZPoint& local_pos) const { auto [xpixel, ypixel] = getPixelIndex(local_pos); auto inPixelPos = local_pos - getPixelCenter(static_cast<unsigned int>(xpixel), static_cast<unsigned int>(ypixel)); return (std::fabs(inPixelPos.x()) <= std::fabs(getImplantSize().x() / 2) && std::fabs(inPixelPos.y()) <= std::fabs(getImplantSize().y() / 2)); } /** * The definition of the pixel grid size is determined by the detector model */ bool DetectorModel::isWithinMatrix(const Pixel::Index& pixel_index) const { return !(pixel_index.x() >= number_of_pixels_.x() || pixel_index.y() >= number_of_pixels_.y()); } /** * The definition of the pixel grid size is determined by the detector model */ bool DetectorModel::isWithinMatrix(const int x, const int y) const { return !(x < 0 || x >= static_cast<int>(number_of_pixels_.x()) || y < 0 || y >= static_cast<int>(number_of_pixels_.y())); } ROOT::Math::XYZPoint DetectorModel::getPixelCenter(unsigned int x, unsigned int y) const { auto size = getPixelSize(); auto local_x = size.x() * x; auto local_y = size.y() * y; auto local_z = getSensorCenter().z() - getSensorSize().z() / 2.0; return {local_x, local_y, local_z}; } std::pair<int, int> DetectorModel::getPixelIndex(const ROOT::Math::XYZPoint& position) const { auto pixel_x = static_cast<int>(std::round(position.x() / pixel_size_.x())); auto pixel_y = static_cast<int>(std::round(position.y() / pixel_size_.y())); return {pixel_x, pixel_y}; } std::set<Pixel::Index> DetectorModel::getNeighbors(const Pixel::Index& idx, const size_t distance) const { std::set<Pixel::Index> neighbors; for(int x = static_cast<int>(idx.x() - distance); x <= static_cast<int>(idx.x() + distance); x++) { for(int y = static_cast<int>(idx.y() - distance); y <= static_cast<int>(idx.y() + distance); y++) { if(!isWithinMatrix(x, y)) { continue; } neighbors.insert({static_cast<unsigned int>(x), static_cast<unsigned int>(y)}); } } return neighbors; } bool DetectorModel::areNeighbors(const Pixel::Index& seed, const Pixel::Index& entrant, const size_t distance) const { auto pixel_distance = [](unsigned int lhs, unsigned int rhs) { return (lhs > rhs ? lhs - rhs : rhs - lhs); }; return (pixel_distance(seed.x(), entrant.x()) <= distance && pixel_distance(seed.y(), entrant.y()) <= distance); } src/core/geometry/DetectorModel.hpp +13 −13 Original line number Diff line number Diff line Loading @@ -207,10 +207,10 @@ namespace allpix { /* PIXEL GRID */ /** * @brief Get number of pixel (replicated blocks in generic sensors) * @brief Get number of pixels (replicated blocks in generic sensors) * @return Number of two dimensional pixels */ virtual ROOT::Math::DisplacementVector2D<ROOT::Math::Cartesian2D<unsigned int>> getNPixels() const { ROOT::Math::DisplacementVector2D<ROOT::Math::Cartesian2D<unsigned int>> getNPixels() const { return number_of_pixels_; } /** Loading @@ -224,7 +224,7 @@ namespace allpix { * @brief Get size of a single pixel * @return Size of a pixel */ virtual ROOT::Math::XYVector getPixelSize() const { return pixel_size_; } ROOT::Math::XYVector getPixelSize() const { return pixel_size_; } /** * @brief Set the size of a pixel * @param val Size of a pixel Loading @@ -234,7 +234,7 @@ namespace allpix { * @brief Get size of the collection diode * @return Size of the collection diode implant */ virtual ROOT::Math::XYVector getImplantSize() const { return implant_size_; } ROOT::Math::XYVector getImplantSize() const { return implant_size_; } /** * @brief Set the size of the implant (collection diode) within a pixel * @param val Size of the collection diode implant Loading Loading @@ -378,21 +378,21 @@ namespace allpix { * @param local_pos Position in local coordinates of the detector model * @return True if a local position is within the sensor, false otherwise */ virtual bool isWithinSensor(const ROOT::Math::XYZPoint& local_pos) const; virtual bool isWithinSensor(const ROOT::Math::XYZPoint& local_pos) const = 0; /** * @brief Returns if a local position is within the pixel implant region of the sensitive device * @param local_pos Position in local coordinates of the detector model * @return True if a local position is within the pixel implant, false otherwise */ virtual bool isWithinImplant(const ROOT::Math::XYZPoint& local_pos) const; virtual bool isWithinImplant(const ROOT::Math::XYZPoint& local_pos) const = 0; /** * @brief Returns if a pixel index is within the grid of pixels defined for the device * @param pixel_index Pixel index to be checked * @return True if pixel_index is within the pixel grid, false otherwise */ virtual bool isWithinMatrix(const Pixel::Index& pixel_index) const; virtual bool isWithinMatrix(const Pixel::Index& pixel_index) const = 0; /** * @brief Returns if a set of pixel coordinates is within the grid of pixels defined for the device Loading @@ -400,7 +400,7 @@ namespace allpix { * @param y Y- (or row-) coordinate to be checked * @return True if pixel coordinates are within the pixel grid, false otherwise */ virtual bool isWithinMatrix(const int x, const int y) const; virtual bool isWithinMatrix(const int x, const int y) const = 0; /** * @brief Returns a pixel center in local coordinates Loading @@ -408,16 +408,16 @@ namespace allpix { * @param y Y- (or row-) coordinate of the pixel * @return Coordinates of the pixel center */ virtual ROOT::Math::XYZPoint getPixelCenter(unsigned int x, unsigned int y) const; virtual ROOT::Math::XYZPoint getPixelCenter(unsigned int x, unsigned int y) const = 0; /** * @brief Return X,Y indices of a pixel corresponding to a local position in a sensor. * @param position Position in local coordinates of the detector model * @param local_pos Position in local coordinates of the detector model * @return X,Y pixel indices * * @note No checks are performed on whether these indices represent an existing pixel or are within the pixel matrix. */ virtual std::pair<int, int> getPixelIndex(const ROOT::Math::XYZPoint& position) const; virtual std::pair<int, int> getPixelIndex(const ROOT::Math::XYZPoint& local_pos) const = 0; /** * @brief Return a set containing all pixels neighboring the given one with a configurable maximum distance Loading @@ -427,7 +427,7 @@ namespace allpix { * * @note The returned set should always also include the initial pixel indices the neighbors are calculated for */ virtual std::set<Pixel::Index> getNeighbors(const Pixel::Index& idx, const size_t distance) const; virtual std::set<Pixel::Index> getNeighbors(const Pixel::Index& idx, const size_t distance) const = 0; /** * @brief Check if two pixel indices are neighbors to each other Loading @@ -436,7 +436,7 @@ namespace allpix { * @param distance Distance for pixels to be considered neighbors * @return Boolean whether pixels are neighbors or not */ virtual bool areNeighbors(const Pixel::Index& seed, const Pixel::Index& entrant, const size_t distance) const; virtual bool areNeighbors(const Pixel::Index& seed, const Pixel::Index& entrant, const size_t distance) const = 0; protected: std::string type_; Loading src/core/geometry/PixelDetectorModel.cpp 0 → 100644 +105 −0 Original line number Diff line number Diff line /** * @file * @brief Implementation of a pixel detector model * * @copyright Copyright (c) 2017-2020 CERN and the Allpix Squared authors. * This software is distributed under the terms of the MIT License, copied verbatim in the file "LICENSE.md". * In applying this license, CERN does not waive the privileges and immunities granted to it by virtue of its status as an * Intergovernmental Organization or submit itself to any jurisdiction. */ #include "PixelDetectorModel.hpp" #include "core/module/exceptions.h" using namespace allpix; PixelDetectorModel::PixelDetectorModel(std::string type, ConfigReader reader) : DetectorModel(std::move(type), reader) { using namespace ROOT::Math; auto config = reader.getHeaderConfiguration(); // Number of pixels setNPixels(config.get<DisplacementVector2D<Cartesian2D<unsigned int>>>("number_of_pixels")); // Size of the pixels auto pixel_size = config.get<XYVector>("pixel_size"); setPixelSize(pixel_size); // Size of the collection diode implant on each pixel, defaults to the full pixel size when not specified auto implant_size = config.get<XYVector>("implant_size", pixel_size); if(implant_size.x() > pixel_size.x() || implant_size.y() > pixel_size.y()) { throw InvalidValueError(config, "implant_size", "implant size cannot be larger than pixel pitch"); } setImplantSize(implant_size); } /** * The definition of inside the sensor is determined by the detector model */ bool PixelDetectorModel::isWithinSensor(const ROOT::Math::XYZPoint& local_pos) const { auto sensor_center = getSensorCenter(); auto sensor_size = getSensorSize(); return (2 * std::fabs(local_pos.z() - sensor_center.z()) <= sensor_size.z()) && (2 * std::fabs(local_pos.y() - sensor_center.y()) <= sensor_size.y()) && (2 * std::fabs(local_pos.x() - sensor_center.x()) <= sensor_size.x()); } /** * The definition of inside the implant region is determined by the detector model * * @note The pixel implant currently is always positioned symmetrically, in the center of the pixel cell. */ bool PixelDetectorModel::isWithinImplant(const ROOT::Math::XYZPoint& local_pos) const { auto [xpixel, ypixel] = getPixelIndex(local_pos); auto inPixelPos = local_pos - getPixelCenter(static_cast<unsigned int>(xpixel), static_cast<unsigned int>(ypixel)); return (std::fabs(inPixelPos.x()) <= std::fabs(getImplantSize().x() / 2) && std::fabs(inPixelPos.y()) <= std::fabs(getImplantSize().y() / 2)); } /** * The definition of the pixel grid size is determined by the detector model */ bool PixelDetectorModel::isWithinMatrix(const Pixel::Index& pixel_index) const { return !(pixel_index.x() >= number_of_pixels_.x() || pixel_index.y() >= number_of_pixels_.y()); } /** * The definition of the pixel grid size is determined by the detector model */ bool PixelDetectorModel::isWithinMatrix(const int x, const int y) const { return !(x < 0 || x >= static_cast<int>(number_of_pixels_.x()) || y < 0 || y >= static_cast<int>(number_of_pixels_.y())); } ROOT::Math::XYZPoint PixelDetectorModel::getPixelCenter(unsigned int x, unsigned int y) const { auto size = getPixelSize(); auto local_x = size.x() * x; auto local_y = size.y() * y; auto local_z = getSensorCenter().z() - getSensorSize().z() / 2.0; return {local_x, local_y, local_z}; } std::pair<int, int> PixelDetectorModel::getPixelIndex(const ROOT::Math::XYZPoint& position) const { auto pixel_x = static_cast<int>(std::round(position.x() / pixel_size_.x())); auto pixel_y = static_cast<int>(std::round(position.y() / pixel_size_.y())); return {pixel_x, pixel_y}; } std::set<Pixel::Index> PixelDetectorModel::getNeighbors(const Pixel::Index& idx, const size_t distance) const { std::set<Pixel::Index> neighbors; for(int x = static_cast<int>(idx.x() - distance); x <= static_cast<int>(idx.x() + distance); x++) { for(int y = static_cast<int>(idx.y() - distance); y <= static_cast<int>(idx.y() + distance); y++) { if(!isWithinMatrix(x, y)) { continue; } neighbors.insert({static_cast<unsigned int>(x), static_cast<unsigned int>(y)}); } } return neighbors; } bool PixelDetectorModel::areNeighbors(const Pixel::Index& seed, const Pixel::Index& entrant, const size_t distance) const { auto pixel_distance = [](unsigned int lhs, unsigned int rhs) { return (lhs > rhs ? lhs - rhs : rhs - lhs); }; return (pixel_distance(seed.x(), entrant.x()) <= distance && pixel_distance(seed.y(), entrant.y()) <= distance); } src/core/geometry/PixelDetectorModel.hpp 0 → 100644 +189 −0 Original line number Diff line number Diff line /** * @file * @brief Pixel detector model * * @copyright Copyright (c) 2017-2020 CERN and the Allpix Squared authors. * This software is distributed under the terms of the MIT License, copied verbatim in the file "LICENSE.md". * In applying this license, CERN does not waive the privileges and immunities granted to it by virtue of its status as an * Intergovernmental Organization or submit itself to any jurisdiction. */ #ifndef ALLPIX_PIXEL_DETECTOR_MODEL_H #define ALLPIX_PIXEL_DETECTOR_MODEL_H #include <array> #include <string> #include <utility> #include <Math/Point2D.h> #include <Math/Point3D.h> #include <Math/Vector2D.h> #include <Math/Vector3D.h> #include "core/config/ConfigReader.hpp" #include "core/config/exceptions.h" #include "core/geometry/DetectorModel.hpp" #include "core/utils/log.h" #include "objects/Pixel.hpp" #include "tools/ROOT.h" namespace allpix { /** * @ingroup DetectorModels * @brief Model of a generic pixel detector. This model is further extended by specialized pixel detector models. */ class PixelDetectorModel : public DetectorModel { public: /** * @brief Constructs the pixel detector model * @param type Name of the model type * @param reader Configuration reader with description of the model */ explicit PixelDetectorModel(std::string type, ConfigReader reader); /* SENSOR */ /** * @brief Get size of the sensor * @return Size of the sensor * * Calculated from \ref DetectorModel::getMatrixSize "pixel grid size", sensor excess and sensor thickness */ ROOT::Math::XYZVector getSensorSize() const override { ROOT::Math::XYZVector excess_thickness((sensor_excess_.at(1) + sensor_excess_.at(3)), (sensor_excess_.at(0) + sensor_excess_.at(2)), sensor_thickness_); return getMatrixSize() + excess_thickness; } /** * @brief Get center of the sensor in local coordinates * @return Center of the sensor * * Center of the sensor with excess taken into account */ ROOT::Math::XYZPoint getSensorCenter() const override { ROOT::Math::XYZVector offset( (sensor_excess_.at(1) - sensor_excess_.at(3)) / 2.0, (sensor_excess_.at(0) - sensor_excess_.at(2)) / 2.0, 0); return getMatrixCenter() + offset; } /** * @brief Set the thickness of the sensor * @param val Thickness of the sensor */ void setSensorThickness(double val) { sensor_thickness_ = val; } /** * @brief Set the excess at the top of the sensor (positive y-coordinate) * @param val Sensor top excess */ void setSensorExcessTop(double val) { sensor_excess_.at(0) = val; } /** * @brief Set the excess at the right of the sensor (positive x-coordinate) * @param val Sensor right excess */ void setSensorExcessRight(double val) { sensor_excess_.at(1) = val; } /** * @brief Set the excess at the bottom of the sensor (negative y-coordinate) * @param val Sensor bottom excess */ void setSensorExcessBottom(double val) { sensor_excess_.at(2) = val; } /** * @brief Set the excess at the left of the sensor (negative x-coordinate) * @param val Sensor right excess */ void setSensorExcessLeft(double val) { sensor_excess_.at(3) = val; } /* CHIP */ /** * @brief Get size of the chip * @return Size of the chip * * Calculated from \ref DetectorModel::getMatrixSize "pixel grid size", sensor excess and chip thickness */ ROOT::Math::XYZVector getChipSize() const override { ROOT::Math::XYZVector excess_thickness((sensor_excess_.at(1) + sensor_excess_.at(3)), (sensor_excess_.at(0) + sensor_excess_.at(2)), chip_thickness_); return getMatrixSize() + excess_thickness; } /** * @brief Get center of the chip in local coordinates * @return Center of the chip * * Center of the chip calculcated from chip excess and sensor offset */ ROOT::Math::XYZPoint getChipCenter() const override { ROOT::Math::XYZVector offset((sensor_excess_.at(1) - sensor_excess_.at(3)) / 2.0, (sensor_excess_.at(0) - sensor_excess_.at(2)) / 2.0, getSensorSize().z() / 2.0 + getChipSize().z() / 2.0); return getMatrixCenter() + offset; } /** * @brief Returns if a local position is within the sensitive device * @param local_pos Position in local coordinates of the detector model * @return True if a local position is within the sensor, false otherwise */ bool isWithinSensor(const ROOT::Math::XYZPoint& local_pos) const override; /** * @brief Returns if a local position is within the pixel implant region of the sensitive device * @param local_pos Position in local coordinates of the detector model * @return True if a local position is within the pixel implant, false otherwise */ bool isWithinImplant(const ROOT::Math::XYZPoint& local_pos) const override; /** * @brief Returns if a pixel index is within the grid of pixels defined for the device * @param pixel_index Pixel index to be checked * @return True if pixel_index is within the pixel grid, false otherwise */ bool isWithinMatrix(const Pixel::Index& pixel_index) const override; /** * @brief Returns if a set of pixel coordinates is within the grid of pixels defined for the device * @param x X- (or column-) coordinate to be checked * @param y Y- (or row-) coordinate to be checked * @return True if pixel coordinates are within the pixel grid, false otherwise */ bool isWithinMatrix(const int x, const int y) const override; /** * @brief Returns a pixel center in local coordinates * @param x X- (or column-) coordinate of the pixel * @param y Y- (or row-) coordinate of the pixel * @return Coordinates of the pixel center */ ROOT::Math::XYZPoint getPixelCenter(unsigned int x, unsigned int y) const override; /** * @brief Return X,Y indices of a pixel corresponding to a local position in a sensor. * @param local_pos Position in local coordinates of the detector model * @return X,Y pixel indices * * @note No checks are performed on whether these indices represent an existing pixel or are within the pixel matrix. */ std::pair<int, int> getPixelIndex(const ROOT::Math::XYZPoint& local_pos) const override; /** * @brief Return a set containing all pixels neighboring the given one with a configurable maximum distance * @param idx Index of the pixel in question * @param distance Distance for pixels to be considered neighbors * @return Set of neighboring pixel indices, including the initial pixel * * @note The returned set should always also include the initial pixel indices the neighbors are calculated for */ std::set<Pixel::Index> getNeighbors(const Pixel::Index& idx, const size_t distance) const override; /** * @brief Check if two pixel indices are neighbors to each other * @param seed Initial pixel index * @param entrant Entrant pixel index to be tested * @param distance Distance for pixels to be considered neighbors * @return Boolean whether pixels are neighbors or not */ bool areNeighbors(const Pixel::Index& seed, const Pixel::Index& entrant, const size_t distance) const override; }; } // namespace allpix #endif // ALLPIX_DETECTOR_MODEL_H Loading
src/core/geometry/DetectorModel.cpp +0 −86 Original line number Diff line number Diff line Loading @@ -41,18 +41,6 @@ DetectorModel::DetectorModel(std::string type, ConfigReader reader) : type_(std: using namespace ROOT::Math; auto config = reader_.getHeaderConfiguration(); // Number of pixels setNPixels(config.get<DisplacementVector2D<Cartesian2D<unsigned int>>>("number_of_pixels")); // Size of the pixels auto pixel_size = config.get<XYVector>("pixel_size"); setPixelSize(pixel_size); // Size of the collection diode implant on each pixels, defaults to the full pixel size when not specified auto implant_size = config.get<XYVector>("implant_size", pixel_size); if(implant_size.x() > pixel_size.x() || implant_size.y() > pixel_size.y()) { throw InvalidValueError(config, "implant_size", "implant size cannot be larger than pixel pitch"); } setImplantSize(implant_size); // Sensor thickness setSensorThickness(config.get<double>("sensor_thickness")); // Excess around the sensor from the pixel grid Loading Loading @@ -195,77 +183,3 @@ std::vector<DetectorModel::SupportLayer> DetectorModel::getSupportLayers() const return ret_layers; } /** * The definition of inside the sensor is determined by the detector model */ bool DetectorModel::isWithinSensor(const ROOT::Math::XYZPoint& local_pos) const { auto sensor_center = getSensorCenter(); auto sensor_size = getSensorSize(); return (2 * std::fabs(local_pos.z() - sensor_center.z()) <= sensor_size.z()) && (2 * std::fabs(local_pos.y() - sensor_center.y()) <= sensor_size.y()) && (2 * std::fabs(local_pos.x() - sensor_center.x()) <= sensor_size.x()); } /** * The definition of inside the implant region is determined by the detector model * * @note The pixel implant currently is always positioned symmetrically, in the center of the pixel cell. */ bool DetectorModel::isWithinImplant(const ROOT::Math::XYZPoint& local_pos) const { auto [xpixel, ypixel] = getPixelIndex(local_pos); auto inPixelPos = local_pos - getPixelCenter(static_cast<unsigned int>(xpixel), static_cast<unsigned int>(ypixel)); return (std::fabs(inPixelPos.x()) <= std::fabs(getImplantSize().x() / 2) && std::fabs(inPixelPos.y()) <= std::fabs(getImplantSize().y() / 2)); } /** * The definition of the pixel grid size is determined by the detector model */ bool DetectorModel::isWithinMatrix(const Pixel::Index& pixel_index) const { return !(pixel_index.x() >= number_of_pixels_.x() || pixel_index.y() >= number_of_pixels_.y()); } /** * The definition of the pixel grid size is determined by the detector model */ bool DetectorModel::isWithinMatrix(const int x, const int y) const { return !(x < 0 || x >= static_cast<int>(number_of_pixels_.x()) || y < 0 || y >= static_cast<int>(number_of_pixels_.y())); } ROOT::Math::XYZPoint DetectorModel::getPixelCenter(unsigned int x, unsigned int y) const { auto size = getPixelSize(); auto local_x = size.x() * x; auto local_y = size.y() * y; auto local_z = getSensorCenter().z() - getSensorSize().z() / 2.0; return {local_x, local_y, local_z}; } std::pair<int, int> DetectorModel::getPixelIndex(const ROOT::Math::XYZPoint& position) const { auto pixel_x = static_cast<int>(std::round(position.x() / pixel_size_.x())); auto pixel_y = static_cast<int>(std::round(position.y() / pixel_size_.y())); return {pixel_x, pixel_y}; } std::set<Pixel::Index> DetectorModel::getNeighbors(const Pixel::Index& idx, const size_t distance) const { std::set<Pixel::Index> neighbors; for(int x = static_cast<int>(idx.x() - distance); x <= static_cast<int>(idx.x() + distance); x++) { for(int y = static_cast<int>(idx.y() - distance); y <= static_cast<int>(idx.y() + distance); y++) { if(!isWithinMatrix(x, y)) { continue; } neighbors.insert({static_cast<unsigned int>(x), static_cast<unsigned int>(y)}); } } return neighbors; } bool DetectorModel::areNeighbors(const Pixel::Index& seed, const Pixel::Index& entrant, const size_t distance) const { auto pixel_distance = [](unsigned int lhs, unsigned int rhs) { return (lhs > rhs ? lhs - rhs : rhs - lhs); }; return (pixel_distance(seed.x(), entrant.x()) <= distance && pixel_distance(seed.y(), entrant.y()) <= distance); }
src/core/geometry/DetectorModel.hpp +13 −13 Original line number Diff line number Diff line Loading @@ -207,10 +207,10 @@ namespace allpix { /* PIXEL GRID */ /** * @brief Get number of pixel (replicated blocks in generic sensors) * @brief Get number of pixels (replicated blocks in generic sensors) * @return Number of two dimensional pixels */ virtual ROOT::Math::DisplacementVector2D<ROOT::Math::Cartesian2D<unsigned int>> getNPixels() const { ROOT::Math::DisplacementVector2D<ROOT::Math::Cartesian2D<unsigned int>> getNPixels() const { return number_of_pixels_; } /** Loading @@ -224,7 +224,7 @@ namespace allpix { * @brief Get size of a single pixel * @return Size of a pixel */ virtual ROOT::Math::XYVector getPixelSize() const { return pixel_size_; } ROOT::Math::XYVector getPixelSize() const { return pixel_size_; } /** * @brief Set the size of a pixel * @param val Size of a pixel Loading @@ -234,7 +234,7 @@ namespace allpix { * @brief Get size of the collection diode * @return Size of the collection diode implant */ virtual ROOT::Math::XYVector getImplantSize() const { return implant_size_; } ROOT::Math::XYVector getImplantSize() const { return implant_size_; } /** * @brief Set the size of the implant (collection diode) within a pixel * @param val Size of the collection diode implant Loading Loading @@ -378,21 +378,21 @@ namespace allpix { * @param local_pos Position in local coordinates of the detector model * @return True if a local position is within the sensor, false otherwise */ virtual bool isWithinSensor(const ROOT::Math::XYZPoint& local_pos) const; virtual bool isWithinSensor(const ROOT::Math::XYZPoint& local_pos) const = 0; /** * @brief Returns if a local position is within the pixel implant region of the sensitive device * @param local_pos Position in local coordinates of the detector model * @return True if a local position is within the pixel implant, false otherwise */ virtual bool isWithinImplant(const ROOT::Math::XYZPoint& local_pos) const; virtual bool isWithinImplant(const ROOT::Math::XYZPoint& local_pos) const = 0; /** * @brief Returns if a pixel index is within the grid of pixels defined for the device * @param pixel_index Pixel index to be checked * @return True if pixel_index is within the pixel grid, false otherwise */ virtual bool isWithinMatrix(const Pixel::Index& pixel_index) const; virtual bool isWithinMatrix(const Pixel::Index& pixel_index) const = 0; /** * @brief Returns if a set of pixel coordinates is within the grid of pixels defined for the device Loading @@ -400,7 +400,7 @@ namespace allpix { * @param y Y- (or row-) coordinate to be checked * @return True if pixel coordinates are within the pixel grid, false otherwise */ virtual bool isWithinMatrix(const int x, const int y) const; virtual bool isWithinMatrix(const int x, const int y) const = 0; /** * @brief Returns a pixel center in local coordinates Loading @@ -408,16 +408,16 @@ namespace allpix { * @param y Y- (or row-) coordinate of the pixel * @return Coordinates of the pixel center */ virtual ROOT::Math::XYZPoint getPixelCenter(unsigned int x, unsigned int y) const; virtual ROOT::Math::XYZPoint getPixelCenter(unsigned int x, unsigned int y) const = 0; /** * @brief Return X,Y indices of a pixel corresponding to a local position in a sensor. * @param position Position in local coordinates of the detector model * @param local_pos Position in local coordinates of the detector model * @return X,Y pixel indices * * @note No checks are performed on whether these indices represent an existing pixel or are within the pixel matrix. */ virtual std::pair<int, int> getPixelIndex(const ROOT::Math::XYZPoint& position) const; virtual std::pair<int, int> getPixelIndex(const ROOT::Math::XYZPoint& local_pos) const = 0; /** * @brief Return a set containing all pixels neighboring the given one with a configurable maximum distance Loading @@ -427,7 +427,7 @@ namespace allpix { * * @note The returned set should always also include the initial pixel indices the neighbors are calculated for */ virtual std::set<Pixel::Index> getNeighbors(const Pixel::Index& idx, const size_t distance) const; virtual std::set<Pixel::Index> getNeighbors(const Pixel::Index& idx, const size_t distance) const = 0; /** * @brief Check if two pixel indices are neighbors to each other Loading @@ -436,7 +436,7 @@ namespace allpix { * @param distance Distance for pixels to be considered neighbors * @return Boolean whether pixels are neighbors or not */ virtual bool areNeighbors(const Pixel::Index& seed, const Pixel::Index& entrant, const size_t distance) const; virtual bool areNeighbors(const Pixel::Index& seed, const Pixel::Index& entrant, const size_t distance) const = 0; protected: std::string type_; Loading
src/core/geometry/PixelDetectorModel.cpp 0 → 100644 +105 −0 Original line number Diff line number Diff line /** * @file * @brief Implementation of a pixel detector model * * @copyright Copyright (c) 2017-2020 CERN and the Allpix Squared authors. * This software is distributed under the terms of the MIT License, copied verbatim in the file "LICENSE.md". * In applying this license, CERN does not waive the privileges and immunities granted to it by virtue of its status as an * Intergovernmental Organization or submit itself to any jurisdiction. */ #include "PixelDetectorModel.hpp" #include "core/module/exceptions.h" using namespace allpix; PixelDetectorModel::PixelDetectorModel(std::string type, ConfigReader reader) : DetectorModel(std::move(type), reader) { using namespace ROOT::Math; auto config = reader.getHeaderConfiguration(); // Number of pixels setNPixels(config.get<DisplacementVector2D<Cartesian2D<unsigned int>>>("number_of_pixels")); // Size of the pixels auto pixel_size = config.get<XYVector>("pixel_size"); setPixelSize(pixel_size); // Size of the collection diode implant on each pixel, defaults to the full pixel size when not specified auto implant_size = config.get<XYVector>("implant_size", pixel_size); if(implant_size.x() > pixel_size.x() || implant_size.y() > pixel_size.y()) { throw InvalidValueError(config, "implant_size", "implant size cannot be larger than pixel pitch"); } setImplantSize(implant_size); } /** * The definition of inside the sensor is determined by the detector model */ bool PixelDetectorModel::isWithinSensor(const ROOT::Math::XYZPoint& local_pos) const { auto sensor_center = getSensorCenter(); auto sensor_size = getSensorSize(); return (2 * std::fabs(local_pos.z() - sensor_center.z()) <= sensor_size.z()) && (2 * std::fabs(local_pos.y() - sensor_center.y()) <= sensor_size.y()) && (2 * std::fabs(local_pos.x() - sensor_center.x()) <= sensor_size.x()); } /** * The definition of inside the implant region is determined by the detector model * * @note The pixel implant currently is always positioned symmetrically, in the center of the pixel cell. */ bool PixelDetectorModel::isWithinImplant(const ROOT::Math::XYZPoint& local_pos) const { auto [xpixel, ypixel] = getPixelIndex(local_pos); auto inPixelPos = local_pos - getPixelCenter(static_cast<unsigned int>(xpixel), static_cast<unsigned int>(ypixel)); return (std::fabs(inPixelPos.x()) <= std::fabs(getImplantSize().x() / 2) && std::fabs(inPixelPos.y()) <= std::fabs(getImplantSize().y() / 2)); } /** * The definition of the pixel grid size is determined by the detector model */ bool PixelDetectorModel::isWithinMatrix(const Pixel::Index& pixel_index) const { return !(pixel_index.x() >= number_of_pixels_.x() || pixel_index.y() >= number_of_pixels_.y()); } /** * The definition of the pixel grid size is determined by the detector model */ bool PixelDetectorModel::isWithinMatrix(const int x, const int y) const { return !(x < 0 || x >= static_cast<int>(number_of_pixels_.x()) || y < 0 || y >= static_cast<int>(number_of_pixels_.y())); } ROOT::Math::XYZPoint PixelDetectorModel::getPixelCenter(unsigned int x, unsigned int y) const { auto size = getPixelSize(); auto local_x = size.x() * x; auto local_y = size.y() * y; auto local_z = getSensorCenter().z() - getSensorSize().z() / 2.0; return {local_x, local_y, local_z}; } std::pair<int, int> PixelDetectorModel::getPixelIndex(const ROOT::Math::XYZPoint& position) const { auto pixel_x = static_cast<int>(std::round(position.x() / pixel_size_.x())); auto pixel_y = static_cast<int>(std::round(position.y() / pixel_size_.y())); return {pixel_x, pixel_y}; } std::set<Pixel::Index> PixelDetectorModel::getNeighbors(const Pixel::Index& idx, const size_t distance) const { std::set<Pixel::Index> neighbors; for(int x = static_cast<int>(idx.x() - distance); x <= static_cast<int>(idx.x() + distance); x++) { for(int y = static_cast<int>(idx.y() - distance); y <= static_cast<int>(idx.y() + distance); y++) { if(!isWithinMatrix(x, y)) { continue; } neighbors.insert({static_cast<unsigned int>(x), static_cast<unsigned int>(y)}); } } return neighbors; } bool PixelDetectorModel::areNeighbors(const Pixel::Index& seed, const Pixel::Index& entrant, const size_t distance) const { auto pixel_distance = [](unsigned int lhs, unsigned int rhs) { return (lhs > rhs ? lhs - rhs : rhs - lhs); }; return (pixel_distance(seed.x(), entrant.x()) <= distance && pixel_distance(seed.y(), entrant.y()) <= distance); }
src/core/geometry/PixelDetectorModel.hpp 0 → 100644 +189 −0 Original line number Diff line number Diff line /** * @file * @brief Pixel detector model * * @copyright Copyright (c) 2017-2020 CERN and the Allpix Squared authors. * This software is distributed under the terms of the MIT License, copied verbatim in the file "LICENSE.md". * In applying this license, CERN does not waive the privileges and immunities granted to it by virtue of its status as an * Intergovernmental Organization or submit itself to any jurisdiction. */ #ifndef ALLPIX_PIXEL_DETECTOR_MODEL_H #define ALLPIX_PIXEL_DETECTOR_MODEL_H #include <array> #include <string> #include <utility> #include <Math/Point2D.h> #include <Math/Point3D.h> #include <Math/Vector2D.h> #include <Math/Vector3D.h> #include "core/config/ConfigReader.hpp" #include "core/config/exceptions.h" #include "core/geometry/DetectorModel.hpp" #include "core/utils/log.h" #include "objects/Pixel.hpp" #include "tools/ROOT.h" namespace allpix { /** * @ingroup DetectorModels * @brief Model of a generic pixel detector. This model is further extended by specialized pixel detector models. */ class PixelDetectorModel : public DetectorModel { public: /** * @brief Constructs the pixel detector model * @param type Name of the model type * @param reader Configuration reader with description of the model */ explicit PixelDetectorModel(std::string type, ConfigReader reader); /* SENSOR */ /** * @brief Get size of the sensor * @return Size of the sensor * * Calculated from \ref DetectorModel::getMatrixSize "pixel grid size", sensor excess and sensor thickness */ ROOT::Math::XYZVector getSensorSize() const override { ROOT::Math::XYZVector excess_thickness((sensor_excess_.at(1) + sensor_excess_.at(3)), (sensor_excess_.at(0) + sensor_excess_.at(2)), sensor_thickness_); return getMatrixSize() + excess_thickness; } /** * @brief Get center of the sensor in local coordinates * @return Center of the sensor * * Center of the sensor with excess taken into account */ ROOT::Math::XYZPoint getSensorCenter() const override { ROOT::Math::XYZVector offset( (sensor_excess_.at(1) - sensor_excess_.at(3)) / 2.0, (sensor_excess_.at(0) - sensor_excess_.at(2)) / 2.0, 0); return getMatrixCenter() + offset; } /** * @brief Set the thickness of the sensor * @param val Thickness of the sensor */ void setSensorThickness(double val) { sensor_thickness_ = val; } /** * @brief Set the excess at the top of the sensor (positive y-coordinate) * @param val Sensor top excess */ void setSensorExcessTop(double val) { sensor_excess_.at(0) = val; } /** * @brief Set the excess at the right of the sensor (positive x-coordinate) * @param val Sensor right excess */ void setSensorExcessRight(double val) { sensor_excess_.at(1) = val; } /** * @brief Set the excess at the bottom of the sensor (negative y-coordinate) * @param val Sensor bottom excess */ void setSensorExcessBottom(double val) { sensor_excess_.at(2) = val; } /** * @brief Set the excess at the left of the sensor (negative x-coordinate) * @param val Sensor right excess */ void setSensorExcessLeft(double val) { sensor_excess_.at(3) = val; } /* CHIP */ /** * @brief Get size of the chip * @return Size of the chip * * Calculated from \ref DetectorModel::getMatrixSize "pixel grid size", sensor excess and chip thickness */ ROOT::Math::XYZVector getChipSize() const override { ROOT::Math::XYZVector excess_thickness((sensor_excess_.at(1) + sensor_excess_.at(3)), (sensor_excess_.at(0) + sensor_excess_.at(2)), chip_thickness_); return getMatrixSize() + excess_thickness; } /** * @brief Get center of the chip in local coordinates * @return Center of the chip * * Center of the chip calculcated from chip excess and sensor offset */ ROOT::Math::XYZPoint getChipCenter() const override { ROOT::Math::XYZVector offset((sensor_excess_.at(1) - sensor_excess_.at(3)) / 2.0, (sensor_excess_.at(0) - sensor_excess_.at(2)) / 2.0, getSensorSize().z() / 2.0 + getChipSize().z() / 2.0); return getMatrixCenter() + offset; } /** * @brief Returns if a local position is within the sensitive device * @param local_pos Position in local coordinates of the detector model * @return True if a local position is within the sensor, false otherwise */ bool isWithinSensor(const ROOT::Math::XYZPoint& local_pos) const override; /** * @brief Returns if a local position is within the pixel implant region of the sensitive device * @param local_pos Position in local coordinates of the detector model * @return True if a local position is within the pixel implant, false otherwise */ bool isWithinImplant(const ROOT::Math::XYZPoint& local_pos) const override; /** * @brief Returns if a pixel index is within the grid of pixels defined for the device * @param pixel_index Pixel index to be checked * @return True if pixel_index is within the pixel grid, false otherwise */ bool isWithinMatrix(const Pixel::Index& pixel_index) const override; /** * @brief Returns if a set of pixel coordinates is within the grid of pixels defined for the device * @param x X- (or column-) coordinate to be checked * @param y Y- (or row-) coordinate to be checked * @return True if pixel coordinates are within the pixel grid, false otherwise */ bool isWithinMatrix(const int x, const int y) const override; /** * @brief Returns a pixel center in local coordinates * @param x X- (or column-) coordinate of the pixel * @param y Y- (or row-) coordinate of the pixel * @return Coordinates of the pixel center */ ROOT::Math::XYZPoint getPixelCenter(unsigned int x, unsigned int y) const override; /** * @brief Return X,Y indices of a pixel corresponding to a local position in a sensor. * @param local_pos Position in local coordinates of the detector model * @return X,Y pixel indices * * @note No checks are performed on whether these indices represent an existing pixel or are within the pixel matrix. */ std::pair<int, int> getPixelIndex(const ROOT::Math::XYZPoint& local_pos) const override; /** * @brief Return a set containing all pixels neighboring the given one with a configurable maximum distance * @param idx Index of the pixel in question * @param distance Distance for pixels to be considered neighbors * @return Set of neighboring pixel indices, including the initial pixel * * @note The returned set should always also include the initial pixel indices the neighbors are calculated for */ std::set<Pixel::Index> getNeighbors(const Pixel::Index& idx, const size_t distance) const override; /** * @brief Check if two pixel indices are neighbors to each other * @param seed Initial pixel index * @param entrant Entrant pixel index to be tested * @param distance Distance for pixels to be considered neighbors * @return Boolean whether pixels are neighbors or not */ bool areNeighbors(const Pixel::Index& seed, const Pixel::Index& entrant, const size_t distance) const override; }; } // namespace allpix #endif // ALLPIX_DETECTOR_MODEL_H