Skip to content

Quick Start

Reading a HIPO File

The recommended way to analyze HIPO files is the sequential chain. You add one or more files, then iterate every event across all of them with a range-based for loop — the chain opens files, loads their schema dictionaries, and hands you each event ready to use:

#include "chain.h"

int main() {
    // 1. Build the chain — one file, or many
    hipo::chain ch;
    ch.add("data.hipo");                  // ch.add_pattern("data/*.hipo") for many

    // 2. Iterate every event across every file
    for (auto& [event, file_idx, event_idx] : ch) {
        auto particles = event.getBank("REC::Particle");

        for (int row = 0; row < particles.getRows(); row++) {
            int   pid = particles.getInt("pid", row);
            float px  = particles.getFloat("px", row);
            float py  = particles.getFloat("py", row);
            float pz  = particles.getFloat("pz", row);
            printf("%d: pid=%d  p=(%.3f, %.3f, %.3f)\n",
                   row, pid, px, py, pz);
        }
    }
}

event.getBank("...") looks the bank up by name in the file's dictionary, so there is no separate schema or bank setup step. The same chain also scales to many cores via ch.process(...) — see Parallel processing.

The Lower-Level reader

For single-file scripts, or when you need fine control (random access), use hipo::reader directly. It is the class the chain is built on: you open the file, load the dictionary, create banks from schemas, and drive the event loop yourself.

#include "reader.h"

int main() {
    hipo::reader reader;
    reader.open("data.hipo");

    hipo::dictionary dict;
    reader.readDictionary(dict);

    // Read multiple banks at once with the banklist API
    hipo::banklist list = reader.getBanks({"REC::Particle", "REC::Event"});

    while (reader.next(list)) {
        auto& particles = list[0];        // REC::Particle
        auto& recEvent  = list[1];        // REC::Event
        for (int row = 0; row < particles.getRows(); row++) {
            int pid = particles.getInt("pid", row);
        }
    }
}

See Reading files for the full set of reader patterns.

Writing a HIPO File

#include "writer.h"

int main() {
    // 1. Define schemas
    hipo::schema schemaPart("event::particle", 100, 1);
    schemaPart.parse("pid/S,px/F,py/F,pz/F");

    // 2. Create writer and register schemas BEFORE opening
    hipo::writer writer;
    writer.getDictionary().addSchema(schemaPart);
    writer.open("output.hipo");

    // 3. Create events with banks
    hipo::event event;
    for (int i = 0; i < 1000; i++) {
        int nrows = 2 + rand() % 10;
        hipo::bank bank(schemaPart, nrows);

        for (int row = 0; row < nrows; row++) {
            bank.putShort("pid", row, 211);
            bank.putFloat("px", row, 0.5f * row);
            bank.putFloat("py", row, 0.3f * row);
            bank.putFloat("pz", row, 1.0f + 0.1f * row);
        }

        event.reset();
        event.addStructure(bank);
        writer.addEvent(event);
    }

    writer.close();
}

Important

Schemas must be added to the writer's dictionary before calling open(). They are written into the file header.

Type System

HIPO supports 6 data types, specified by single characters in schema definitions:

Character Type C++ Type Size
B Byte int8_t 1 byte
S Short int16_t 2 bytes
I Int int32_t 4 bytes
F Float float 4 bytes
D Double double 8 bytes
L Long int64_t 8 bytes

Schema format: "column1/T,column2/T,..." where T is the type character.

hipo::schema s("REC::Particle", 300, 1);
s.parse("pid/I,px/F,py/F,pz/F,vx/D,vy/D,vz/D,charge/B,status/L");

Next Steps