Commit f9ebd69e authored by Elio Sacchetti's avatar Elio Sacchetti
Browse files

Merge branch allpix-squared:master into f-spice-netlist

parents 9b9b5127 a7d5b6af
Loading
Loading
Loading
Loading
+24 −16
Original line number Diff line number Diff line
@@ -146,10 +146,15 @@ void DepositionPointChargeModule::initialize() {
        }

        // Check that the scan setup is correct
        root_ = events;
        events_per_cell_ = config_.get<unsigned int>("events_per_cell", 1);
        if(events % events_per_cell_ != 0) {
            LOG(WARNING) << "Number of events cannot be divided into cells evenly";
        }

        root_ = static_cast<unsigned int>(std::ceil(events / static_cast<double>(events_per_cell_)));
        if(no_of_coordinates_ == 2) {
            root_ = static_cast<unsigned int>(std::lround(std::sqrt(events)));
            if(events != root_ * root_) {
            root_ = static_cast<unsigned int>(std::lround(std::sqrt(events / events_per_cell_)));
            if(events != root_ * root_ * events_per_cell_) {
                LOG(WARNING) << "Number of events is not a square, pixel cell volume cannot fully be covered in scan. "
                             << "Closest square is " << root_ * root_;
            }
@@ -160,8 +165,8 @@ void DepositionPointChargeModule::initialize() {
                                        "The coordinates must be x, y, or z, and a coordinate must not be repeated");
            }
        } else if(no_of_coordinates_ == 3) {
            root_ = static_cast<unsigned int>(std::lround(std::cbrt(events)));
            if(events != root_ * root_ * root_) {
            root_ = static_cast<unsigned int>(std::lround(std::cbrt(events / events_per_cell_)));
            if(events != root_ * root_ * root_ * events_per_cell_) {
                LOG(WARNING) << "Number of events is not a cube, pixel cell volume cannot fully be covered in scan. "
                             << "Closest cube is " << root_ * root_ * root_;
            }
@@ -218,6 +223,10 @@ void DepositionPointChargeModule::run(Event* event) {
        // Fixed position as read from the configuration:
        position = position_;
    } else if(model_ == DepositionModel::SCAN) {
        // Voxel iterator depends on number of events per cell:
        // Note: this implicitly throws away the fractional part of the number, which is desirable in this case
        const auto voxel_it = (event->number - 1) / events_per_cell_;

        // Center the volume to be scanned in the center of the sensor,
        // reference point is lower left corner of one pixel volume
        auto ref = position_ + detector_model_->getMatrixSize() / 2.0 + voxel_ / 2.0 -
@@ -226,27 +235,26 @@ void DepositionPointChargeModule::run(Event* event) {
                                         detector_model_->getSensorSize().z() / 2.0);
        LOG(DEBUG) << "Reference: " << Units::display(ref, {"um", "mm"});
        if(no_of_coordinates_ == 3) {
            position =
                ROOT::Math::XYZPoint(voxel_.x() * static_cast<double>((event->number - 1) % root_),
                                     voxel_.y() * static_cast<double>(((event->number - 1) / root_) % root_),
                                     voxel_.z() * static_cast<double>(((event->number - 1) / root_ / root_) % root_)) +
            position = ROOT::Math::XYZPoint(voxel_.x() * static_cast<double>(voxel_it % root_),
                                            voxel_.y() * static_cast<double>((voxel_it / root_) % root_),
                                            voxel_.z() * static_cast<double>((voxel_it / root_ / root_) % root_)) +
                       ref;
        } else {
            position = ref;
            if(scan_x_) {
                position.SetX(voxel_.x() * static_cast<double>((event->number - 1) % root_) + ref.x());
                position.SetX(voxel_.x() * static_cast<double>(voxel_it % root_) + ref.x());
                if(scan_y_) {
                    position.SetY(voxel_.y() * static_cast<double>(((event->number - 1) / root_) % root_) + ref.y());
                    position.SetY(voxel_.y() * static_cast<double>((voxel_it / root_) % root_) + ref.y());
                } else if(scan_z_) {
                    position.SetZ(voxel_.z() * static_cast<double>(((event->number - 1) / root_) % root_) + ref.z());
                    position.SetZ(voxel_.z() * static_cast<double>((voxel_it / root_) % root_) + ref.z());
                }
            } else if(scan_y_) {
                position.SetY(voxel_.y() * static_cast<double>((event->number - 1) % root_) + ref.y());
                position.SetY(voxel_.y() * static_cast<double>(voxel_it % root_) + ref.y());
                if(scan_z_) {
                    position.SetZ(voxel_.z() * static_cast<double>(((event->number - 1) / root_) % root_) + ref.z());
                    position.SetZ(voxel_.z() * static_cast<double>((voxel_it / root_) % root_) + ref.z());
                }
            } else {
                position.SetZ(voxel_.z() * static_cast<double>((event->number - 1) % root_) + ref.z());
                position.SetZ(voxel_.z() * static_cast<double>(voxel_it % root_) + ref.z());
            }
        }
        LOG(DEBUG) << "Deposition position in local coordinates: " << Units::display(position, {"um", "mm"});
+1 −1
Original line number Diff line number Diff line
@@ -99,7 +99,7 @@ namespace allpix {
        double spot_size_{};
        ROOT::Math::XYZVector voxel_;
        double step_size_{};
        unsigned int root_{}, carriers_{};
        unsigned int root_{}, events_per_cell_{1}, carriers_{};
        ROOT::Math::XYZVector position_{};
        ROOT::Math::XYZVector mip_direction_{};
        std::vector<std::string> scan_coordinates_{};
+2 −1
Original line number Diff line number Diff line
@@ -21,7 +21,7 @@ Two different source types are available:
This module supports three different deposition models:

* In the `fixed` model, charge carriers are always deposited at exactly the same position, specified via the `position` parameter, in every event of the simulation. This model is mostly interesting for development of new charge transport algorithms, where the initial position of charge carriers should be known exactly.
* In the `scan` model, the position where charge carriers are deposited changes with every event. The scanning positions are distributed such, that the volume of one pixel cell is homogeneously scanned. The total number of positions is taken from the total number of events configured for the simulation. If this number doesn't allow for a full illumination, a warning is printed, suggesting a different number of events. The pixel volume to be scanned is always placed at the center of the active sensor area. The scan model can be used to generate sensor response templates for fast simulations by generating a lookup table from the final simulation results.
* In the `scan` model, the position where charge carriers are deposited changes with every event. The scanning positions are distributed such that the volume of one pixel cell is homogeneously scanned. The total number of positions is taken from the total number of events configured for the simulation. If this number doesn't allow for a full illumination, a warning is printed, suggesting a different number of events. The pixel volume to be scanned always has its bottom left corner placed at the center of the active sensor area. The `scan` model can be used to generate sensor response templates for fast simulations by generating a lookup table from the final simulation results.
* In the `spot` model, charge carriers are deposited in a Gaussian spot around the configured position. The sigma of the Gaussian distribution in all coordinates can be configured via the `spot_size` parameter. Charge carriers are only deposited inside the active sensor volume.

Monte Carlo particles are generated at the respective positions, bearing a particle ID of -1.
@@ -36,6 +36,7 @@ All charge carriers are deposited at time zero, i.e. at the beginning of the eve
* `position`: Position in local coordinates of the sensor, where charge carriers should be deposited. Expects three values for local-x, local-y and local-z position in the sensor volume and defaults to `0um 0um 0um`, i.e. the center of first (lower left) pixel. When using source type `mip`, providing a 2D position is sufficient since it only uses the x and y coordinates. If used in scan mode, it allows you to shift the origin of each deposited charge by adding this value. If the scan is only performed in one or two dimensions, the remaining coordinate will constantly have the value given by `position`.
* `spot_size`: Width of the Gaussian distribution used to smear the position in the `spot` model. Only one value is taken and used for all three dimensions.
* `scan_coordinates`: Coordinates to scan over, a combination of x, y, z. Only used for the `scan` model. Defaults to `x y z`, i.e. all three spatial coordinates. The `position` parameter is used to determine the value of the coordinates that are not scanned over if a partial scan is requested, and the start offset of the scan for the other coordinates.
* `events_per_cell`: Number of events simulated in each voxel cell of the scan, Only used with `model = scan`, defaults to `1`. It should be noted that this setting does not change the total `number_of_events` to be simulated, this needs to be increased by the same proportion.
* `mip_direction`: Vector giving the direction of the line along which deposits are made when the `mip` source type is used. Defaults to `0 0 1`, i.e. along the z-axis. The `position` keyword gives a point that the line of depositions will cross through with this direction.

### Plotting parameters