Library for Silicon Photomultipliers simulation.
Project description
SimSiPM
Authors
SimSiPM has been developed by Edoardo Proserpio under the supervision of professor Romualdo Santoro at University of Insubria Como - Italy.
SimSiPM is distrubuted as an Open Source project and if you plan to use it please acknowledge us as authors or cite us in your paper.
Table of contents
Introduction
SimSiPM is a simple and easy to use C++ library providing a set of object-oriented tools with all the functionality needed to describe and simulate Silicon PhotonMultipliers (SiPM) sensors. The main goal of SimSiPM is to include the response of SiPM sensors, along with noise and saturation effects, in the description of a generic detector in order to have a more detailed simulation. It can also be used to perform optimization studies considering different SiPMs models.
SimSiPM has beed developed following FCCSW C++ rules and guidelines and it is focused on SiPM simulation for high-energy physics and particle physics experiments however its flexibility allows to simulate any kind of experiments involving SiPM devices.
SimSiPM does not have any major external dependency making it the perfect candidate to be used in an already existing environment (Geant4 or DD4HEP) or as "stand-alone".
Features
- Easy to use:
- Straight forward installation without external dependencies
- Easy to use Object Oriented paradigm
- Python implementation
- Description of SiPM sensors:
- Based on datasheet values or measurable quantities
- High level of customization allowing to describe a wide range of use cases
- Does not include tedious electronic circuit simulations
- High performance:
- Very fast signal generation
- Low memory footprint (if you do not intend to save all waveforms!)
Installation
SimSiPM has not external dependencies other than CMake.
Optional dependencies:
- Pybind11: to generate python bindings
- OpenMP: for multi-core simulations
- Doxygen: to generate documentation
C++
SimSiPM can be installed using the standard CMake workflow:
# In SimSiPM directory
cmake -B build -S .
make -C build
make -C build install
Installation directory can be specified with -DCMAKE_INSTALL_PREFIX
variable.
Python bindings can be installed in the default python site-packages path by adding the variable -DCOMPILE_PYTHON_BINDINGS=ON
but this requires Pybind11 to be installed.
Python
It is also possible to install only the python version via pip but performance might not be as good as the source code version:
pip install SiPM
C++ basic use
SiPMProperties
SiPMProperties object stores all SiPM and simulation parameters
#include "SiPMProperties.h"
using namespace sipm;
// Create a SiPMProperties object
SiPMProperties myProperties;
// Edit some parameters
myProperties.setDcr(250e3); // Using proper setter
myProperties.setPropery("Xt",0.03); // Using parameter name
SiPMSensor
SiPMSensor object is used to store photons and generate signals
#include "SiPMProperties.h"
using namespace sipm;
// Create a SiPMSensor object
SiPMSensor mySensor(myProperties);
// Change parameters
mySensor.properties().setAp(0.01); // Using proper getter/setter
mySensor.setProperty("Pitch", 25); // Using parameter name
Input and simulation
Input of the simulation is either the arriving time of a photon on the SiPM surface or both the arriving time of the photon and its wavelength.
It is possible to add individual photons in a loop
mySensor.resetState();
for(...){
// Generate times for photons
mySensor.addPhoton(time); // Appends a single photon (time is in ns)
}
mySensor.runEvent(); // Runs the simulation
It is also possible to add all photons at once
std::vector<double> times = {13.12, 25.45, 33.68};
mySensor.resetState();
mySensor.addPhotons(times); // Sets photon times (times are in ns) (not appending)
mySensor.runEvent(); // Runs the simulation
Signal output and signal features
After running the simulation the signal can be retrieved:
SiPMAnalogSignal mySignal = mySensor.signal();
double integral = signal.integral(5,250,0.5); // (intStart, intGate, threshold)
double peak = signal.peak(5,250,0.5); // (intStart, intGate, threshold)
double toa = signal.toa(5,250,0.5); // (intStart, intGate, threshold)
double tot = signal.tot(5,250,0.5); // (intStart, intGate, threshold)
// It is possible to iterate throw an analog signal
for(int i=0;i<mySignal.size();++i){
// Do something with mySignal[i]
}
// It is possible to convert an analog signal to a simple vector
std::vector<double> waveform = mySignal.waveform();
Complete event loop
A typical event loop would look like:
// Create sensor and set parameters
SiPMProperties myProperties;
SiPMSensor mySensor(myProperties);
// ...
// Store results in here
std::vector<double> integral(NEVENTS);
// peak
// ...
for(int i=0;i<NEVENTS;++i){
// Generate photons times accordingly
// to your experimental setup
mySensor.resetState();
mySensor.addPhotons(times);
mySensor.runEvent();
SiPMAnalogSignal mySignal = mySensor.signal();
integral[i] = signal.integral(10,250,0.5);
// peak
// ...
}
Python basic use
Python bindings are generated using Pybind11 so the usage is very similar to C++ but with python syntax.
from SiPM import SiPMSensor, SiPMProperties
myProperties = SiPMProperties()
myProperties.setDcr(250e3)
myProperties.setProperty("Xt",0.03)
mySensor = SiPMSensor(myProperties)
mySensor.resetState()
mySensor.addPhotons([13.12, 25.45, 33.68])
mySensor.runEvent()
mySignal = mySensor.signal()
integral = mySignal.integral(10,250,0.5)
Advanced use
PDE
No Pde
Tracking a large number of photons is a CPU intensive task and since most of photons will not be detected due to photon detection efficiency (PDE) it would be a waste of time.
By default SiPM sensors have PDE set to 100% meaning that every photon is converted to a photoelectron and detected. This allows to generate only the photons that will be detected by the sensor. For example the geometry of IDEA dual-readout calorimeter requires the simulation of 130 millions of optical fibers and in each one of those photons are tracked by Geant4 requiring a lot of CPU time. It would be meaningless to track photons along the fibers if they are not detected!
Simple PDE
It is possible to account for PDE in the simulation using a fixed value of PDE for all photons. In this case the probability to detect a photon is proportional to PDE. This option can be used if the spectrum of emitted photons is very narrow or if the SiPM has a wide and flat spectral response.
// Set in SiPMProperties
myProperties.setPdeType(sipm::SiPMProperties::PdeType::kSimplePde);
myProperties.setPde(0.27);
// Change setting of a sensor
mySensor.properties().setPdeType(sipm::SiPMProperties::PdeType::kSimplePde);
mySensor.setProperty("Pde",0.27); // or mySensor.properties().setPde(0.27);
To revert back at default setting of 100% PDE use setPdeType(sipm::SiPMProperties::PdeType::kSimplePde)
Spectral PDE
In some SiPM sensors PDE strongly depends on photon wavelength. In some cases it might be necessary to consider the spectral response of the SiPM for a more accurate simulation. This can be done by feeding the SiPM settings with two arrays containing wavelengths and corresponding PDEs.
In this case it is also necessary to input photon wavelength along with its time.
std::vector<double> wlen = {300, 400, 500, 600, 700, 800};
std::vector<double> pde = {0.01, 0.20, 0.33, 0.27, 0.15, 0.05};
myProperties.setPdeType(sipm::SiPMProperties::PdeType::kSpectrumPde);
myProperties.setPdeSpectrum(wlen,pde);
// or using a std::map
// std::map<double,double> wlen_pde = {{300, 0.01}, {400, 0.20}, {500, 0.33}, ...};
// myProperties.setPdeSpectrum(wlen_pde);
// Adding photons to the sensor
mySensor.addPhoton(photonTime, photonWlen);
// or mySensor.addPhotons(photonTimes, photonWlens);
The values inserted by the user are linearly interpolated to calculate the PDE for each wavelength so it is better to add a reasonable number of values.
Hit distribution
By default photoelectrons are considered to be distributed uniformly on the surface of the SiPM. In most cases this assumption resembles what happens in a typical setup but sometimes the geometry of the sensor or the optical characteristics of the setup lead to an inhomogeneous distribution of the light on the sensor's surface.
Uniform hit distribution
This is the default setting. Each SiPM cell has the same probability to be hitted.
myPropertie.setHitDistribution(sipm::SiPMProperties::HitDistribution::kUniform);
Circular hit distribution
In this case 95% of photons are placed in a circle centered in the sensor and with a diameter that is the same as the sensor's side lenght. The remaining 5% is distributed uniformly on the sensor.
myPropertie.setHitDistribution(sipm::SiPMProperties::HitDistribution::kCircle);
Gaussian hit distribution
In this case 95% of the photons are distributed following a gaussian distribution centered in the sensor. The remaining 5% is distributed uniformly on the sensor.
myPropertie.setHitDistribution(sipm::SiPMProperties::HitDistribution::kGaussian);
Contributing
SimSiPM is being developed in the contest of FCCSW and IDEA Dual-Readout Calorimeter Software. I am the main responsible for development and maintainment of this project. Feel free to contact me if you have any problem while including SimSiPM in your project, if you find a bug or have any suggestion or improvement. I would be pleased to discuss it with you.
Cite
Even thou SimSiPM has been used in simulations related to published articles, there is not yet an article about SimSiPM itself. So if you need to cite SimSiPM please use:
@manual{,
title = {{SimSiPM: a library for SiPM simulation}},
author = {Edoardo, Proserpio and Romualdo, Santoro},
address = {Como, Italy},
year = 2021,
url = {https://github.com/EdoPro98/SimSiPM}
}
Contacts
Author: Edoardo Proserpio
Email: edoardo.proserpio@gmail.com (private)
Email: eproserpio@studenti.uninsubria.it (instiutional)
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distributions
Hashes for SiPM-1.2.4-pp37-pypy37_pp73-manylinux2010_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | a6c486c40b18e87cafe2cbe01a0a529041fee1ca375ce0d0f4d5b13e4e1f3f92 |
|
MD5 | 254bbd6b583c0fc8aa691c9ba121f8f6 |
|
BLAKE2b-256 | 1efddfd18cf349dc7a94b7f71c875aaefb0d242dd3b5539c46fe48bd41cd9785 |
Hashes for SiPM-1.2.4-pp37-pypy37_pp73-macosx_10_9_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 35872863b83151aeecd84c39d3f924ecec47100346e18331b0b0c2ab8fda9079 |
|
MD5 | 3c36f47a01bff7d5cb7b0c8b3f5cf60d |
|
BLAKE2b-256 | 2e941a45116dfbfc566ef87b1b9e43c3b1e7acfed915159313c526462c100d00 |
Hashes for SiPM-1.2.4-pp36-pypy36_pp73-manylinux2010_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 2b34b91e575357c9a0f15e6e64098f01ba61c162cb86cf46b0a4c8b6aaa2b284 |
|
MD5 | 57edd07a83066710244572f3b2f50ed0 |
|
BLAKE2b-256 | eda68d78c092e87d9a003e504b613590ef8d31201fda168e9c28ebf7d44ff3fe |
Hashes for SiPM-1.2.4-pp36-pypy36_pp73-macosx_10_9_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 36a1f13998f0cbfa438f7cf1585a7167cb7e0755790e1f02c95eedc0d2809d47 |
|
MD5 | 8b0f4e2c5cddc9298243839e304989fe |
|
BLAKE2b-256 | 2c53d2241f369b9fb0d3376ca61222d3d29c571f54e7cbe7ac44f1e621d311a9 |
Hashes for SiPM-1.2.4-cp39-cp39-manylinux2010_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 742547f49c94148b5a0e3a77f50695f261e044a11c5e0d783979865423225b79 |
|
MD5 | a6d514019c3af1b8c6e28eacaf959952 |
|
BLAKE2b-256 | 1b7456df9dc38fbf6da1f3e07cf6d81fa921b92c56d953b2a7b3d743e642c184 |
Hashes for SiPM-1.2.4-cp39-cp39-macosx_11_0_arm64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 74a624cd00ab8b9e4b65d503da20886bd6063d4d9b68243af9eb9bb0b12ba1a0 |
|
MD5 | 95ca42bb23f2729af8eafd1faf82bf0d |
|
BLAKE2b-256 | bfccacd5cddbad7b7a0d0f66783c41e6af408524128edf5eccaf4d9ba7eade2a |
Hashes for SiPM-1.2.4-cp39-cp39-macosx_10_9_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | e490e688709256556518df4f771792b82f0787a01eaba1ad43281b85d66339bd |
|
MD5 | 64368ecc64f0572ef670fbc5628ca8ec |
|
BLAKE2b-256 | 8e8cecc47b3ac38b6bfdbe7c9e9903ab2e43d197073db4bed4c232d6e7ddcc3c |
Hashes for SiPM-1.2.4-cp39-cp39-macosx_10_9_universal2.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 14f3e09c77574ae4b07d20bee58fc06912338b5bec9dfcc2d4b2b0c8969de0a8 |
|
MD5 | d0118b4f4219bb6a66804d2b60b80003 |
|
BLAKE2b-256 | 611fc70d7d3c3c3eaa2c00968e9ba2807459c010659f8d8273a08086d540ad8b |
Hashes for SiPM-1.2.4-cp38-cp38-manylinux2010_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 171ae32bdf0e8c1ea20ec69ece6aff255c95db142a0ecee27095bd8ea3323358 |
|
MD5 | 16987af751187aff039750cf2ea470d0 |
|
BLAKE2b-256 | 969d35491f8598011d2c70089587c7fc154bec5cdb037166e0cd7e5bb7d70212 |
Hashes for SiPM-1.2.4-cp38-cp38-macosx_10_9_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | bd7021c134ee1da651e6fd524503482a63e0e4ee126769dd41a61a7e6923a545 |
|
MD5 | 00bafa7804130d3e02850af0d13e48bf |
|
BLAKE2b-256 | b6e063e43c4d4fc708c67f9873d477555b9841636885458e9a1e13f1a960ba19 |
Hashes for SiPM-1.2.4-cp37-cp37m-manylinux2010_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 84706418a482634a3d4ff4e231ad25077b9dd8b01307d45944e7997dbd668573 |
|
MD5 | 4677d7efef3e5a16d9caf48c31abd968 |
|
BLAKE2b-256 | 14acb81197096c125b96f7e90b2425976f6c9b117724ac366663bcf0596de4db |
Hashes for SiPM-1.2.4-cp37-cp37m-macosx_10_9_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 60798fdff61fd0e780307e9929bc33f4cc562aeaeabeba0ea6361e9ba1f7a1e4 |
|
MD5 | 1e78d9233cfdc99674ae7b90010e3234 |
|
BLAKE2b-256 | 9d40e626086433be7eb8ec12e050c6b6b1fe238d708837813805037b2855a99c |
Hashes for SiPM-1.2.4-cp36-cp36m-manylinux2010_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 12871a532ffd9a5b8ef24ef4f6b38bba089b8437baa7c42b951882c5a0d0280c |
|
MD5 | d31e70fe8036f7fd5f4f6f4adb635d19 |
|
BLAKE2b-256 | 561fac54f23bf1a589e8180bd4fee24710df8015a5ab8a4356628ca5bb0bfe02 |
Hashes for SiPM-1.2.4-cp36-cp36m-macosx_10_9_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 8d28c3989e0c1b4293547cc5ad9a5dbad198fbf0e75f9b64e03039d529d168af |
|
MD5 | a3477123a27eb56c129028661ffeb13e |
|
BLAKE2b-256 | 30de1f544ec7ec55972353247ce2341892b023f9a86728c2a86305f828d8ba7c |
Hashes for SiPM-1.2.4-cp35-cp35m-manylinux2010_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | edfdffde53891cfb45996d7ebbf40163e5d8d11ace21108c93d0d4441e23ebd6 |
|
MD5 | 194ae6dc16cad27d548e22da662d9dd9 |
|
BLAKE2b-256 | 563ff120685a9f80740dc7355fe7566e449e7b66fde0de8533023a0305e2ad71 |
Hashes for SiPM-1.2.4-cp35-cp35m-macosx_10_9_x86_64.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | 3b7eec27e25a5c95893c23b499801ca4af83948a40fd1007a9b43cf76da376bf |
|
MD5 | 74c0f8a973592ae2fbdcd7513b8f4d79 |
|
BLAKE2b-256 | 92201ac5617084905bef9f69161ff1d71ca7204a7891bdb833dd48e0c32d36bb |