EDM4hep in Julia

Prototype of the EDM4hep (generic Event Data Model for HEP experiments part of Key4hep) for Julia with the goal to have very simple structures (isbits) with the purpose to evaluate its ergonomic design and implementation performance.

PODIO generation

The Julia POD structs should be generated from the edm4hep.yaml yaml file using PODIO scripts.

For the time being, for this evaluation, the Julia structs are generated by a local Julia script in ./podio/generate.jl. The files genComponents/jl and genDatatypes.jl are fully generated.

Main design features

  • All EDM4hep entities are immutable structs and containing basic types and structs. Including the relationships (one-to-one and one-to-many) and vector members. Objects attributes cannot be changed. This makes the objects with the isbits(obj) == true.

  • Objects are created by default not being registered, they are free floating. The user can register them with register(obj).

  • Note that operations like register, setting relationships (add_daughter,...), etc. will automatically create a new instance. The typical pattern is to overwrite the user variable with the new instance, e.g.:

    p1 = MCParticle(...)
    p1 = register(p1)
    p1, d1 = add_daughter(p1, MCParticle(...))
  • The main goal for reading EDM4hep containers from a ROOT file is to obtain as result a StructArray(see StructArrays.jl documentation). This provides a very efficient access by column and the same time provide a convenient views as object instances. For example if you want to sum the momentum of a range of MCParticles the user should be able to write:

    julia> mcparticles = get(reader,...)
    julia> mcparticles[5:8].momentum
    4-element StructArray(::Vector{Float32}, ::Vector{Float32}, ::Vector{Float32}) with eltype Vector3f:
      (0.8740664,-0.002116337,124.84335)
      (0.8602309,-0.056633994,-124.632545)
      (-0.00012483617,0.0021162117,0.0026654897)
      (0.014539731,0.05663412,-0.32755017)
    
    julia> sum(mcparticles[5:8].momentum)
      (1.7487122,0.0,-0.11407688)

Roadmap

There are a number of issues and problems still to be resolved. We keep track of them in this list:

  • Need to generate and support VectorMembers. For the time being are ignored. - DONE
  • Handle cyclic datatype dependencies. In EDM4hep there is one case that is not yet resolved. Vertex depends on ReconstructedParticle in a one-to-one relation and ReconstructedParticle relates to Vertex. Using the abstract class POD in this case works well to break the cycle. - DONE
  • Better handle collectionID in one-to-many relations - DONE
  • Be able to read RNTuple files in addition to TTree files - DONE
  • Generate doc string with member information - DONE
  • Generate accessors for one-to-many relations, vector members - DONE
  • Support latest version (RC2) of RNTuple format - DONE
  • Support for multi-threading (i.e. be able to add @threads in the event loop) - DONE

Tests

Unit tests can be run with julia --project=. test/runtests.jl

Examples

examples/mcparticle_tree.jl

Creates a collection of MCParticles and a collection of SimTrackerHits in memory, constructing the relations between particle parents and daughters, as well as, the one-to-one relation between each simulation hit and its originating MCParticle.

examples/read_example.jl

An example of reading from a ROOT file created by the C++ implementation of EDM4hep. This is the full code:

using EDM4hep
using EDM4hep.RootIO

cd(@__DIR__)
f = "ttbar_edm4hep_digi.root"

reader = RootIO.Reader(f)
events = RootIO.get(reader, "events")

evt = events[1];

hits = RootIO.get(reader, evt, "InnerTrackerBarrelCollection")
mcps = RootIO.get(reader, evt, "MCParticle")

for hit in hits
    println("Hit $(hit.index) is related to MCParticle $(hit.mcparticle.index) with name $(hit.mcparticle.name)")
end

for p in mcps
    println("MCParticle $(p.index) $(p.name) with momentum $(p.momentum) and energy $(p.energy) has $(length(p.daughters)) daughters")
    for d in p.daughters
        println("   ---> $(d.index) $(d.name) and momentum $(d.momentum) has $(length(d.parents)) parents")
        for m in d.parents
            println("      ---> $(m.index) $(m.name)")
        end 
    end
end

examples/FCC/analysis_mH-recoil.jl

This is basically the example higgs/mH-recoil/mumu from FCCAnalyses. It shows in a realistic manner how to develop analysis functions using the Data Types from EDM4hep to created high-level analysis functions. The Jupyter notebook analysis_mH-recoil.ipynb shows the same example in form of a notebook.

examples/FCC/analysis_MT.jl

This is basically the example higgs/mH-recoil/mumu from FCCAnalyses in a multi-threaded mode. The Jupyter notebook analysis_mH-recoil.ipynb shows the same example in form of a notebook.

EDM4hep Data Model

This is the diagram for the EDM4hep datamodel including relationships.

Figure