Improve Pulse Object
Status Quo
We had some trouble with code requesting to add very late contributions to a pulse object, leading to excessive vector lengths and bad allocation exceptions (see e.g. this MR and probably also this forum thread ).
Ways Forward
There are two ways of dealing with this:
- Make the storage of pulses sparse, i.e. introduce a different container as storage e.g. a map of time bins to pulse bin content. The advantage of this is that very late contributions can be added without allocating lots of zeros in between. The downside is that it requires a lot more memory for dense (i.e. not-sparse) pulses. Also, it doesn't easily decay to a vector-like object but would require a wrapper class for that. This approach is being followed here: https://gitlab.cern.ch/allpix-squared/allpix-squared/-/tree/sparse_pulse
- Properly catch and handle OOM/BadAlloc situations when adding charge. This is what this MR does. Advantage: we really have proper contiguous vector storage of the pulse, efficient for dense objects. Disadvantage is that we require a lot of (useless) memory if we have sparse and long pulses.
This Implementation
Let's discuss which approach is better.
This MR improves the currently implemented pulse gently by:
- directly inheriting from
std::vector
instead of having one as member. This allows to directly iterate over it but - in its current form - also provides direct access to all parent methods. This we might want to constrain a bit. - catching
std::bad_alloc
and rethrowingPulseBadAlloc
with some additional information - adding a second constructor which attempts to reserves the full pulse length at construction, making it more efficient in situations where we already know the total pulse length (
integration_time
hello!)