xAODs, templating in accessor methods

Hi all,

for visualisation I want to write a small “track browser” in pyROOT on xAOD basis.

To get the measurements and local track states, < T >auxdata( cost char* ) is called as method of a track particle.
I wonder how to pythonise the call…

The snippet looks as follows:

std::vector< u_uint64 > getHitIds ( const xAOD::TrackParticle* tp  )
{
    static const char* measurementNames = "msosLink";
    typedef std::vector<ElementLink< xAOD::TrackStateValidationContainer > > MeasurementsOnTrack;
    const MeasurementsOnTrack& measurementsOnTrack = ( tp )->auxdata< MeasurementsOnTrack > ( measurementNames );
    [...]

The MeasurementsOnTrack statement can be transformed into somewhat like

but then the exception what(): SG::ExcConstAuxData: Non-const operation `fetch item' performed on const aux data `::msosLink' (344).
is thrown…

Hi,

python does not consider ‘const’, so will pick up whatever method comes first. I remember a discussion with Attila about this when the auxillary store was just being designed, but I don’t think a solution was ever implemented. Methods have a ‘disp’ method to select a specific overload, but currently that, too, ignores const on the method, so it’d have to be on one of the arguments to enable selection.

Cheers,
Wim

Hi Wim,

Attila replied to an email, I will quote them completely:

[quote]Attila Krasznahorkay wrote:
Hi Manuel,

There are multiple issues here.

As you suspected, you can’t use auxdata in PyROOT. Since Python doesn’t have a concept of const/non-const, when you call the auxdata<…>(…) function, that always gets forwarded to the non-const function. Which is most often not what you want.

For this reason the base class also includes a function called auxdadaConst<…>(…). Which you should be able to call from PyROOT like:

trackParticle = …
pt = trackParticle.auxdataConst( “float” )( “pt” )

Now, the problem is that you can only use “string type names” in this formalism that describe types for which a dictionary was compiled for this template function. We do build a fair number of dictionaries by default, but of course we can’t do it for custom types like “std::vector<ElementLinkxAOD::TrackStateValidationContainer >”. So you won’t be able to call this function just like that… :frowning:

At this point you have two choices. You could build a dictionary for this template specialisation of SG::AuxElement::auxdataConst<…>(…). Similar to how all the other template types are set up in the AthContainers package.

svnweb.cern.ch/trac/atlasoff/br … Dict.h#L96

Although I have to admit that I’m not even sure how easy it is to do this really. I’m not sure if it’s even possible to build the dictionary for a template function separately from the library that holds its class.

So I think the second choice is a much easier one. Where you create a helper function for yourself in C++ that retrieves these objects in some format that Python can easily deal with. Because remember: ElementLink-s are also very difficult to handle in all their glory in Python…

I could imagine a function like:

xAOD::TrackStateValidationContainer measurementsOnTrack( const xAOD::TrackParticle* tp ) {

// Get the ElementLink-s from the track particle:
typedef std::vector< ElementLink< xAOD::TrackStateValidationContainer > >
MeasurementsOnTrack;
static const SG::AuxElement::ConstAccessor< MeasurementsOnTrack >
acc( “measurementsOnTrack” );
const MeasurementsOnTrack& meas = acc( *tp );

// Set up a view container for the objects:
ConstDataVector< xAOD::TrackStateValidationContainer > result( SG::VIEW_ELEMENTS );
result.reserve( meas.size() );

// Fill it:
for( const auto& el : meas ) {
result.push_back( *el );
}

// Return it:
return *( result.asDataVector() );
}

Building a dictionary for this function would be fairly easy. Since xAOD::TrackStateValidationContainer has its own dictionary already, you don’t need to worry about that.

In the end, you’d use the function in PyROOT like:

trackParticle = …
measurements = ROOT.xAODHelpers.measurementsOnTrack( trackParticle )
for meas in measurements:

(This of course assumes that you put the “measurementsOnTrack” function into the “xAODHelpers” namespace.)

Cheers,
Attila
[/quote]

[quote]On Fri, May 20, 2016 at 4:41 PM, Manuel Neumann mneumann@cern.ch wrote:
Hi all,

to write a track browser in pyROOT, I need to access the track states and measurements.
In C++ this is nor problem at all, but the statement

typedef std::vector<ElementLink< xAOD::TrackStateValidationContainer > > MeasurementsOnTrack;
const MeasurementsOnTrack& measurementsOnTrack = ( tp )->auxdata< MeasurementsOnTrack ( measurementNames );

can not so easy translated into pyROOT.

It seems possible to write the target type as string like
auxdata( 'std::vector<ElementLinkxAOD::TrackStateValidationContainer > > ’ )( “msosLink” );

terminate called after throwing an instance of ‘SG::ExcConstAuxData’
what(): SG::ExcConstAuxData: Non-const operation fetch item' performed on const aux data::msosLink’ (344).
Aborted (core dumped)

but the operation fails. I’m not sure, but it seems related to the
target variable, which is of course non const.

Maybe someone has an idea… maybe one auxData is not needed anymore…

Ciao and thanks for reading,
Manuel[/quote]

Manuel,

with the caveat that this statement from Atilla:[quote]As you suspected, you can’t use auxdata in PyROOT. Since Python doesn’t have a concept of const/non-const, when you call the auxdata<…>(…) function, that always gets forwarded to the non-const function. Which is most often not what you want.[/quote]
is incomplete. Other than for setItem (which requires a non-const return), PyROOT simply chooses overloads in declared order, so it does NOT always forward to the non-const function. Just only if that is the first function in the class definition.

Cheers,
Wim

at some point the workaround has been moved to __getitem__() so:

before:

jet.auxdataConst("int")("HadronConeExclTruthLabelID")

now:

jet.auxdataConst["int"]("HadronConeExclTruthLabelID")