Skip to content

Data Format ​

CSV files are written by eic2ai, a single-pass C++ converter that reads an eicrecon file (.edm4eic.root) and, when a role needs it, the paired npsim file (.edm4hep.root) once, and writes one CSV per role. The rows are identical to those of the older csv_convert/ ROOT macros (except the shared Λ decay codes and the added truth_* block of reco_dis); the column names follow one shared vocabulary (below).

eic2ai --list-columns prints the header of every role, eic2ai --list-writers the collections each role reads. The tables on this page follow the writer sources in eic2ai/src/writer_*.hpp.

Files ​

<stem>.<role>.csv.zip     default: one deflate ZIP64 entry named <stem>.<role>.csv
<stem>.<role>.csv         --compress none
<stem>.<role>.csv.gz      --compress gz

<stem> is the reco file name without .eicrecon.edm4eic.root or .edm4eic.root (the sim file name without .edm4hep.root in sim-only runs), so k_lambda_18x275_5000evt_0022.edm4eic.root gives k_lambda_18x275_5000evt_0022.trk_hits.csv.zip. pandas reads the zip directly.

A role whose writer fails leaves no file; a file that exists is complete.

Column vocabulary ​

Every column is <prefix>_<quantity>, and evt (the entry counter of the input file) is the join key of every role.

PrefixObject
prtthe MC particle behind a hit, cluster or row
trk_hitreconstructed tracker hit
cal_hitdigitized calorimeter hit
clucalorimeter cluster
recreconstructed particle
simsimulation truth aggregated over a calorimeter cell

Units: GeV, GeV/c, mm, ns, rad, charge in e.

Signal or background: prt_origin ​

ValueMeaning
0unknown
1signal particle from the generator
2Geant4 secondary of a signal particle
3background particle from the generator
4Geant4 secondary of a background particle

The background merger adds a source-specific offset (a multiple of 1000, see Backgrounds) to the generator status of background particles before Geant4 runs. Generator particles are classified by prt_gen_status (1 or 2 signal, >= 1000 background); Geant4 secondaries (prt_gen_status = 0) take the class of their first generator ancestor up the parent chain.

Roles ​

RoleOne row perNeeds
trk_hitsreconstructed tracker hit, with its MC particlereco
cal_hitsdigitized calorimeter hit, truth-labeled from the sim cellreco + sim
calo_clusterscluster ↔ MC particle associationreco
mc_particlesMC particlereco
reco_particlesreconstructed particlereco
mc_disevent: generator DIS kinematicsreco
event_indexprocessed eventany
reco_disevent: reconstructed DIS kinematics by seven methods, with truthreco
mcpart_lambda, lambda_acceptance, reco_ff_lambda, acceptance_ppim, acceptance_npi0, combinatorics_ppim, comb_candidatesΛ analysis tablesreco or sim

The Λ and DIS roles serve the Meson Structure analyses; their columns are listed by eic2ai --list-columns.

trk_hits ​

One row per tracker hit association (raw hit → sim hit → MC particle), joined with the reconstructed hit. Hits from these association collections:

B0TrackerRawHitAssociations            OuterMPGDBarrelRawHitAssociations
BackwardMPGDEndcapRawHitAssociations   RICHEndcapNRawHitsAssociations
ForwardMPGDEndcapRawHitAssociations    SiBarrelRawHitAssociations
ForwardOffMTrackerRawHitAssociations   SiBarrelVertexRawHitAssociations
ForwardRomanPotRawHitAssociations      SiEndcapTrackerRawHitAssociations
MPGDBarrelRawHitAssociations           TOFBarrelRawHitAssociations
TOFEndcapRawHitAssociations
ColumnTypeUnitDescription
evtuint64entry counter
hit_indexuint64index of the hit association in its collection
prt_indexuint64index of the particle in MCParticles
prt_pdgint32PDG code (11 e⁻, 211 π⁺, 2212 p, …)
prt_gen_statusint32generator status: 1 or 2 from the generator, 0 created by Geant4
prt_originint32signal or background
prt_energydoubleGeVtotal energy
prt_chargefloateelectric charge
prt_mom_x/y/zdoubleGeV/cmomentum
prt_vtx_timefloatnstime at the production vertex
prt_vtx_pos_x/y/zfloatmmproduction vertex
prt_end_timefloatnsequal to prt_vtx_time (EDM4hep stores one particle time)
prt_end_pos_x/y/zfloatmmendpoint
trk_hit_cell_iduint64full cellID of the reconstructed hit
trk_hit_system_iduint64detector system id (bits 0–7 of the cellID)
trk_hit_system_namestringdetector name, e.g. VertexBarrel_0 (Unknown for ids outside the table)
trk_hit_pos_x/y/zfloatmmreconstructed hit position
trk_hit_timefloatnsreconstructed hit time
trk_hit_pos_err_xx/yy/zzfloatmm²position variances
trk_hit_time_errfloatnstime uncertainty
trk_hit_edepfloatGeVenergy deposited in the sensor
trk_hit_edep_errfloatGeVenergy deposit uncertainty

cal_hits ​

One row per digitized calorimeter hit. The reco file has no calorimeter hit ↔ particle association, so each hit is matched by (evt, cellID) to the sim hit of the same cell in the paired .edm4hep.root file. A cell with several contributing particles gets the prt_origin of the energy-majority class, label_purity = that class's energy fraction, and the prt_* block of the largest contributor of that class. A hit whose cell has no sim hit keeps its features with prt_origin = 0 and zeros in the prt_* block.

Calorimeters: EcalBarrelScFiRecHits, EcalBarrelImagingRecHits, EcalEndcapNRecHits, EcalEndcapPRecHits, HcalBarrelRecHits, HcalEndcapNRecHits, HcalEndcapPInsertRecHits, LFHCALRecHits, B0ECalRecHits, EcalFarForwardZDCRecHits, HcalFarForwardZDCRecHits.

ColumnTypeUnitDescription
evtuint64entry counter
cal_hit_collectionstringrec-hit collection name (the detector)
cal_hit_cell_iduint64full cellID (same cell in sim and reco)
cal_hit_system_iduint64detector system id (bits 0–7 of the cellID)
cal_hit_system_namestringdetector name
cal_hit_pos_x/y/zfloatmmhit position
cal_hit_energyfloatGeVcalibrated energy
cal_hit_energy_errfloatGeVenergy uncertainty
cal_hit_timefloatnsdigitized time
cal_hit_time_errfloatnstime uncertainty
sim_energydoubleGeVsum of the cell's contribution energies (raw deposit)
sim_timefloatnsearliest contribution time
n_contribint32contributions in the cell
label_purityfloatenergy fraction of the majority origin class
prt_indexuint64representative particle in the sim file's MCParticles
prt_pdg, prt_gen_status, prt_originint32as in trk_hits
prt_energydoubleGeVtotal energy
prt_chargefloateelectric charge
prt_mom_x/y/zdoubleGeV/cmomentum
prt_vtx_timefloatnstime at the production vertex
prt_vtx_pos_x/y/zfloatmmproduction vertex
prt_end_pos_x/y/zfloatmmendpoint

The cal_hit_* columns are the detector-level features; sim_*, n_contrib, label_purity and prt_* are truth.

calo_clusters ​

One row per cluster ↔ MC particle association, from a fixed list of 27 *ClusterAssociations collections (regular, truth and split-merge clusters of the ECAL, HCAL, B0, ZDC and luminosity calorimeters); collections absent from a file are skipped.

ColumnTypeUnitDescription
evtuint64entry counter
clu_indexuint64index of the association in its collection
clu_collectionstringassociation collection name (detector + algorithm)
prt_index … prt_end_pos_x/y/zthe particle block of trk_hits (with prt_end_time)
clu_first_cell_iduint64cellID of the first constituent hit (0 when none resolves)
clu_system_iduint64detector system id of that cellID
clu_system_namestringdetector name (Unknown when no hit resolves)
clu_typeint32cluster type flag
clu_energyfloatGeVcluster energy
clu_energy_errfloatGeVenergy uncertainty
clu_timefloatnscluster time
clu_time_errfloatnstime uncertainty
clu_nhitsuint32hits in the cluster
clu_pos_x/y/zfloatmmcluster position
clu_pos_err_xx/yy/zzfloatmm²position variances
clu_theta, clu_phifloatradintrinsic polar and azimuthal angles
clu_assoc_weightfloatassociation weight

mc_particles ​

One row per particle of MCParticles.

ColumnTypeUnitDescription
evtuint64entry counter
prt_indexuint64index in MCParticles
prt_pdgint32PDG code
prt_gen_statusint321 or 2 signal, >= 1000 background, 0 created by Geant4
prt_sim_statusint32simulator status bit field (createdInSimulation, decayedInTracker, …)
prt_originint32signal or background
prt_massdoubleGeV/c²mass
prt_energydoubleGeVtotal energy
prt_chargefloateelectric charge
prt_mom_x/y/zdoubleGeV/cmomentum
prt_vtx_timefloatnstime at the production vertex
prt_vtx_pos_x/y/zfloatmmproduction vertex
prt_end_pos_x/y/zfloatmmendpoint
prt_n_parentsuint32number of parents
prt_n_daughtersuint32number of daughters
prt_parent_indexint64index of the first parent, -1 without parents

prt_index here is the same index as prt_index in trk_hits and calo_clusters (both read the reco file's MCParticles), so (evt, prt_index) joins a hit or cluster to its full particle record.

reco_particles ​

One row per ReconstructedParticles entry.

ColumnTypeUnitDescription
evtuint64entry counter
rec_indexint32index in ReconstructedParticles
rec_pdgint32PDG code assigned by reconstruction
rec_chargefloateelectric charge
rec_energyfloatGeVenergy
rec_massfloatGeV/c²mass
rec_mom_x/y/zfloatGeV/cmomentum
rec_ref_pos_x/y/zfloatmmreference point
rec_pid_goodnessfloatgoodness of the PID hypothesis
rec_typeint32particle type flag
rec_n_clustersclusters attached
rec_n_trackstracks attached
rec_n_particlesdaughter particles
rec_n_particle_idsParticleID hypotheses
rec_n_cluster_hitscalorimeter hits behind the clusters
rec_n_track_measurementsmeasurements behind the tracks
rec_n_tracker_hitstracker hits behind those measurements

mc_dis ​

One row per event with the generator's DIS kinematics, read from the event parameters dis_<name> that the generator writes. Columns: evt, then alphas, mx2, nu, p_rt, pdrest, pperps, pperpz, q2, s_e, s_q, tempvar, tprime, tspectator, twopdotk, twopdotq, w, x_d, xbj, y_d, yplus. A missing parameter leaves an empty field.

event_index ​

One row per processed event: evt, event_number (from EventHeader), reco_collections, sim_collections (collections in each frame, 0 without that file). Its row count is the event count of a complete conversion.

Loading the CSV ​

python
import pandas as pd

hits = pd.read_csv("k_lambda_18x275_5000evt_0022.trk_hits.csv.zip")

event_0 = hits[hits["evt"] == 0]
primaries = hits[hits["prt_gen_status"] == 1]

signal = hits[hits["prt_origin"].isin([1, 2])]
background = hits[hits["prt_origin"].isin([3, 4])]

hits_per_system = hits.groupby("trk_hit_system_name").size()

# Full particle record of each hit
particles = pd.read_csv("k_lambda_18x275_5000evt_0022.mc_particles.csv.zip")
hits = hits.merge(particles[["evt", "prt_index", "prt_sim_status", "prt_parent_index"]],
                  on=["evt", "prt_index"])

Files written by the macros before the column unification use older names (prt_status, rec_collection, event, …). eic2ai/column_renames.py holds the old → new table per role; rename_dataframe(df, role) renames a loaded file.

Released under the MIT License.