Skip to content

Commit 442d782

Browse files
committed
Updated README.md
1 parent b00f86a commit 442d782

File tree

3 files changed

+54
-27
lines changed

3 files changed

+54
-27
lines changed

README.md

+53-27
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,9 @@ SimSiPM is distrubuted as an Open Source project and if you plan to use it pleas
3232

3333
## <a name="introduction"></a>Introduction
3434
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.
35-
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.
35+
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 allowing to choose the most suitable product available on the market.
3636

37-
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.
37+
SimSiPM code follows FCCSW rules and guidelines concerning C++. SimSiPM has been developed especially for high-energy physics and particle physics experiments, however its flexibility allows to simulate any kind of experiments involving SiPM devices.
3838

3939
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".
4040

@@ -45,22 +45,23 @@ SimSiPM does not have any major external dependency making it the perfect candid
4545
- Easy to use:
4646
- Straight forward installation without external dependencies
4747
- Easy to use Object Oriented paradigm
48-
- Python implementation
48+
- Python implementation via Pybind11
4949
- Description of SiPM sensors:
50-
- Based on datasheet values or measurable quantities
50+
- Driven by parameters that can be obtained from the datasheet or laboratory measurements
5151
- High level of customization allowing to describe a wide range of use cases
5252
- Does not include tedious electronic circuit simulations
5353
- High performance:
5454
- Very fast signal generation
55+
- Reliable description of SiPM signals and related quantities over all the dynamic range
5556
- Low memory footprint (if you do not intend to save all waveforms!)
5657

5758

5859
## <a name="installation"></a>Installation
59-
SimSiPM has not external dependencies other than CMake.
60+
SimSiPM is fully functional without any external dependencies other than CMake.
6061
#### Optional dependencies:
6162
- Pybind11: to generate python bindings
62-
- OpenMP: for multi-core simulations
6363
- Doxygen: to generate documentation
64+
- GTest/Pytest: for advanced testing
6465

6566
### <a name="c++install"></a>C++
6667
SimSiPM can be installed using the standard CMake workflow:
@@ -70,19 +71,31 @@ cmake -B build -S .
7071
make -C build
7172
make -C build install
7273
```
73-
Installation directory can be specified with `-DCMAKE_INSTALL_PREFIX` variable.
74-
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.
74+
It is advisable to enable compiler optimizations like `-O3` and `-mfma -mavx2` since some parts of code are specifically written using intrinsic functions for vectorization.
75+
76+
Installation directory can be specified with `-DCMAKE_INSTALL_PREFIX` variable.
77+
78+
Python bindings can be compiled and installed by adding the variable `-DCOMPILE_PYTHON_BINDINGS=ON` but this requires Pybind11.
79+
The corresponding python module is called `SiPM` and each class can be accessed as a sub-module.
80+
81+
```py
82+
import SiPM
83+
from SiPM import SiPMSensor
84+
85+
print(SiPM.__version__)
86+
```
87+
7588

7689
### <a name="pyinstall"></a>Python
77-
It is also possible to install only the python version via pip but performance might not be as good as the source code version:
90+
It is also possible to use pip to install only the Python version using a precompiled binary wheel. This installation method is easyer but performance may be impaired with respect to the C++/Pybind11 installation.
7891
```sh
7992
pip install SiPM
8093
```
8194

8295
## <a name="C++_basic_usage"></a>C++ basic use
83-
96+
SimSiPM focuses on simplicity! It does not make use of pointers, or custom classes as parameters of the simulation or input. In most cases a std::vector is all that you need in order to get started.
8497
### SiPMProperties
85-
SiPMProperties object stores all SiPM and simulation parameters
98+
SiPMProperties class stores all SiPM and simulation parameters. It can be used to define the SiPM detector model in use and it can be shared among different SiPMs in case many identical sensors are needed.
8699
```cpp
87100
#include "SiPMProperties.h"
88101
using namespace sipm;
@@ -96,7 +109,7 @@ myProperties.setPropery("Xt",0.03); // Using parameter name
96109
```
97110

98111
### SiPMSensor
99-
SiPMSensor object is used to store photons and generate signals
112+
SiPMSensor class is the core of the simulation and is created from a SiPMProperties class. It stores input photoelectrons, it runs the event simulation and gives a signal as output.
100113
```cpp
101114
#include "SiPMProperties.h"
102115
using namespace sipm;
@@ -109,8 +122,17 @@ mySensor.properties().setAp(0.01); // Using proper getter/setter
109122
mySensor.setProperty("Pitch", 25); // Using parameter name
110123
```
111124
125+
### SiPMAnalogSignal
126+
SiPMAnalogSignal class is a wrapper around std::vector that expands its features. It contains the samples of the SiPM waveform along with some properties and methods used to extract features from the signal.
127+
```cpp
128+
SiPMAnalogSignal signal = mySensor.signal();
129+
double sampling = signal.sampling();
130+
double sample = signal[10];
131+
```
132+
112133
### Input and simulation
113-
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.
134+
The only input needed for the simulation of a SiPM event is the arriving time of each photon to the sensitive surface of the SiPM detector.
135+
In order to have a detailed description of the dependency of the PDE with respect to the photon wavelength it is possible to add the wavelength information togheter with the time information.
114136

115137
It is possible to add individual photons in a loop
116138
```cpp
@@ -131,7 +153,7 @@ mySensor.runEvent(); // Runs the simulation
131153
```
132154
133155
### Signal output and signal features
134-
After running the simulation the signal can be retrieved:
156+
The simulation can output the signal waveform and can also perform some simple features extraction.
135157
```cpp
136158
SiPMAnalogSignal mySignal = mySensor.signal();
137159
@@ -142,15 +164,16 @@ double tot = signal.tot(5,250,0.5); // (intStart, intGate, threshold)
142164
143165
// It is possible to iterate throw an analog signal
144166
for(int i=0;i<mySignal.size();++i){
145-
// Do something with mySignal[i]
167+
double sample = mySignal[i]
168+
// Do something with sample
146169
}
147170
148171
// It is possible to convert an analog signal to a simple vector
149172
std::vector<double> waveform = mySignal.waveform();
150173
```
151174

152175
### Complete event loop
153-
A typical event loop would look like:
176+
This is an example of "stand-alone" usage of SimSiPM. In case SimSiPM is used in Geant4 or other framework, then the generation of photon times has to be caryed by the user (usually in G4UserSteppingAction) and the event has to be simulated after all photons have been added (usually in G4UserEventAction).
154177
```cpp
155178
// Create sensor and set parameters
156179
SiPMProperties myProperties;
@@ -177,7 +200,7 @@ for(int i=0;i<NEVENTS;++i){
177200
}
178201
```
179202
## <a name="python_basic_usage"></a>Python basic use
180-
Python bindings are generated using Pybind11 so the usage is very similar to C++ but with python syntax.
203+
Python bindings are generated for all the classes using Pybind11. This allows for an almost 1:1 mapping of the C++ functionalities in Python.
181204
182205
```python
183206
from SiPM import SiPMSensor, SiPMProperties
@@ -198,9 +221,9 @@ integral = mySignal.integral(10,250,0.5)
198221
## <a name="adv"></a>Advanced use
199222
### <a name="pde"></a>PDE
200223
#### No Pde
201-
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.
224+
Tracking a large number of photons throwgh a scintillator crystal or optical fiber is a very CPU-intensive task. Since most of photons will not be detected due to photon detection efficiency (PDE) it is a waste of time to track all of them.
202225

203-
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!
226+
By default SiPM sensors have PDE set to 100% meaning that every photon given as input is converted to a photoelectron, detected and generates a signal. This allows to generate and track 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, so PDE is evaluated before the tracking of photons.
204227

205228
#### Simple PDE
206229
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.
@@ -216,13 +239,13 @@ mySensor.setProperty("Pde",0.27); // or mySensor.properties().setPde(0.27);
216239
To revert back at default setting of 100% PDE use `setPdeType(sipm::SiPMProperties::PdeType::kSimplePde)`
217240

218241
#### Spectral PDE
219-
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.
242+
In 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.
220243
This can be done by feeding the SiPM settings with two arrays containing wavelengths and corresponding PDEs.
221244

222245
In this case it is also necessary to input photon wavelength along with its time.
223246
```cpp
224-
std::vector<double> wlen = {300, 400, 500, 600, 700, 800};
225-
std::vector<double> pde = {0.01, 0.20, 0.33, 0.27, 0.15, 0.05};
247+
std::vector<double> wlen = {800, 750, 700, 650, 600, 550, 500, 450, 400, 350, 300};
248+
std::vector<double> pde = {0.22, 0.30, 0.40, 0.45, 0.50, 0.50, 0.45, 0.35, 0.25, 0.15, 0.0};
226249

227250
myProperties.setPdeType(sipm::SiPMProperties::PdeType::kSpectrumPde);
228251
myProperties.setPdeSpectrum(wlen,pde);
@@ -237,27 +260,30 @@ mySensor.addPhoton(photonTime, photonWlen);
237260
```
238261
<p align="center"><img src="images/pde.png" width=500></p>
239262
240-
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.
263+
The input values for PDE given by the user are interpolated using the formula below to obtain additional 25 values over the given range. Then, during the simulation, values are linearly interpolated between the points of the newly obtained curve.
264+
265+
<p align="center"><img src="images/interpolation.svg" width=400></p>
266+
241267
242268
### <a name="hit"></a>Hit distribution
243-
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.
269+
By default photoelectrons hits are considered to be uniformly distributed 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.
244270
245271
#### Uniform hit distribution
246-
This is the default setting. Each SiPM cell has the same probability to be hitted.
272+
This is the default setting: each SiPM cell has the same probability to be hitted. This setting should work in most of scenarios.
247273
```cpp
248274
myPropertie.setHitDistribution(sipm::SiPMProperties::HitDistribution::kUniform);
249275
```
250276

251277
#### Circular hit distribution
252-
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.
278+
In this case 90% 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 10% is distributed outside this circle. This setting resembles those cases where light is focused in the central region.
253279
<p align="center"><img src="images/circleHits.png" width=250></p>
254280

255281
```cpp
256282
myPropertie.setHitDistribution(sipm::SiPMProperties::HitDistribution::kCircle);
257283
```
258284

259285
#### Gaussian hit distribution
260-
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.
286+
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.
261287
<p align="center"><img src="images/gaussianHits.png" width=250></p>
262288

263289
```cpp

0 commit comments

Comments
 (0)