Writing Files¶
Basic Writing¶
// 1. Define schemas
hipo::schema schemaPart("event::particle", 100, 1);
schemaPart.parse("pid/S,px/F,py/F,pz/F");
// 2. Register schemas with writer BEFORE open()
hipo::writer writer;
writer.getDictionary().addSchema(schemaPart);
writer.open("output.hipo");
// 3. Write events
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);
}
event.reset();
event.addStructure(bank);
writer.addEvent(event);
}
// 4. Close (writes trailer)
writer.close();
Important
Always call writer.close() to finalize the file. It writes the trailer (record index) needed for random access.
Multiple Banks Per Event¶
hipo::schema schemaPart("event::particle", 100, 1);
schemaPart.parse("pid/S,px/F,py/F,pz/F");
hipo::schema schemaDet("event::detector", 100, 2);
schemaDet.parse("pindex/I,detectorid/I,x/F,y/F,z/F,time/F,energy/F");
hipo::writer writer;
writer.getDictionary().addSchema(schemaPart);
writer.getDictionary().addSchema(schemaDet);
writer.open("output.hipo");
hipo::event event;
for (int i = 0; i < 25000; i++) {
hipo::bank partBank(schemaPart, 5);
hipo::bank detBank(schemaDet, 10);
// fill banks...
event.reset();
event.addStructure(partBank);
event.addStructure(detBank);
writer.addEvent(event);
}
writer.close();
User Configuration¶
Store metadata as key-value pairs:
writer.addUserConfig("run", "12345");
writer.addUserConfig("beam_energy", "10.6");
writer.addUserConfig("target", "liquid_hydrogen");
// Must be called before open()
writer.open("output.hipo");
Read it back:
hipo::reader reader;
reader.open("output.hipo");
std::string run = reader.readUserConfig("run");
Copy/Filter Pattern¶
Read events from one file, optionally filter or modify, write to another:
hipo::reader reader;
reader.open("input.hipo");
hipo::dictionary dict;
reader.readDictionary(dict);
hipo::writer writer;
writer.addDictionary(dict);
writer.open("filtered.hipo");
hipo::event event;
hipo::bank particles(dict.getSchema("REC::Particle"));
while (reader.next()) {
reader.read(event);
event.read(particles);
// Filter: only keep events with electrons
bool hasElectron = false;
for (int row = 0; row < particles.getRows(); row++) {
if (particles.getInt("pid", row) == 11) {
hasElectron = true;
break;
}
}
if (hasElectron) {
writer.addEvent(event);
}
}
writer.close();
Generic Bank Filling¶
Fill any bank generically based on its schema:
void fillRandom(hipo::bank& bank) {
int nrows = bank.getRows();
int ncols = bank.getSchema().getEntries();
for (int row = 0; row < nrows; row++) {
for (int col = 0; col < ncols; col++) {
int type = bank.getSchema().getEntryType(col);
const char* name = bank.getSchema().getEntryName(col).c_str();
switch (type) {
case hipo::kByte:
case hipo::kShort:
case hipo::kInt:
bank.putInt(name, row, rand() % 100);
break;
case hipo::kFloat:
bank.putFloat(name, row, (float)rand() / RAND_MAX);
break;
case hipo::kDouble:
bank.putDouble(name, row, (double)rand() / RAND_MAX);
break;
case hipo::kLong:
bank.putLong(name, row, rand());
break;
}
}
}
}