Add an SOA fitted track container
The below is lifted from the description of !2668 (merged):
LHCb::Pr::Fitted::Forward::Tracks
only stores the x-x
, x-tx
, tx-tx
, y-y
, y-ty
and ty-ty
elements of a covariance matrix -- the q/p-q/p
diagonal element and many off-diagonal elements are not stored.
- When looping over this container, the proxy class has to return a full matrix. For the off-diagonal elements that were not stored, it returns zero. But the q/p error was a fudged value (this is not really specific to the proxies, the same thing was done in converters) -- a fixed relative error.
- The change in !2668 (merged) is/was just to change the fudge factor to better reflect the real distribution.
- This is important because in "HLT2" the selections are based on a zip that includes
LHCb::Pr::Fitted::Forward::Tracks
, and the q/p error that is assumed makes a significant difference some selection variables derived from composite particles. For example, the IPCHI2 (and therefore PV association) of composites was significantly affected. - Making the fudged value "more realistic" makes the effect smaller, but fundamentally does not address the issue.
The real fix is to add a fitted track container that can store relevant information. There have been some discussions of this, including here and here (plus the minutes of those meetings).
Suggested content of this container (@olupton summary/suggestion):
- Track type (enum, single value set at container level)
- Variable number of states, where the number is set at container construction time
- At container level, a list of type enum values for these states (ClosestToBeam, FirstMeasurement etc.)
- Each state contains a full 5D state vector (
x
,y
,t_x
,t_y
,q/p
) with covariance matrix, and az
coordinate, so the track container has21 \times N_{\text{states}}
32-bit float columns
-
\chi^2
andN_{\text{d.o.f.}}
of the fit - Some link to a "full track fit result", e.g. the track container could have a
Zipping::ZipFamilyNumber
identifying the container of "full track fit results" output by the track fit, and there could be a column containing indices into this container. -
LHCbID
s for the track, possibly split into sub-ranges (i.e. separated by subdetector)- It seems these are used often enough that having to navigate to these via, for example, the "full track fit result" is not a good option
- The simplest solution (A) is to add
N_{\text{max. LHCbIDs}}
integer columns, plus a column giving the actual number.N_{\text{max. LHCbIDs}}
could be specified at container creation time (and, if this actually helps, reduced when the container is filtered), so this is not as inefficient as always allocating for the worst conceivable case. - Alternatively (B), the
LHCbID
storage could be separate, and the track data could just contain indices to the first/last IDs in that storage. There is a sketch of what this could look like, but no full implementation. This scheme is more complicated but more compact if the max/mean number of hits differ significantly. - It was suggested that hits could be stored directly, instead of
LHCbID
s. It's not clear to @olupton what subdetector-universal format could be used for this, and supporting heterogenous hit types could quickly get complex and import subdetector-specific knowledge into the fitted track container (at least in the simplest extension of A) - An analogue of B might be more appealing (but perhaps still not very appealing, given the coupling of track and hit data structures). Note that this requires non-trivial copy operations like these
struct Tracks : public SOACollection<Tracks, ...> /* main one-row-per-track storage including indices into sub-detector hit containers */ {
std::tuple<VeloHits, UTHits, SciFiHits, ...> m_hits{};
};
Optional extras:
- Some link to the ancestor of the track.
cc: @sstahl @nnolte @wouter @jonrob @ldufour @apearce @mvesteri
Edited by Olli Lupton