Commit 9beef140 authored by Håkan Wennlöf's avatar Håkan Wennlöf
Browse files

Added warnings for unused keywords in the detector geometry definition.

Did this by passing along a reference to the header configuration (i.e. the empty section). This way, it gets updated when keys are used.
Also added check in the individual implant and support sections.
parent 7c91eb77
Loading
Loading
Loading
Loading
+7 −1
Original line number Diff line number Diff line
@@ -80,7 +80,13 @@ void ConfigManager::parse_detectors() {

    std::ifstream detector_file(detector_file_name);
    ConfigReader detector_reader(detector_file, detector_file_name);
    auto detector_configs = detector_reader.getConfigurations();
    auto detector_configs =
        detector_reader
            .getConfigurations(); // Holds all the sub-configs of the detector geometry file definition. Like [implant]
    LOG(ERROR) << "Number of sub-headers: " << detector_configs.size();
    for(auto& conf : detector_configs) {
        LOG(ERROR) << "Name: " << conf.getName();
    }
    detector_configs_ = std::list<Configuration>(detector_configs.begin(), detector_configs.end());
}

+1 −1
Original line number Diff line number Diff line
@@ -98,7 +98,7 @@ namespace allpix {
        unsigned int countConfigurations(std::string name) const;

        /**
         * @brief Get cmobined configuration of all empty sections (usually the header)
         * @brief Get combined configuration of all empty sections (usually the header)
         * @note Typically this is only the section at the top of the file
         * @return Configuration object for the empty section
         */
+21 −23
Original line number Diff line number Diff line
@@ -31,11 +31,10 @@ namespace allpix {
         * Detector assembly constructor
         * @param reader  ConfigReader holding the full detector model configuration
         */
        explicit DetectorAssembly(const ConfigReader& reader) {
            auto config = reader.getHeaderConfiguration();
        explicit DetectorAssembly(Configuration& header_config) {

            // Chip thickness
            thickness_ = config.get<double>("chip_thickness", 0);
            thickness_ = header_config.get<double>("chip_thickness", 0);
        }

        ///@{
@@ -84,25 +83,25 @@ namespace allpix {
         * Constructor for hybrid assemblies
         * @param reader  ConfigReader holding the full detector model configuration
         */
        explicit HybridAssembly(const ConfigReader& reader) : DetectorAssembly(reader) {
            auto config = reader.getHeaderConfiguration();
        explicit HybridAssembly(Configuration& header_config) : DetectorAssembly(header_config) {

            // Excess around the chip from the pixel grid
            auto default_assembly_excess = config.get<double>("chip_excess", 0);
            excess_.at(0) = config.get<double>("chip_excess_top", default_assembly_excess);
            excess_.at(1) = config.get<double>("chip_excess_right", default_assembly_excess);
            excess_.at(2) = config.get<double>("chip_excess_bottom", default_assembly_excess);
            excess_.at(3) = config.get<double>("chip_excess_left", default_assembly_excess);
            auto default_assembly_excess = header_config.get<double>("chip_excess", 0);
            excess_.at(0) = header_config.get<double>("chip_excess_top", default_assembly_excess);
            excess_.at(1) = header_config.get<double>("chip_excess_right", default_assembly_excess);
            excess_.at(2) = header_config.get<double>("chip_excess_bottom", default_assembly_excess);
            excess_.at(3) = header_config.get<double>("chip_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);
            bump_cylinder_radius_ = header_config.get<double>("bump_cylinder_radius");
            bump_height_ = header_config.get<double>("bump_height");
            bump_sphere_radius_ = header_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});
            auto pitch = header_config.get<ROOT::Math::XYVector>("pixel_size");
            bump_offset_ = header_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");
                throw InvalidValueError(
                    header_config, "bump_offset", "bump bond offset cannot be larger than half pixel pitch");
            }
        }

@@ -155,15 +154,14 @@ namespace allpix {
         * Constructor for monolithic assemblies
         * @param reader  ConfigReader holding the full detector model configuration
         */
        explicit MonolithicAssembly(const ConfigReader& reader) : DetectorAssembly(reader) {
            auto config = reader.getHeaderConfiguration();
        explicit MonolithicAssembly(Configuration& header_config) : DetectorAssembly(header_config) {

            // 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);
            auto default_assembly_excess = header_config.get<double>("sensor_excess", 0);
            excess_.at(0) = header_config.get<double>("sensor_excess_top", default_assembly_excess);
            excess_.at(1) = header_config.get<double>("sensor_excess_right", default_assembly_excess);
            excess_.at(2) = header_config.get<double>("sensor_excess_bottom", default_assembly_excess);
            excess_.at(3) = header_config.get<double>("sensor_excess_left", default_assembly_excess);
        }
    };
} // namespace allpix
+62 −27
Original line number Diff line number Diff line
@@ -22,72 +22,87 @@
using namespace allpix;

std::shared_ptr<DetectorModel> DetectorModel::factory(const std::string& name, const ConfigReader& reader) {
    Configuration config = reader.getHeaderConfiguration();
    Configuration header_config = reader.getHeaderConfiguration();

    // Sensor geometry
    // FIXME we might want to deprecate this default at some point?
    if(!config.has("geometry")) {
        LOG(WARNING) << "Model file " << config.getFilePath() << " does not provide a geometry parameter, using default";
    if(!header_config.has("geometry")) {
        LOG(WARNING) << "Model file " << header_config.getFilePath()
                     << " does not provide a geometry parameter, using default";
    }
    auto geometry = config.get<std::string>("geometry", "pixel");
    auto geometry = header_config.get<std::string>("geometry", "pixel");

    // Assembly type
    if(!config.has("type")) {
        LOG(FATAL) << "Model file " << config.getFilePath() << " does not provide a type parameter";
    if(!header_config.has("type")) {
        LOG(FATAL) << "Model file " << header_config.getFilePath() << " does not provide a type parameter";
    }
    auto type = config.get<std::string>("type");
    auto type = header_config.get<std::string>("type");

    std::shared_ptr<DetectorAssembly> assembly;
    if(type == "hybrid") {
        assembly = std::make_shared<HybridAssembly>(reader);
        assembly = std::make_shared<HybridAssembly>(header_config);
    } else if(type == "monolithic") {
        assembly = std::make_shared<MonolithicAssembly>(reader);
        assembly = std::make_shared<MonolithicAssembly>(header_config);
    } else {
        LOG(FATAL) << "Model file " << config.getFilePath() << " type parameter is not valid";
        throw InvalidValueError(config, "type", "model type is not supported");
        LOG(FATAL) << "Model file " << header_config.getFilePath() << " type parameter is not valid";
        throw InvalidValueError(header_config, "type", "model type is not supported");
    }

    // Instantiate the correct detector model
    std::shared_ptr<DetectorModel> model;
    if(geometry == "pixel") {
        model = std::make_shared<PixelDetectorModel>(name, assembly, reader);
        model = std::make_shared<PixelDetectorModel>(name, assembly, reader, header_config);
    } else if(geometry == "radial_strip") {
        model = std::make_shared<RadialStripDetectorModel>(name, assembly, reader);
        model = std::make_shared<RadialStripDetectorModel>(name, assembly, reader, header_config);
    } else if(geometry == "hexagonal") {
        model = std::make_shared<HexagonalPixelDetectorModel>(name, assembly, reader);
        model = std::make_shared<HexagonalPixelDetectorModel>(name, assembly, reader, header_config);
    } else {
        LOG(FATAL) << "Model file " << config.getFilePath() << " geometry parameter is not valid";
        LOG(FATAL) << "Model file " << header_config.getFilePath() << " geometry parameter is not valid";
        // FIXME: The model can probably be silently ignored if we have more model readers later
        throw InvalidValueError(config, "geometry", "model geometry is not supported");
        throw InvalidValueError(header_config, "geometry", "model geometry is not supported");
    }

    // Validate the detector model - we call this here because validation might depend on derived class properties:
    model->validate();

    auto unused_keys = header_config.getUnusedKeys();
    if(!unused_keys.empty()) {
        std::stringstream st;
        st << "Unused configuration keys in global section in sensor geometry definition:";
        for(auto& key : unused_keys) {
            st << std::endl << key;
        }
        LOG(WARNING) << st.str();
    }

    return model;
}

DetectorModel::DetectorModel(std::string type, std::shared_ptr<DetectorAssembly> assembly, ConfigReader reader)
DetectorModel::DetectorModel(std::string type,
                             std::shared_ptr<DetectorAssembly> assembly,
                             ConfigReader reader,
                             Configuration& header_config)
    : type_(std::move(type)), assembly_(std::move(assembly)), reader_(std::move(reader)) {
    using namespace ROOT::Math;
    auto config = reader_.getHeaderConfiguration();
    LOG(ERROR) << "Address of header_config DetectorModel constructor: " << &header_config;

    // Sensor thickness
    setSensorThickness(config.get<double>("sensor_thickness"));
    setSensorThickness(header_config.get<double>("sensor_thickness"));

    // Excess around the sensor from the pixel grid
    auto default_sensor_excess = config.get<double>("sensor_excess", 0);
    setSensorExcessTop(config.get<double>("sensor_excess_top", default_sensor_excess));
    setSensorExcessBottom(config.get<double>("sensor_excess_bottom", default_sensor_excess));
    setSensorExcessLeft(config.get<double>("sensor_excess_left", default_sensor_excess));
    setSensorExcessRight(config.get<double>("sensor_excess_right", default_sensor_excess));
    auto default_sensor_excess = header_config.get<double>("sensor_excess", 0);
    setSensorExcessTop(header_config.get<double>("sensor_excess_top", default_sensor_excess));
    setSensorExcessBottom(header_config.get<double>("sensor_excess_bottom", default_sensor_excess));
    setSensorExcessLeft(header_config.get<double>("sensor_excess_left", default_sensor_excess));
    setSensorExcessRight(header_config.get<double>("sensor_excess_right", default_sensor_excess));

    // Sensor material:
    sensor_material_ = config.get<SensorMaterial>("sensor_material", SensorMaterial::SILICON);
    sensor_material_ = header_config.get<SensorMaterial>("sensor_material", SensorMaterial::SILICON);

    // Issue a warning for pre-3.0 implant definitions:
    if(config.has("implant_size")) {
        LOG(WARNING) << "Parameter \"implant_size\" of model " << config.getFilePath() << " not supported," << std::endl
    if(header_config.has("implant_size")) {
        LOG(WARNING) << "Parameter \"implant_size\" of model " << header_config.getFilePath() << " not supported,"
                     << std::endl
                     << "Individual [implant] sections must be used for implant definitions";
    }

@@ -100,6 +115,16 @@ DetectorModel::DetectorModel(std::string type, std::shared_ptr<DetectorAssembly>
        auto orientation = implant_config.get<double>("orientation", 0.);

        addImplant(imtype, shape, size, offset, orientation, implant_config);

        auto unused_keys = implant_config.getUnusedKeys();
        if(!unused_keys.empty()) {
            std::stringstream st;
            st << "Unused configuration keys in [implant] section in sensor geometry definition:";
            for(auto& key : unused_keys) {
                st << std::endl << key;
            }
            LOG(WARNING) << st.str();
        }
    }

    // Read support layers
@@ -129,6 +154,16 @@ DetectorModel::DetectorModel(std::string type, std::shared_ptr<DetectorAssembly>
                        std::move(location),
                        hole_size,
                        std::move(hole_offset));

        auto unused_keys = support_config.getUnusedKeys();
        if(!unused_keys.empty()) {
            std::stringstream st;
            st << "Unused configuration keys in [support] section in sensor geometry definition:";
            for(auto& key : unused_keys) {
                st << std::endl << key;
            }
            LOG(WARNING) << st.str();
        }
    }
}

+5 −1
Original line number Diff line number Diff line
@@ -180,8 +180,12 @@ namespace allpix {
         * @param type Name of the model type
         * @param assembly Detector assembly object with information about ASIC and packaging
         * @param reader Configuration reader with description of the model
         * @param reader Configuration holding the empty section of the configuration file
         */
        explicit DetectorModel(std::string type, std::shared_ptr<DetectorAssembly> assembly, ConfigReader reader);
        explicit DetectorModel(std::string type,
                               std::shared_ptr<DetectorAssembly> assembly,
                               ConfigReader reader,
                               Configuration& header_config);

        /**
         * @brief Essential virtual destructor
Loading