Commit f5fdfad3 authored by Simon Spannagel's avatar Simon Spannagel
Browse files

Move DetectorAssembly to separate file

parent 087be98b
Loading
Loading
Loading
Loading
+129 −0
Original line number Diff line number Diff line
/**
 * @file
 * @brief Definition of detector assemblies
 *
 * @copyright Copyright (c) 2017 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_DETECTOR_ASSEMBLY_H
#define ALLPIX_DETECTOR_ASSEMBLY_H

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

/**
 * @brief Helper class to hold information on the detector assembly
 */
namespace allpix {
    class DetectorAssembly {
    public:
        DetectorAssembly(const ConfigReader& reader) {
            auto config = reader.getHeaderConfiguration();

            // Chip thickness
            thickness_ = config.get<double>("assembly_thickness", 0);
        }
        DetectorAssembly() = delete;
        virtual ~DetectorAssembly() = default;

        /**
         * @brief Get the thickness of the chip
         * @return Thickness of the chip
         */
        double getThickness() const { return thickness_; }

        ROOT::Math::XYVector getExcess() const { return {(excess_.at(1) + excess_.at(3)), (excess_.at(0) + excess_.at(2))}; }

        virtual ROOT::Math::XYZVector getOffset() const {
            return {(excess_.at(1) - excess_.at(3)), (excess_.at(0) - excess_.at(2)), 0};
        }

    protected:
        std::array<double, 4> excess_{};

    private:
        double thickness_{};
    };

    class HybridAssembly : public DetectorAssembly {
    public:
        HybridAssembly(const ConfigReader& reader) : DetectorAssembly(reader) {
            auto config = reader.getHeaderConfiguration();

            // Excess around the chip from the pixel grid
            auto default_assembly_excess = config.get<double>("assembly_excess", 0);
            excess_.at(0) = config.get<double>("assembly_excess_top", default_assembly_excess);
            excess_.at(1) = config.get<double>("assembly_excess_right", default_assembly_excess);
            excess_.at(2) = config.get<double>("assembly_excess_bottom", default_assembly_excess);
            excess_.at(3) = config.get<double>("assembly_excess_left", default_assembly_excess);

            // Set bump parameters
            bump_cylinder_radius_ = config.get<double>("bump_cylinder_radius");
            bump_height_ = config.get<double>("bump_height");
            bump_sphere_radius_ = config.get<double>("bump_sphere_radius", 0);

            auto pitch = config.get<ROOT::Math::XYVector>("pixel_size");
            bump_offset_ = config.get<ROOT::Math::XYVector>("bump_offset", {0, 0});
            if(std::fabs(bump_offset_.x()) > pitch.x() / 2.0 || std::fabs(bump_offset_.y()) > pitch.y() / 2.0) {
                throw InvalidValueError(config, "bump_offset", "bump bond offset cannot be larger than half pixel pitch");
            }
        }

        ROOT::Math::XYZVector getOffset() const override {
            return {(excess_.at(1) - excess_.at(3)), (excess_.at(0) - excess_.at(2)), bump_height_};
        }

        /**
         * @brief Get the center of the bump bonds in local coordinates
         * @return Center of the bump bonds
         *
         * The bump bonds are aligned with the grid with an optional XY-offset. The z-offset is calculated with the
         * sensor and chip offsets taken into account.
         */
        ROOT::Math::XYZVector getBumpsOffset() const { return {bump_offset_.x(), bump_offset_.y(), bump_height_ / 2.0}; }
        /**
         * @brief Get the radius of the sphere of every individual bump bond (union solid with cylinder)
         * @return Radius of bump bond sphere
         */
        double getBumpSphereRadius() const { return bump_sphere_radius_; }
        /**
         * @brief Get the radius of the cylinder of every individual bump bond  (union solid with sphere)
         * @return Radius of bump bond cylinder
         */
        double getBumpCylinderRadius() const { return bump_cylinder_radius_; }
        /**
         * @brief Get the height of the bump bond cylinder, determining the offset between sensor and chip
         * @return Height of the bump bonds
         */
        double getBumpHeight() const { return bump_height_; }

    private:
        double bump_sphere_radius_{};
        double bump_height_{};
        ROOT::Math::XYVector bump_offset_;
        double bump_cylinder_radius_{};
    };

    class MonolithicAssembly : public DetectorAssembly {
    public:
        MonolithicAssembly(const ConfigReader& reader) : DetectorAssembly(reader) {
            auto config = reader.getHeaderConfiguration();

            // Excess around the chip is copied from sensor size
            auto default_assembly_excess = config.get<double>("sensor_excess", 0);
            excess_.at(0) = config.get<double>("sensor_excess_top", default_assembly_excess);
            excess_.at(1) = config.get<double>("sensor_excess_right", default_assembly_excess);
            excess_.at(2) = config.get<double>("sensor_excess_bottom", default_assembly_excess);
            excess_.at(3) = config.get<double>("sensor_excess_left", default_assembly_excess);
        }

    private:
    };
} // namespace allpix

#endif // ALLPIX_SUPPORT_LAYER_H
+1 −108
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@
#include "objects/Pixel.hpp"
#include "tools/ROOT.h"

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

namespace allpix {
@@ -75,114 +76,6 @@ namespace allpix {
         */
        template <class T> bool is() { return dynamic_cast<T*>(this) != nullptr; }

        class DetectorAssembly {
        public:
            DetectorAssembly(const ConfigReader& reader) {
                auto config = reader.getHeaderConfiguration();

                // Chip thickness
                thickness_ = config.get<double>("assembly_thickness", 0);
            }
            DetectorAssembly() = delete;
            virtual ~DetectorAssembly() = default;

            /**
             * @brief Get the thickness of the chip
             * @return Thickness of the chip
             */
            double getThickness() const { return thickness_; }

            ROOT::Math::XYVector getExcess() const {
                return {(excess_.at(1) + excess_.at(3)), (excess_.at(0) + excess_.at(2))};
            }

            virtual ROOT::Math::XYZVector getOffset() const {
                return {(excess_.at(1) - excess_.at(3)), (excess_.at(0) - excess_.at(2)), 0};
            }

        protected:
            std::array<double, 4> excess_{};

        private:
            double thickness_{};
        };

        class HybridAssembly : public DetectorAssembly {
        public:
            HybridAssembly(const ConfigReader& reader) : DetectorAssembly(reader) {
                auto config = reader.getHeaderConfiguration();

                // Excess around the chip from the pixel grid
                auto default_assembly_excess = config.get<double>("assembly_excess", 0);
                excess_.at(0) = config.get<double>("assembly_excess_top", default_assembly_excess);
                excess_.at(1) = config.get<double>("assembly_excess_right", default_assembly_excess);
                excess_.at(2) = config.get<double>("assembly_excess_bottom", default_assembly_excess);
                excess_.at(3) = config.get<double>("assembly_excess_left", default_assembly_excess);

                // Set bump parameters
                bump_cylinder_radius_ = config.get<double>("bump_cylinder_radius");
                bump_height_ = config.get<double>("bump_height");
                bump_sphere_radius_ = config.get<double>("bump_sphere_radius", 0);

                auto pitch = config.get<ROOT::Math::XYVector>("pixel_size");
                bump_offset_ = config.get<ROOT::Math::XYVector>("bump_offset", {0, 0});
                if(std::fabs(bump_offset_.x()) > pitch.x() / 2.0 || std::fabs(bump_offset_.y()) > pitch.y() / 2.0) {
                    throw InvalidValueError(
                        config, "bump_offset", "bump bond offset cannot be larger than half pixel pitch");
                }
            }

            ROOT::Math::XYZVector getOffset() const override {
                return {(excess_.at(1) - excess_.at(3)), (excess_.at(0) - excess_.at(2)), bump_height_};
            }

            /**
             * @brief Get the center of the bump bonds in local coordinates
             * @return Center of the bump bonds
             *
             * The bump bonds are aligned with the grid with an optional XY-offset. The z-offset is calculated with the
             * sensor and chip offsets taken into account.
             */
            ROOT::Math::XYZVector getBumpsOffset() const { return {bump_offset_.x(), bump_offset_.y(), bump_height_ / 2.0}; }
            /**
             * @brief Get the radius of the sphere of every individual bump bond (union solid with cylinder)
             * @return Radius of bump bond sphere
             */
            double getBumpSphereRadius() const { return bump_sphere_radius_; }
            /**
             * @brief Get the radius of the cylinder of every individual bump bond  (union solid with sphere)
             * @return Radius of bump bond cylinder
             */
            double getBumpCylinderRadius() const { return bump_cylinder_radius_; }
            /**
             * @brief Get the height of the bump bond cylinder, determining the offset between sensor and chip
             * @return Height of the bump bonds
             */
            double getBumpHeight() const { return bump_height_; }

        private:
            double bump_sphere_radius_{};
            double bump_height_{};
            ROOT::Math::XYVector bump_offset_;
            double bump_cylinder_radius_{};
        };

        class MonolithicAssembly : public DetectorAssembly {
        public:
            MonolithicAssembly(const ConfigReader& reader) : DetectorAssembly(reader) {
                auto config = reader.getHeaderConfiguration();

                // Excess around the chip is copied from sensor size
                auto default_assembly_excess = config.get<double>("sensor_excess", 0);
                excess_.at(0) = config.get<double>("sensor_excess_top", default_assembly_excess);
                excess_.at(1) = config.get<double>("sensor_excess_right", default_assembly_excess);
                excess_.at(2) = config.get<double>("sensor_excess_bottom", default_assembly_excess);
                excess_.at(3) = config.get<double>("sensor_excess_left", default_assembly_excess);
            }

        private:
        };

        /**
         * @brief Constructs the base detector model
         * @param type Name of the model type
+1 −1
Original line number Diff line number Diff line
@@ -358,7 +358,7 @@ void DetectorConstructionG4::build(const std::shared_ptr<G4LogicalVolume>& world
        geo_manager_->setExternalObject(name, "supports_phys", supports_phys);

        // Build the bump bonds only for hybrid pixel detectors
        auto hybrid_chip = std::dynamic_pointer_cast<DetectorModel::HybridAssembly>(model->getAssembly());
        auto hybrid_chip = std::dynamic_pointer_cast<HybridAssembly>(model->getAssembly());
        if(hybrid_chip != nullptr) {

            /**
+1 −1
Original line number Diff line number Diff line
@@ -50,7 +50,7 @@ static double compute_model_relative_radlength(const DetectorModel& model) {
    add("chip", X0_SI, model.getChipSize().z());

    // compute contributions from bumps if available
    const auto* hybrid = dynamic_cast<const DetectorModel::HybridAssembly*>(model.getAssembly().get());
    const auto* hybrid = dynamic_cast<const HybridAssembly*>(model.getAssembly().get());
    if(hybrid != nullptr) {
        // average the bump material over the full pixel size.
        auto bump_radius = std::max(hybrid->getBumpSphereRadius(), hybrid->getBumpCylinderRadius());