181 lines
5.2 KiB
C++
181 lines
5.2 KiB
C++
|
// mana - mnode analysis / mini analysis
|
||
|
// usage: mana_auto_replay <zipfile>
|
||
|
//
|
||
|
// open the file
|
||
|
// read preamble
|
||
|
// create crateconfig from preamble data
|
||
|
//
|
||
|
// setup:
|
||
|
// for each event in the config:
|
||
|
// for each module:
|
||
|
// check for module type in meta data
|
||
|
// find module type in vme_module_data_sources.json
|
||
|
// for each filter in the modules data_sources:
|
||
|
// calculate array size (use float as the storage type for now)
|
||
|
// reserve buffer space for the array
|
||
|
//
|
||
|
// replay:
|
||
|
// for each event in the listfile:
|
||
|
// for each module in the event:
|
||
|
// locate the list of filters for the crate, event and module index triplet
|
||
|
// for each filter:
|
||
|
// match it against every word in the module data
|
||
|
// if a word matches extract address and value
|
||
|
// store value in the reserved array buffer
|
||
|
//
|
||
|
// -> extracted u32 data is stored in the buffer space for this event
|
||
|
// what now?
|
||
|
// - histogram
|
||
|
// - make arrays available to python and test numpy
|
||
|
// - crrate root histograms and accumulate
|
||
|
// - create root trees or the new rntuples(?)
|
||
|
// -> want plugins. similar to the mvme listfile_reader but on analysis data
|
||
|
|
||
|
#include <cmrc/cmrc.hpp> // mnode::resources
|
||
|
#include <mesytec-mvlc/mesytec-mvlc.h>
|
||
|
#include <mesytec-mnode/mnode_cpp_types.h>
|
||
|
#include <nlohmann/json.hpp>
|
||
|
#include <list>
|
||
|
#include "mana_replay_api.h"
|
||
|
|
||
|
CMRC_DECLARE(mnode::resources);
|
||
|
|
||
|
using namespace mesytec;
|
||
|
using namespace mesytec::mnode;
|
||
|
|
||
|
namespace arena
|
||
|
{
|
||
|
|
||
|
// source: https://blog.xoria.org/rounding-up/
|
||
|
inline int64_t round_up(int64_t n, int64_t p)
|
||
|
{
|
||
|
int64_t mask = p - 1;
|
||
|
return (n + mask) & ~mask;
|
||
|
}
|
||
|
|
||
|
struct Arena
|
||
|
{
|
||
|
struct Segment
|
||
|
{
|
||
|
std::vector<u8> data;
|
||
|
size_t used;
|
||
|
|
||
|
explicit Segment(size_t size)
|
||
|
: data(size)
|
||
|
, used(0)
|
||
|
{
|
||
|
}
|
||
|
inline size_t free() const { return data.size() - used; }
|
||
|
inline u8 *cur() { return data.data() + used; }
|
||
|
};
|
||
|
|
||
|
std::list<Segment> segments;
|
||
|
size_t current = 0;
|
||
|
|
||
|
inline Segment *current_segment()
|
||
|
{
|
||
|
if (current < segments.size())
|
||
|
{
|
||
|
auto it = segments.begin();
|
||
|
std::advance(it, current);
|
||
|
return &(*it);
|
||
|
}
|
||
|
|
||
|
return nullptr;
|
||
|
}
|
||
|
|
||
|
inline u8 *push_size(size_t required)
|
||
|
{
|
||
|
required = round_up(required, 16);
|
||
|
|
||
|
if (auto segment = current_segment(); !segment || segment->free() < required)
|
||
|
{
|
||
|
// could waste segments if required > default size of 1u << 20 but that's fine for now
|
||
|
segments.emplace_back(
|
||
|
Arena::Segment(std::max(required, static_cast<size_t>(1u << 20))));
|
||
|
current = segments.size() - 1;
|
||
|
}
|
||
|
|
||
|
auto segment = current_segment();
|
||
|
assert(segment);
|
||
|
assert(segment->free() >= required);
|
||
|
u8 *result = segment->cur();
|
||
|
std::memset(result, 0, required);
|
||
|
segment->used += required;
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
template<typename T> T *push_t(size_t count = 1)
|
||
|
{
|
||
|
static_assert(std::is_trivial<T>::value, "T must be a trivial type");
|
||
|
return reinterpret_cast<T *>(push_size(sizeof(T) * count));
|
||
|
}
|
||
|
};
|
||
|
|
||
|
}; // namespace arena
|
||
|
|
||
|
struct ListfileContext
|
||
|
{
|
||
|
mvlc::listfile::ZipReader zipReader;
|
||
|
mvlc::listfile::ReadHandle *readHandle;
|
||
|
mvlc::listfile::ListfileReaderHelper readerHelper;
|
||
|
mvlc::CrateConfig crateConfig;
|
||
|
};
|
||
|
|
||
|
std::optional<ListfileContext> make_listfile_context(const std::string &filename)
|
||
|
{
|
||
|
try
|
||
|
{
|
||
|
ListfileContext ctx{};
|
||
|
ctx.zipReader.openArchive(filename);
|
||
|
ctx.readHandle = ctx.zipReader.openEntry(ctx.zipReader.firstListfileEntryName());
|
||
|
ctx.readerHelper = mvlc::listfile::make_listfile_reader_helper(ctx.readHandle);
|
||
|
auto configData = ctx.readerHelper.preamble.findCrateConfig();
|
||
|
if (!configData)
|
||
|
{
|
||
|
std::cerr << fmt::format("No MVLC crate config found in {}\n", filename);
|
||
|
return {};
|
||
|
}
|
||
|
|
||
|
ctx.crateConfig = mvlc::crate_config_from_yaml(configData->contentsToString());
|
||
|
std::cout << fmt::format("Found MVLC crate config in {}\n", filename);
|
||
|
for (size_t i=0; i<ctx.crateConfig.stacks.size(); ++i)
|
||
|
{
|
||
|
std::cout << fmt::format("event[{}] {}:\n", i, ctx.crateConfig.stacks[i].getName());
|
||
|
size_t mi=0;
|
||
|
for (const auto &module_: ctx.crateConfig.stacks[i].getGroups())
|
||
|
{
|
||
|
auto meta = fmt::format("{}", fmt::join(module_.meta, ", "));
|
||
|
std::cout << fmt::format(" module[{}]: {}, {}\n", mi++, module_.name, meta);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return ctx;
|
||
|
}
|
||
|
catch (const std::exception &e)
|
||
|
{
|
||
|
std::cerr << fmt::format("Error: {}\n", e.what());
|
||
|
return {};
|
||
|
}
|
||
|
}
|
||
|
|
||
|
int main(int argc, char *argv[])
|
||
|
{
|
||
|
auto f = cmrc::mnode::resources::get_filesystem().open("data/vme_module_data_sources.json");
|
||
|
const auto jModuleDataSources = nlohmann::json::parse(f.begin(), f.end());
|
||
|
|
||
|
if (argc < 2)
|
||
|
{
|
||
|
std::cout << fmt::format("Usage: {} <listfile.zip>\n", argv[0]);
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
std::string filename = argv[1];
|
||
|
auto listfileContext = make_listfile_context(filename);
|
||
|
|
||
|
if (!listfileContext)
|
||
|
return 1;
|
||
|
|
||
|
return 0;
|
||
|
}
|