Creating and accessing Products

DataSets, Runs, SubRuns, and Events can store Products. A Product is an instance of any C++ object. Since the mechanism for storing and loading products is the same when using DataSets, Runs, SubRuns, and Events, the following code sample illustrates only how to store products in events.

main.cpp (show/hide)

#include <iostream>
#include <string>
#include <hepnos.hpp>
#include <boost/serialization/string.hpp>
#include <boost/serialization/vector.hpp>

using namespace hepnos;

struct Particle {

    std::string name;
    double x, y, z;

    Particle() {}

    Particle(const std::string& name, double x, double y, double z)
    : name(name), x(x), y(y), z(z) {}

    template<typename Archive>
    void serialize(Archive& ar, const unsigned int version) {
        ar & name;
        ar & x;
        ar & y;
        ar & z;
    }
};

int main(int argc, char** argv) {

    if(argc != 3) {
        std::cerr << "Usage: " << argv[0] << " <protocol> <configfile>" << std::endl;
        exit(-1);
    }

    DataStore datastore = DataStore::connect(argv[1], argv[2]);
    // Get the root of the DataStore
    DataSet root = datastore.root();
    // Create a DataSet, a Run, a SubRun, and an Event
    DataSet example8 = root.createDataSet("example8");
    Run run = example8.createRun(1);
    SubRun subrun = run.createSubRun(4);
    Event event = subrun.createEvent(32);
    // Store a product into the event
    {
        Particle p("electron", 3.4, 4.5, 5.6);
        ProductID pid = event.store("mylabel", p);
    }
    // Reload a product from the event
    {
        Particle p;
        bool b = event.load("mylabel", p);
        if(b) std::cout << "Particle loaded succesfully" << std::endl;
        else  std::cout << "Particle wasn't loaded" << std::endl;
    }
    // Store a section of a vector into the event
    {
        std::vector<Particle> v;
        for(unsigned i=0; i < 5; i++) {
            v.emplace_back("electron", i*4, i*2, i+1);
        }
        // store only the sub-vector [1,3[ (2 elements)
        event.store("myvec", v, 1, 3);
    }
    // Load the vector
    {
        std::vector<Particle> v;
        event.load("myvec", v);
        std::cout << "Reloaded " << v.size() << " particles" << std::endl;
    }
}

In this example, we want to store instances of the Particle class. For this, we need to provide a serialization function for Boost to use when serializing the object into storage.

We then use the Event::store() method to store the desired object into the event. This method takes a label as a first argument. The pair (label, product type) uniquely addresses a product inside an event. It is not possible to overwrite an existing product. Hence multiple products of the same type may be stored in the same event using different labels. The same label may be used to store products of different types in the same event.

The second part of the example shows how to use the vector storage interface. In this example, the Event::store function is used to store a sub-vector of the vector v, from index 1 (included) to index 3 (excluded). The type of product stored by this way is std::vector<Particle>. Hence it can be reloaded into a std::vector<Particle> later on.