src/core/geometry/DetectorModel.hpp

Base of detector models. More…

Namespaces

Name
allpix
Helper class to hold support layers for a detector model.

Classes

Name
class allpix::DetectorModel
Base of all detector models.
class allpix::DetectorModel::Implant
Helper class to hold implant definitions for a detector model.

Types

Name
enum class SensorMaterial { SILICON = 1, GALLIUM_ARSENIDE, GERMANIUM, CADMIUM_TELLURIDE, CADMIUM_ZINC_TELLURIDE, DIAMOND, SILICON_CARBIDE, GALLIUM_NITRIDE}
Sensor materials.
enum class Dopant { PHOSPHORUS = 0, ARSENIC}
Type of dopant.

Detailed Description

Base of detector models.

Copyright: Copyright (c) 2017-2024 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. SPDX-License-Identifier: MIT

Types Documentation

enum SensorMaterial

Enumerator Value Description
SILICON 1 Silicon.
GALLIUM_ARSENIDE Gallium Arsenide.
GERMANIUM Germanium.
CADMIUM_TELLURIDE Cadmium Telluride.
CADMIUM_ZINC_TELLURIDE Cadmium Zinc Telluride.
DIAMOND Diamond.
SILICON_CARBIDE Silicon Carbide.
GALLIUM_NITRIDE Gallium Nitride.

Sensor materials.

enum Dopant

Enumerator Value Description
PHOSPHORUS 0
ARSENIC

Type of dopant.

Source code


#ifndef ALLPIX_DETECTOR_MODEL_H
#define ALLPIX_DETECTOR_MODEL_H

#include <array>
#include <string>
#include <utility>

#include <Math/Point2D.h>
#include <Math/Point3D.h>
#include <Math/RotationZ.h>
#include <Math/Vector2D.h>
#include <Math/Vector3D.h>

#include "core/config/ConfigReader.hpp"
#include "core/config/exceptions.h"
#include "core/utils/log.h"
#include "objects/Pixel.hpp"
#include "tools/ROOT.h"

#include "DetectorAssembly.hpp"
#include "SupportLayer.hpp"

namespace allpix {
    enum class SensorMaterial {
        SILICON = 1,            
        GALLIUM_ARSENIDE,       
        GERMANIUM,              
        CADMIUM_TELLURIDE,      
        CADMIUM_ZINC_TELLURIDE, 
        DIAMOND,                
        SILICON_CARBIDE,        
        GALLIUM_NITRIDE,        
    };

    enum class Dopant {
        PHOSPHORUS = 0,
        ARSENIC,
    };

    class DetectorModel {
    public:
        static std::shared_ptr<DetectorModel> factory(const std::string& name, const ConfigReader&);

        template <class T> bool is() { return dynamic_cast<T*>(this) != nullptr; }

        class Implant {
            friend class DetectorModel;

        public:
            enum class Type { FRONTSIDE, BACKSIDE };
            enum class Shape { RECTANGLE, ELLIPSE };

            ROOT::Math::XYZVector getOffset() const { return offset_; }
            ROOT::Math::RotationZ getOrientation() const { return orientation_; }
            ROOT::Math::XYZVector getSize() const { return size_; }
            Type getType() const { return type_; }

            Shape getShape() const { return shape_; }

            bool contains(const ROOT::Math::XYZVector& position) const;

            const Configuration& getConfiguration() const { return config_; }

            std::optional<ROOT::Math::XYZPoint> intersect(const ROOT::Math::XYZVector& direction,
                                                          const ROOT::Math::XYZPoint& position) const;

        private:
            Implant(Type type,
                    Shape shape,
                    ROOT::Math::XYZVector size,
                    ROOT::Math::XYZVector offset,
                    ROOT::Math::RotationZ orientation,
                    Configuration config)
                : type_(type), shape_(shape), size_(std::move(size)), offset_(std::move(offset)), orientation_(orientation),
                  config_(std::move(config)) {}

            // Actual parameters returned
            Type type_;
            Shape shape_;
            ROOT::Math::XYZVector size_;
            ROOT::Math::XYZVector offset_;
            ROOT::Math::RotationZ orientation_;
            Configuration config_;
        };

        explicit DetectorModel(std::string type,
                               std::shared_ptr<DetectorAssembly> assembly,
                               const ConfigReader& reader,
                               const Configuration& config);

        virtual ~DetectorModel() = default;

        std::vector<Configuration> getConfigurations() const;

        const std::string& getType() const { return type_; }

        const std::shared_ptr<DetectorAssembly> getAssembly() const { return assembly_; }

        virtual ROOT::Math::XYZPoint getMatrixCenter() const {
            return {getMatrixSize().x() / 2.0 - getPixelSize().x() / 2.0,
                    getMatrixSize().y() / 2.0 - getPixelSize().y() / 2.0,
                    0};
        }

        virtual ROOT::Math::XYZPoint getModelCenter() const;

        virtual ROOT::Math::XYZVector getSize() const;

        /* PIXEL GRID */
        ROOT::Math::DisplacementVector2D<ROOT::Math::Cartesian2D<unsigned int>> getNPixels() const {
            return number_of_pixels_;
        }

        const ROOT::Math::XYVector& getPixelSize() const { return pixel_size_; }
        Pixel::Type getPixelType() const { return pixel_type_; }

        inline const std::vector<Implant>& getImplants() const { return implants_; };

        virtual ROOT::Math::XYZVector getMatrixSize() const {
            return {getNPixels().x() * getPixelSize().x(), getNPixels().y() * getPixelSize().y(), 0};
        }

        /* SENSOR */
        virtual ROOT::Math::XYZVector getSensorSize() const {
            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;
        }
        virtual ROOT::Math::XYZPoint getSensorCenter() const {
            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;
        }
        SensorMaterial getSensorMaterial() const { return sensor_material_; }

        /* CHIP */
        virtual ROOT::Math::XYZVector getChipSize() const {
            ROOT::Math::XYZVector excess_thickness(
                assembly_->getChipExcess().x(), assembly_->getChipExcess().y(), assembly_->getChipThickness());
            return getMatrixSize() + excess_thickness;
        }
        virtual ROOT::Math::XYZPoint getChipCenter() const {
            ROOT::Math::XYZVector offset(assembly_->getChipOffset().x() / 2.0,
                                         assembly_->getChipOffset().y() / 2.0,
                                         getSensorSize().z() / 2.0 + getChipSize().z() / 2.0 +
                                             assembly_->getChipOffset().z());
            return getMatrixCenter() + offset;
        }

        /* SUPPORT */
        virtual std::vector<SupportLayer> getSupportLayers() const;

        virtual bool isWithinSensor(const ROOT::Math::XYZPoint& local_pos) const = 0;

        virtual bool isOnSensorBoundary(const ROOT::Math::XYZPoint& local_pos) const = 0;

        virtual ROOT::Math::XYZPoint getSensorIntercept(const ROOT::Math::XYZPoint& inside,
                                                        const ROOT::Math::XYZPoint& outside) const = 0;

        virtual std::optional<Implant> isWithinImplant(const ROOT::Math::XYZPoint& local_pos) const;

        ROOT::Math::XYZPoint getImplantIntercept(const Implant& implant,
                                                 const ROOT::Math::XYZPoint& outside,
                                                 const ROOT::Math::XYZPoint& inside) const;

        virtual bool isWithinMatrix(const Pixel::Index& pixel_index) const = 0;

        virtual bool isWithinMatrix(const int x, const int y) const = 0;

        virtual bool isWithinMatrix(const ROOT::Math::XYZPoint& position) const {
            auto [index_x, index_y] = getPixelIndex(position);
            return isWithinMatrix(index_x, index_y);
        }

        virtual ROOT::Math::XYZPoint getPixelCenter(const int x, const int y) const = 0;
        virtual std::pair<int, int> getPixelIndex(const ROOT::Math::XYZPoint& local_pos) const = 0;

        virtual std::set<Pixel::Index> getNeighbors(const Pixel::Index& idx, const size_t distance) const = 0;

        virtual bool areNeighbors(const Pixel::Index& seed, const Pixel::Index& entrant, const size_t distance) const = 0;

    protected:
        void setNPixels(ROOT::Math::DisplacementVector2D<ROOT::Math::Cartesian2D<unsigned int>> val) {
            number_of_pixels_ = std::move(val);
        }

        void setPixelSize(ROOT::Math::XYVector val) { pixel_size_ = std::move(val); }

        void setSensorThickness(double val) { sensor_thickness_ = val; }
        void setSensorExcessTop(double val) { sensor_excess_.at(0) = val; }
        void setSensorExcessRight(double val) { sensor_excess_.at(1) = val; }
        void setSensorExcessBottom(double val) { sensor_excess_.at(2) = val; }
        void setSensorExcessLeft(double val) { sensor_excess_.at(3) = val; }

        std::string type_;

        ROOT::Math::DisplacementVector2D<ROOT::Math::Cartesian2D<unsigned int>> number_of_pixels_;
        ROOT::Math::XYVector pixel_size_;
        Pixel::Type pixel_type_{Pixel::Type::RECTANGLE};

        double sensor_thickness_{};
        std::array<double, 4> sensor_excess_{};
        SensorMaterial sensor_material_{SensorMaterial::SILICON};

        std::shared_ptr<DetectorAssembly> assembly_;
        std::vector<Implant> implants_;
        std::vector<SupportLayer> support_layers_;

    private:

        DetectorModel(const DetectorModel&) = default;
        DetectorModel& operator=(const DetectorModel&) = default;

        DetectorModel(DetectorModel&&) = default;
        DetectorModel& operator=(DetectorModel&&) = default;

        void addImplant(const Implant::Type& type,
                        const Implant::Shape& shape,
                        ROOT::Math::XYZVector size,
                        const ROOT::Math::XYVector& offset,
                        double orientation,
                        const Configuration& config);

        void addSupportLayer(const ROOT::Math::XYVector& size,
                             double thickness,
                             ROOT::Math::XYZVector offset,
                             std::string material,
                             std::string type,
                             const SupportLayer::Location location,
                             const ROOT::Math::XYVector& hole_size,
                             ROOT::Math::XYVector hole_offset) {
            ROOT::Math::XYZVector full_size(size.x(), size.y(), thickness);
            ROOT::Math::XYZVector full_hole_size(hole_size.x(), hole_size.y(), thickness);
            support_layers_.push_back(SupportLayer(std::move(full_size),
                                                   std::move(offset),
                                                   std::move(material),
                                                   std::move(type),
                                                   location,
                                                   std::move(full_hole_size),
                                                   std::move(hole_offset)));
        }

        // Validation of the detector model
        virtual void validate();

        ConfigReader reader_;
    };
} // namespace allpix

#endif // ALLPIX_DETECTOR_MODEL_H

Updated on 2025-02-27 at 14:14:46 +0000