Skip to content
Snippets Groups Projects
Commit 8d2df157 authored by Felix Weiglhofer's avatar Felix Weiglhofer Committed by Pierre-Alain Loizeau
Browse files

Add archive explorer to display online archives.

parent 80f50cd8
No related branches found
No related tags found
1 merge request!1506Add archive explorer to display online archives.
Pipeline #25707 passed
......@@ -6,7 +6,10 @@
#include "CbmDigiEvent.h"
#include "tof/Hit.h"
#include <boost/serialization/access.hpp>
#include <boost/serialization/utility.hpp>
#include <boost/serialization/vector.hpp>
#include <cstdint>
......@@ -14,6 +17,7 @@
#include "PartitionedVector.h"
#include "ca/core/data/CaTrack.h"
#include "ca/core/utils/CaVector.h"
#include "sts/Hit.h"
namespace cbm::algo
{
......
add_subdirectory(archive_explorer)
add_subdirectory(histserv)
#
# Application
#
set(APP cbm-archive-explorer)
set(APP_SRCS
app/Application.cxx
app/Options.cxx
app/main.cxx
)
add_executable(${APP} ${APP_SRCS})
target_link_libraries(${APP}
Algo
Boost::program_options
external::fles_logging
fmt::fmt
)
#
# libCbmArchiveExplorer
#
set(LIBRARY_NAME CbmArchiveExplorer)
set(LINKDEF lib/LinkDef.h)
set(INCLUDE_DIRECTORIES
lib
)
set(SRCS
lib/Server.cxx
)
set(HEADERS
lib/Server.h
)
set(PUBLIC_DEPENDENCIES
Algo
external::fles_logging
fmt::fmt
ROOT::Core
ROOT::Gpad
ROOT::Hist
ROOT::RIO
ROOT::RHTTP
)
generate_cbm_library()
target_link_libraries(${APP} CbmArchiveExplorer)
/* Copyright (C) 2023 FIAS Frankfurt Institute for Advanced Studies, Frankfurt / Main
SPDX-License-Identifier: GPL-3.0-only
Authors: Felix Weiglhofer [committer] */
#include "Application.h"
#include <log.hpp>
#include "RecoResultsInputArchive.h"
#include "Server.h"
using namespace cbm::explore;
using namespace cbm::algo;
Application::Application(const Options& options) : fOpts(options)
{
L_(info) << "Starting application with port " << fOpts.Port();
L_(info) << "Opening archive " << fOpts.Input();
auto archive = std::make_shared<RecoResultsInputArchive>(fOpts.Input().string());
fServer = std::make_unique<Server>(fOpts.Port(), archive);
}
Application::~Application() {}
int Application::Run()
{
fServer->Run();
return 0;
}
/* Copyright (C) 2023 FIAS Frankfurt Institute for Advanced Studies, Frankfurt / Main
SPDX-License-Identifier: GPL-3.0-only
Authors: Felix Weiglhofer [committer] */
#pragma once
#include <memory>
#include "Options.h"
namespace cbm::explore
{
class Server;
class Application {
public:
Application(const Options& options);
~Application();
int Run();
private:
Options fOpts;
std::unique_ptr<Server> fServer;
};
} // namespace cbm::explore
/* Copyright (C) 2023 FIAS Frankfurt Institute for Advanced Studies, Frankfurt / Main
SPDX-License-Identifier: GPL-3.0-only
Authors: Felix Weiglhofer [committer] */
#include "Options.h"
#include <boost/program_options.hpp>
#include <iostream>
namespace po = boost::program_options;
Options::Options(int argc, char** argv)
{
po::options_description options("Options");
// clang-format off
options.add_options()
("input,i", po::value(&fInput)->value_name("<input>")->required(),
"input archive")
("port,p", po::value(&fPort)->value_name("<port>")->default_value(8080),
"port to listen on")
("help,h",
"produce help message")
;
// clang-format on
po::variables_map vm;
po::command_line_parser parser {argc, argv};
parser.options(options);
try {
auto result = parser.run();
po::store(result, vm);
}
catch (const std::exception& e) {
std::cerr << "Error: " << e.what() << std::endl;
std::cerr << "Use '-h' to display all valid options." << std::endl;
std::exit(EXIT_FAILURE);
}
if (vm.count("help") > 0) {
std::cout << options << std::endl;
std::exit(EXIT_SUCCESS);
}
try {
po::notify(vm);
}
catch (const po::required_option& e) {
std::cerr << "Error: " << e.what() << std::endl;
std::cerr << "Use '-h' to display all valid options." << std::endl;
std::exit(EXIT_FAILURE);
}
}
/* Copyright (C) 2023 FIAS Frankfurt Institute for Advanced Studies, Frankfurt / Main
SPDX-License-Identifier: GPL-3.0-only
Authors: Felix Weiglhofer [committer] */
#pragma once
#include <compat/Filesystem.h>
class Options {
public:
Options(int argc, char** argv);
int Port() const { return fPort; }
cbm::algo::fs::path Input() const { return fInput; }
private:
int fPort;
std::string fInput;
};
/* Copyright (C) 2023 FIAS Frankfurt Institute for Advanced Studies, Frankfurt / Main
SPDX-License-Identifier: GPL-3.0-only
Authors: Felix Weiglhofer [committer] */
#include <log.hpp>
#include "Application.h"
#include "Options.h"
using namespace cbm::explore;
int main(int argc, char** argv)
{
Options options(argc, argv);
Application app(options);
return app.Run();
}
/* Copyright (C) 2023 FIAS Frankfurt Institute for Advanced Studies, Frankfurt / Main
SPDX-License-Identifier: GPL-3.0-only
Authors: Felix Weiglhofer [committer] */
#pragma link off all globals;
#pragma link off all classes;
#pragma link off all functions;
#pragma link C++ class cbm::explore::Server + ;
/* Copyright (C) 2023 FIAS Frankfurt Institute for Advanced Studies, Frankfurt / Main
SPDX-License-Identifier: GPL-3.0-only
Authors: Felix Weiglhofer [committer] */
#include "Server.h"
#include <TH1.h>
#include <THttpServer.h>
#include <TSystem.h>
#include <log.hpp>
#include <fmt/format.h>
using namespace cbm::explore;
ClassImp(Server);
Server::Server(int port, std::shared_ptr<algo::RecoResultsInputArchive> archive)
: TNamed("server", "server")
, fArchive(archive)
{
L_(info) << "Starting Server with port " << port;
fServer = new THttpServer(fmt::format("http:{}", port).c_str());
fServer->SetTimer(0, true);
// FIXME: Why doesn't root use the local jsroot by default???
fServer->SetJSROOT("https://jsroot.gsi.de/7.1.0/");
}
Server::~Server() {}
int Server::Run()
{
// register this object in http server
fServer->Register("/", this);
fServer->Hide("/server");
// enable monitoring and
// specify items to draw when page is opened
// fServer->SetItemField("/", "_monitoring", "5000");
// Specify layout. TODO: does not work?
fServer->SetItemField("/", "_layout", "grid3x3");
fServer->RegisterCommand("/NextTS", "/server/->RequestNextTS()");
fServer->SetItemField("/NextTS", "_title", "Next Timeslice");
CreateHistos();
NextTS();
L_(info) << "Starting event loop";
while (true) {
int nRequests = 0;
do {
nRequests = fServer->ProcessRequests();
if (nRequests > 0) L_(info) << "Processed " << nRequests << " requests";
// sleep minimal time
// TODO: This is terrible. And the sleep should not be in this loop.
// But ROOTJS sometimes sends commands multiple times,
// And this is the only way, i was able to catch duplicate commands
gSystem->Sleep(SleepPerTick_ms);
} while (nRequests > 0);
if (fRequestNextTS) {
NextTS();
fRequestNextTS = false;
}
}
return 0;
}
void Server::NextTS()
{
L_(info) << "Fetching next Timeslice...";
auto recoResults = fArchive->get();
if (fArchive->eos()) {
L_(info) << "End of archive reached";
return;
}
ResetHistos();
auto& stsHits = recoResults->StsHits();
for (size_t p = 0; p < stsHits.NPartitions(); p++) {
auto [sensor, address] = stsHits.Partition(p);
L_(info) << "Filling sensor " << address << " with " << sensor.size() << " hits";
for (auto& hit : sensor) {
fHStsHitsX->Fill(hit.X());
fHStsHitsY->Fill(hit.Y());
fHStsHitsZ->Fill(hit.Z());
fHStsHitsTime->Fill(hit.Time());
fHStsHitsDx->Fill(hit.Dx());
fHStsHitsDy->Fill(hit.Dy());
fHStsHitsDz->Fill(hit.fDz);
fHStsHitsDxy->Fill(hit.fDxy);
fHStsHitsTimeError->Fill(hit.TimeError());
fHStsHitsDu->Fill(hit.fDu);
fHStsHitsDv->Fill(hit.fDv);
}
}
L_(info) << "Finished Timeslice";
}
void Server::ResetHistos()
{
for (auto* histo : fHistos) {
histo->Reset();
}
}
void Server::CreateHistos()
{
CreateFolder("/sts", "STS");
CreateFolder("/sts/hits", "Hits");
CreateHisto(fHStsHitsX, "/sts/hits", "hStsHitsX", "Sts Hits X", 100, -10, 10);
CreateHisto(fHStsHitsY, "/sts/hits", "hStsHitsY", "Sts Hits Y", 100, -10, 10);
CreateHisto(fHStsHitsZ, "/sts/hits", "hStsHitsZ", "Sts Hits Z", 100, -10, 10);
CreateHisto(fHStsHitsTime, "/sts/hits", "hStsHitsTime", "Sts Hits Time", 1000, 0, 128000000);
CreateHisto(fHStsHitsDx, "/sts/hits", "hStsHitsDx", "Sts Hits Dx", 100, 0, 0.1);
CreateHisto(fHStsHitsDy, "/sts/hits", "hStsHitsDy", "Sts Hits Dy", 100, 0, 0.1);
CreateHisto(fHStsHitsDz, "/sts/hits", "hStsHitsDz", "Sts Hits Dz", 100, 0, 0.1);
CreateHisto(fHStsHitsDxy, "/sts/hits", "hStsHitsDxy", "Sts Hits Dxy", 100, 0, 0.1);
CreateHisto(fHStsHitsTimeError, "/sts/hits", "hStsHitsTimeError", "Sts Hits Time Error", 100, 0, 0.1);
CreateHisto(fHStsHitsDu, "/sts/hits", "hStsHitsDu", "Sts Hits Du", 100, 0, 0.1);
CreateHisto(fHStsHitsDv, "/sts/hits", "hStsHitsDv", "Sts Hits Dv", 100, 0, 0.1);
}
template<typename Histo_t>
void Server::CreateHisto(Histo_t*& histo, const char* folder, const char* name, const char* title, int nbins,
double xlow, double xmax)
{
histo = new Histo_t(name, title, nbins, xlow, xmax);
histo->SetDirectory(nullptr);
fServer->Register(folder, histo);
fHistos.push_back(histo);
}
void Server::CreateFolder(const char* path, const char* name)
{
fServer->CreateItem(path, name);
fServer->SetItemField(path, "_kind", "Folder");
}
/* Copyright (C) 2023 FIAS Frankfurt Institute for Advanced Studies, Frankfurt / Main
SPDX-License-Identifier: GPL-3.0-only
Authors: Felix Weiglhofer [committer] */
#pragma once
#include <Rtypes.h>
#include <TNamed.h>
#include <memory>
#include "RecoResultsInputArchive.h"
class THttpServer;
class TH1;
class TH1F;
class TH1I;
namespace cbm::explore
{
class Server : public TNamed {
public:
Server(int port, std::shared_ptr<algo::RecoResultsInputArchive> archive);
virtual ~Server();
int Run();
// Server commands
void RequestNextTS() { fRequestNextTS = true; }
private:
static constexpr int SleepPerTick_ms = 50;
// Internal state
THttpServer* fServer = nullptr; //!
std::shared_ptr<algo::RecoResultsInputArchive> fArchive; //!
std::vector<TH1*> fHistos; //!
// Server commands
bool fRequestNextTS = false;
// Histograms
TH1F* fHStsHitsX = nullptr;
TH1F* fHStsHitsY = nullptr;
TH1F* fHStsHitsZ = nullptr;
TH1I* fHStsHitsTime = nullptr;
TH1F* fHStsHitsDx = nullptr;
TH1F* fHStsHitsDy = nullptr;
TH1F* fHStsHitsDz = nullptr;
TH1F* fHStsHitsDxy = nullptr;
TH1F* fHStsHitsTimeError = nullptr;
TH1F* fHStsHitsDu = nullptr;
TH1F* fHStsHitsDv = nullptr;
void NextTS();
void ResetHistos();
void CreateHistos();
template<typename Histo_t>
void CreateHisto(Histo_t*& histo, const char* folder, const char* name, const char* title, int nbins, double xlow,
double xmax);
void CreateFolder(const char* path, const char* name);
ClassDef(Server, 1);
};
} // namespace cbm::explore
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment