WIP: Make PackTrack functional
Making PackTrack functional so that tracks can be packed and persisted in Moore.
Note that
- Removed checking functionality
EnableCheck
- Removed delete input functionality
DeleteInput
- Removed
AlwaysCreateOutput
option
Merge request reports
Activity
added all-slots label
removed all-slots label
- Resolved by Nicole Skidmore
- Resolved by Nicole Skidmore
- Resolved by Nicole Skidmore
/ci-test --merge
added ci-test-triggered label
- [2020-09-12 10:42] Validation started with lhcb-master-mr#1300
- [2020-09-14 12:45] Validation started with lhcb-master-mr#1308
Edited by Software for LHCb- Resolved by Nicole Skidmore
why not go one step further and make this a
Gaudi::Functional::Transformer
?
@graven Is this what you had in mind? It builds and runs just as the datahandle version did. For my knowledge is the namespace name chosen
namespace LHCb::Converters::PackedTrack
deliberately to match
#include "Event/PackedTrack.h"
Kind of yes ;-)
Basically, there are already several algorithms that 'convert' data from one representation to another (eg. Track V2 to Track v2, or 'Pr' tracks to Track V1 or V2, see eg. code here) And the convention kind of is to enclose them in
LHCb::Converters
(because they convert things), and then indicate the 'target' type, which is the most relevant for any downstream code, and then indicate some way the 'from' type...
- Resolved by Nicole Skidmore
/ci-test --merge
mentioned in issue Moore#204 (closed)
Getting errors in Brunel
AttributeError: Configurable 'PackTrack' does not have property 'EnableCheck'.
Edited by Nicole SkidmoreThat's not surprising, as those properties were removed -- so any bit of code trying to set them should be adapted. I suspect that:
diff --git a/GaudiConf/python/GaudiConf/DstConf.py b/GaudiConf/python/GaudiConf/DstConf.py index 5462aa65b..7ed833c2e 100644 --- a/GaudiConf/python/GaudiConf/DstConf.py +++ b/GaudiConf/python/GaudiConf/DstConf.py @@ -313,12 +313,7 @@ class DstConf(LHCbConfigurableUser): # Pack tracks if they were not read from the input file... if "Tracking" not in self.getProp("EnableUnpack"): - packDST.Members += [ - PackTrack( - name="PackTracks", - AlwaysCreateOutput=alwaysCreate, - EnableCheck=doChecks) - ] + packDST.Members += [ PackTrack( name="PackTracks") ] # for Run2, add packed Velo tracks if ((self.getProp("DataType") in self.Run2DataTypes) and (self.getProp("PVPersistence") is "RecVertex")): @@ -394,10 +389,9 @@ class DstConf(LHCbConfigurableUser): packDST.Members += [ PackTrack( name="PackMuonTracks", - AlwaysCreateOutput=alwaysCreate, InputName="/Event/Rec/Track/Muon", OutputName="/Event/pRec/Track/Muon", - EnableCheck=doChecks) + ) ] # In MDF case, add a sub sequence for the MDF writing
should do the trick...
Indeed. But note that that property used to drive the following code:
// Packing checks if ( UNLIKELY( m_enableCheck ) ) { // make new unpacked output data object LHCb::Tracks* unpacked = new LHCb::Tracks(); put( unpacked, m_inputName + "_PackingCheck" ); // unpack packer.unpack( *out, *unpacked ); // run checks packer.check( *tracks, *unpacked ).ignore(); // clean up after checks StatusCode sc = evtSvc()->unregisterObject( unpacked ).andThen( [&] { delete unpacked; } ); if ( sc.isFailure() ) return sc; }
(interesting how it first registers something in the TES, only to remove it afterwards...)
So if we want a replacement for that I would propose to make a separate
Gaudi::Functional::Consumer<void(const LHCb::Tracks&)>
algorithm (given that these algorithms are only a handful of lines of code):namespace LHCb::Packers::Check { struct TrackPacker : Gaudi::Functional::Consumer<void(const LHCb::Tracks&)> { TrackPacker( const std::string& name, ISvcLocator* pSvcLocator ) : Consumer::Consumer{name, pSvcLocator, KeyValue{"InputName", TrackLocation::Default} }{} void operator()(const LHCb::Tracks& in) const override { auto packer = LHCb::TrackPacker{this}; LHCb::PackedTracks packed; packer.pack( in, packed ); LHCb::Tracks unpacked; packer.unpack( packed, unpacked ); packer.check( in, unpacked ).orThrow( "Packing check failed", name() ); } }; DECLARE_COMPONENT_WITH_ID( TrackPacker, "CheckTrackPacker" ) }
and then add that algorithm where previously
EnableCheck
would be enabled... that moves an 'if' from run time to configuration time, which is always a good thing IMHO.Now, one could perhaps wonder whether a properly written, dedicated unit test for just the packer would not be a better / sufficient solution, instead of parasitically random sampling the phase space of tracks 'on the fly' inside of some larger job, but let's keep that discussion for another occasion...
Aside: if the
pack()
, andunpack()
methods wouldreturn *this
i.e. return a reference to their instance, instead of beingvoid
, you could write it as a daisy chain:LHCb::Tracks unpacked; LHCb::PackedTracks packed; LHCb::TrackPacker{this}.pack( in, packed) .unpack(packed, unpacked) .check( in, unpacked).orThrow("Packing check failed", name());
Edited by Gerhard RavenYou may question the way in which the check was implemented, but this was to all intents and purposes a unit test of the packing and unpacking that was implemented as close to the code as could possibly be (and which was run by the author on large statistics samples whenever he made a change). We have for good reasons changed the way in which we test our code, but if you remove this, you should definitely implement an equivalent unit test.
Looking a bit in the configuration it turns out that we do run these checks in Brunel's xdst-to-xdst test (on 10 events, but still something). There the
Brunel().Histograms="Expert"
is set, which in turn means that the packing checks are enabled.Since all of this persistence machinery is likely to change, I would suggest to keep the checking in the simplest possible way for now. This means adding back the
EnableCheck
property, and copy-pasting and adapting the call to the check that was removed. You should be able to simplify it on the way and avoid putting a temporary container on the TES by changing it to something like this:if ( UNLIKELY( m_enableCheck ) ) { LHCb::Tracks unpacked; packer.unpack( out, unpacked ); packer.check( tracks, unpacked ).ignore(); }
(does
put
have a side effect that the old code relied on?)
mentioned in merge request Moore!619 (merged)
80 const StatusCode sc = evtSvc()->unregisterObject( tracks ).andThen( [&] { 81 delete tracks; 82 tracks = nullptr; 83 } ); 84 if ( sc.isFailure() ) return sc; 85 } else { 86 // Clear the registry address of the unpacked container, to prevent reloading 87 auto* pReg = tracks->registry(); 88 if ( pReg ) pReg->setAddress( nullptr ); 15 #include "GaudiAlg/Transformer.h" 16 17 /** @class PackTrack PackTrack.h 18 * 19 * Pack track container 20 * 21 * @author Olivier Callot Hi @nskidmor, this is effectively a new algo. I would replace Callot's name by yours at this point. He left a decade-ish ago, BTW ... And better write a relevant date too.
added modernisation label
assigned to @nskidmor
I'd say we can close it. We've made good progress in Moore without needing the changes here. Do you agree @nskidmor?
unassigned @nskidmor
mentioned in merge request !3081 (closed)