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¶
- Architecture -- understand how HIPO files are structured
- Reading Recipes -- advanced reading patterns
- Writing Recipes -- advanced writing patterns
- API Reference -- full bank API