Skip to content

Commit

Permalink
More options to configure acquisition (#7)
Browse files Browse the repository at this point in the history
* remove old files

* more options for run

* option to skip run info

* early exit

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* print

* daq env

* manual output file

* c string stuff

* c string stuff

* I hate c strings

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
  • Loading branch information
lobis and pre-commit-ci[bot] authored Sep 25, 2024
1 parent 53007da commit 5711031
Show file tree
Hide file tree
Showing 9 changed files with 112 additions and 58 deletions.
14 changes: 0 additions & 14 deletions other/loadDAQ_EnvVars.sh

This file was deleted.

6 changes: 0 additions & 6 deletions other/run.info

This file was deleted.

37 changes: 28 additions & 9 deletions src/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <string>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/shm.h>
Expand All @@ -43,8 +44,6 @@ using namespace std;
/*******************************************************************************
Constants types and global variables
*******************************************************************************/
char res_file[80] = {"\0"};
int save_res = 0;
int verbose = 4;
int format_ver = 2;
int pending_event = 0;
Expand Down Expand Up @@ -74,6 +73,14 @@ int SemaphoreId;
constexpr int MAX_SIGNALS = feminos_daq_storage::MAX_SIGNALS;
constexpr int MAX_POINTS = feminos_daq_storage::MAX_POINTS;

void removeRootExtension(std::string& filename) {
const std::string extension = ".root";
std::size_t pos = filename.rfind(extension);
if (pos != std::string::npos && pos == filename.length() - extension.length()) {
filename.erase(pos); // Remove the extension
}
}

template<typename T>
void stringIpToArray(const std::string& ip, T* ip_array) {
// we assume ip is a valid IP (this has to be checked beforehand)
Expand Down Expand Up @@ -128,6 +135,10 @@ int main(int argc, char** argv) {
bool version_flag = false;
bool disable_aqs = false;
std::string compression_option = "default";
double stop_run_after_seconds = 0;
unsigned int stop_run_after_entries = 0;
bool allow_losing_events = false;
bool skip_run_info = false;

CLI::App app{"feminos-daq"};

Expand All @@ -146,15 +157,22 @@ int main(int argc, char** argv) {
->check(CLI::ValidIPV4);
app.add_option("-i,--input", input_file, "Read commands from file specified")
->group("File Options");
app.add_option("-o,--output", output_file, "Save results in file specified (DOES NOT WORK!)")
app.add_option("-o,--output", output_file, "Save results in file specified")
->group("File Options");
app.add_option("-d,--output-directory", output_directory, "Output directory. This can also be specified via the environment variable 'FEMINOS_DAQ_OUTPUT_DIRECTORY' or 'RAWDATA_PATH'")
->group("File Options");
app.add_option("-v,--verbose", verbose_level, "Verbose level")
->group("General")
->check(CLI::Range(0, 4));
app.add_option("-t,--time", stop_run_after_seconds, "Stop the acquisition after the specified time in seconds")
->group("General")
->check(CLI::Range(0.0, 1e6));
app.add_option("-e,--entries", stop_run_after_entries, "Stop the acquisition after reaching the specified number of entries")
->group("General");
app.add_flag("--read-only", readOnly, ("Read-only mode"))
->group("General");
app.add_flag("--allow-losing-events", allow_losing_events, "Allow losing events if the buffer is full (acceptable for calibrations, not for background runs)")
->group("General");
app.add_flag("--shared-buffer", sharedBuffer, "Store event data in a shared memory buffer")->group("General");
app.add_flag("--compression", compression_option,
R"(Select the compression settings for the output root file. Data must be written to disk faster than it is acquired. Frames are never dropped, if the rate is too high (or the disk too slow) a queue will begin to fill up and a warning message will appear.
Expand All @@ -164,6 +182,7 @@ int main(int argc, char** argv) {
->group("File Options")
->check(CLI::IsMember(feminos_daq_storage::StorageManager::GetCompressionOptions()));
app.add_flag("--disable-aqs", disable_aqs, "Do not store data in aqs format. NOTE: aqs files may be created anyways but they will not have data")->group("File Options");
app.add_flag("--skip-run-info", skip_run_info, "Skip asking for run information and use default values (same as pressing enter)")->group("General");

CLI11_PARSE(app, argc, argv);

Expand All @@ -186,17 +205,17 @@ int main(int argc, char** argv) {
storage_manager.SetOutputDirectory(output_directory);
storage_manager.compression_option = compression_option;
storage_manager.disable_aqs = disable_aqs;
storage_manager.stop_run_after_seconds = stop_run_after_seconds;
storage_manager.stop_run_after_entries = stop_run_after_entries;
storage_manager.allow_losing_events = allow_losing_events;
storage_manager.skip_run_info = skip_run_info;

stringIpToArray(server_ip, femarray.rem_ip_beg);
stringIpToArray(local_ip, femarray.loc_ip);

if (!output_file.empty()) {
if (output_file.length() > 80) {
std::cerr << "Output file name is too long" << std::endl;
return 1;
}
strcpy(res_file, output_file.c_str());
save_res = 1;
removeRootExtension(output_file);
storage_manager.output_filename_manual = output_file;
}

if (!input_file.empty()) {
Expand Down
57 changes: 41 additions & 16 deletions src/mclient/cmdfetcher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,8 @@ int CmdFetcher_Main(CmdFetcher* cf) {
// Pass this semaphore to the FemArray
fa->sem_cur_cmd_done = cf->sem_cur_cmd_done;

const auto& storage_manager = feminos_daq_storage::StorageManager::Instance();

// Command fetching loop
while (!alldone) {
// Get the next command from the local command array
Expand Down Expand Up @@ -266,6 +268,8 @@ int CmdFetcher_Main(CmdFetcher* cf) {
}

// use stdin for commands
const auto daq_config_directory = getenv("DAQ_CONFIG");

if (cf->use_stdin) {
cmd_stdin_done = 0;
while (!cmd_stdin_done) {
Expand All @@ -281,8 +285,7 @@ int CmdFetcher_Main(CmdFetcher* cf) {
strcmp(cf->cmd_file, "runTCM") != 0) {

if (!readOnly) {

sprintf(tmpStr, "%s/%s", getenv("DAQ_CONFIG"), "ped.info");
sprintf(tmpStr, "%s/%s", daq_config_directory, "ped.info");
fRunInfo = fopen(tmpStr, "rt");

fscanf(fRunInfo, "%s\n", clockStr);
Expand All @@ -293,7 +296,7 @@ int CmdFetcher_Main(CmdFetcher* cf) {
printf("Getting info from ped.info\n");
printf("Clock divisions : %s shaping : %s gain : %s\n", clockStr, shapingStr, gainStr);

sprintf(tmpStr, "%s/%s", getenv("DAQ_CONFIG"), "run.info");
sprintf(tmpStr, "%s/%s", daq_config_directory, "run.info");
fRunInfo = fopen(tmpStr, "rt");
fscanf(fRunInfo, "%s\n", runNumberStr);
runNumber = atoi(runNumberStr);
Expand All @@ -304,53 +307,75 @@ int CmdFetcher_Main(CmdFetcher* cf) {
fscanf(fRunInfo, "%s\n", detectorStr);
fclose(fRunInfo);

const bool skip_run_info = storage_manager.skip_run_info;
if (skip_run_info) {
sprintf(tmpStr, "\n");
}

printf("Enter the run conditions :\n");
printf("--------------------------\n");
printf("Run number : %d\n", runNumber + 1);

printf("\nDrift field (%s V/cm/bar) : ", driftFieldStr);
fgets(tmpStr, 100, stdin);
if (!skip_run_info) {
fgets(tmpStr, 100, stdin);
}
strtok(tmpStr, "\n");
if (strcmp(tmpStr, "\n") != 0)
if (strcmp(tmpStr, "\n") != 0) {
sprintf(driftFieldStr, "%s", tmpStr);
}
printf("\nDrift field set to : %s V/cm/bar\n", driftFieldStr);

printf("\nMesh voltage (%s V) : ", meshVoltageStr);
fgets(tmpStr, 100, stdin);
if (!skip_run_info) {
fgets(tmpStr, 100, stdin);
}
strtok(tmpStr, "\n");
if (strcmp(tmpStr, "\n") != 0)
if (strcmp(tmpStr, "\n") != 0) {
sprintf(meshVoltageStr, "%s", tmpStr);
}
printf("\nMesh voltage set to : %s V\n", meshVoltageStr);

printf("\nDetector pressure (%s bar) : ", detectorPressureStr);
fgets(tmpStr, 100, stdin);
if (!skip_run_info) {
fgets(tmpStr, 100, stdin);
}
strtok(tmpStr, "\n");
if (strcmp(tmpStr, "\n") != 0)
if (strcmp(tmpStr, "\n") != 0) {
sprintf(detectorPressureStr, "%s", tmpStr);
}
printf("\nPressure set to : %s bar\n", detectorPressureStr);

printf("\nRun tag (%s) : ", runTagStr);
fgets(tmpStr, 100, stdin);
if (!skip_run_info) {
fgets(tmpStr, 100, stdin);
}
strtok(tmpStr, "\n");
if (strcmp(tmpStr, "\n") != 0)
if (strcmp(tmpStr, "\n") != 0) {
sprintf(runTagStr, "%s", tmpStr);
}
printf("\n");
removeSpaces(runTagStr);
printf("Run tag set to : %s\n", runTagStr);

printf("\nDetector (%s) : ", detectorStr);
fgets(tmpStr, 100, stdin);
if (!skip_run_info) {
fgets(tmpStr, 100, stdin);
}
strtok(tmpStr, "\n");
if (strcmp(tmpStr, "\n") != 0)
if (strcmp(tmpStr, "\n") != 0) {
sprintf(detectorStr, "%s", tmpStr);
}
printf("\nDetector set to : %s\n", detectorStr);

printf("\nComments : ");
fgets(tmpStr, 512, stdin);
if (!skip_run_info) {
fgets(tmpStr, 100, stdin);
}
sprintf(runComments, "%s", tmpStr);
printf("\n");

sprintf(tmpStr, "%s/%s", getenv("DAQ_CONFIG"), "run.info");
sprintf(tmpStr, "%s/%s", daq_config_directory, "run.info");
fRunInfo = fopen(tmpStr, "wt");
runNumber++;
fprintf(fRunInfo, "%d\n", runNumber);
Expand Down Expand Up @@ -414,7 +439,7 @@ int CmdFetcher_Main(CmdFetcher* cf) {
}
fclose(fRunInfo);

sprintf(tmpStr, "%s/%s", getenv("DAQ_CONFIG"), "ped.info");
sprintf(tmpStr, "%s/%s", daq_config_directory, "ped.info");
fRunInfo = fopen(tmpStr, "wt");

fprintf(fRunInfo, "%s\n", clockStr);
Expand Down
2 changes: 1 addition & 1 deletion src/mclient/cmdfetcher.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
Constants types and global variables
*******************************************************************************/
#define CMD_ARRAY_SIZE 25000
#define CMD_LINE_SIZE 120
#define CMD_LINE_SIZE 200

typedef struct _CmdFetcher {
int id;
Expand Down
19 changes: 12 additions & 7 deletions src/mclient/evbuilder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,6 @@ int timeStart = 0;

char elogCommand[512];

char filenameToCopy[256];
char command[256];

char fileNameNow[256];
Expand Down Expand Up @@ -917,7 +916,7 @@ int EventBuilder_FileAction(EventBuilder* eb,
if (readOnly) { return 0; }

struct tm* now;
char name[120];
char name[200];
time_t start_time;
char str_res[4];
char str_ext[8];
Expand Down Expand Up @@ -1026,8 +1025,7 @@ int EventBuilder_FileAction(EventBuilder* eb,
now->tm_sec);
*/
sprintf(eb->run_str,
"R%05d_%s_Vm_%s_Vd_%s_Pr_%s_Gain_%s_Shape_%"
"s_Clock_%s",
"R%05d_%s_Vm_%s_Vd_%s_Pr_%s_Gain_%s_Shape_%s_Clock_%s",
runNumber, runTagStr, meshVoltageStr,
driftFieldStr, detectorPressureStr, gainStr,
shapingStr, clockStr);
Expand Down Expand Up @@ -1087,7 +1085,16 @@ int EventBuilder_FileAction(EventBuilder* eb,
const auto output_directory = feminos_daq_storage::StorageManager::Instance().GetOutputDirectory();
sprintf(&(eb->file_path[0]), "%s", output_directory.c_str());

char filename_root[120] = {};
auto& storage_manager = feminos_daq_storage::StorageManager::Instance();
if (!storage_manager.output_filename_manual.empty()) {
// clear strings (c-string)
eb->file_path[0] = '.';
eb->file_path[1] = '/';
eb->file_path[2] = '\0';
storage_manager.output_filename_manual.copy(eb->run_str, storage_manager.output_filename_manual.size());
eb->run_str[storage_manager.output_filename_manual.size()] = '\0';
}
char filename_root[200] = {};
sprintf(filename_root, "%s/%s.%s", &(eb->file_path[0]),
&(eb->run_str[0]), "root");
cout << "Root file name : " << filename_root << endl;
Expand All @@ -1113,8 +1120,6 @@ int EventBuilder_FileAction(EventBuilder* eb,

printf("Opening file : %s\n", name);

auto& storage_manager = feminos_daq_storage::StorageManager::Instance();

// This loop is entered for every subrun, so we need to make sure this is only initialized once
if (!storage_manager.IsInitialized()) {
storage_manager.Initialize(filename_root);
Expand Down
2 changes: 1 addition & 1 deletion src/mclient/evbuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ typedef struct _EventBuilder {

void* fa; // pointer to FEM Array

char file_path[120]; // result file path
char file_path[200]; // result file path
int savedata; // 0: do not save data; 1: save to disk in ASCII; 2: save to disk in binary
FILE* fout; // output file pointer

Expand Down
23 changes: 20 additions & 3 deletions src/root/storage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ void feminos_daq_storage::StorageManager::Checkpoint(bool force) {

if (force || std::chrono::system_clock::now() - checkpoint_last > checkpoint_interval) {
file->Write("", TObject::kOverwrite);
file->Flush();
checkpoint_last = std::chrono::system_clock::now();
}
}
Expand Down Expand Up @@ -197,7 +196,7 @@ void StorageManager::Initialize(const string& filename) {

run_tree->Branch("number", &run_number);
run_tree->Branch("name", &run_name);
run_tree->Branch("timestamp", &run_time_start);
run_tree->Branch("timestamp", &run_time_start_millis);
run_tree->Branch("detector", &run_detector_name);
run_tree->Branch("tag", &run_tag);
run_tree->Branch("drift_field_V_cm_bar", &run_drift_field_V_cm_bar);
Expand All @@ -207,7 +206,7 @@ void StorageManager::Initialize(const string& filename) {
run_tree->Branch("commands", &run_commands);

// millis since epoch
run_time_start = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
run_time_start_millis = std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();

auto& prometheus_manager = feminos_daq_prometheus::PrometheusManager::Instance();
prometheus_manager.ExposeRootOutputFilename(filename);
Expand Down Expand Up @@ -237,6 +236,13 @@ void StorageManager::Initialize(const string& filename) {
prometheus_manager.SetNumberOfEvents(storage_manager.event_tree->GetEntries());

prometheus_manager.UpdateOutputRootFileSize();

const bool exit_due_to_entries = storage_manager.stop_run_after_entries > 0 && storage_manager.event_tree->GetEntries() >= storage_manager.stop_run_after_entries;
const bool exit_due_to_time = storage_manager.stop_run_after_seconds > 0 && double(std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count()) - double(storage_manager.run_time_start_millis) > storage_manager.stop_run_after_seconds * 1000.0;
if (exit_due_to_entries || exit_due_to_time) {
cout << "Stopping run at " << storage_manager.event_tree->GetEntries() << " entries" << endl;
early_exit();
}
}

storage_manager.Clear();
Expand Down Expand Up @@ -308,6 +314,17 @@ double StorageManager::GetQueueUsage() {
return GetNumberOfFramesInQueue() / (double) max_frames;
}

void StorageManager::early_exit() const {
// Invoking this from a thread is not the cleanest way to exit the program, but it appears to work

if (file) {
file->Write("", TObject::kOverwrite);
file->Close();
}

exit(0);
}

std::pair<unsigned short, std::array<unsigned short, MAX_POINTS>> Event::get_signal_id_data_pair(size_t index) const {
unsigned short channel = signal_ids[index];
std::array<unsigned short, MAX_POINTS> data{};
Expand Down
Loading

0 comments on commit 5711031

Please sign in to comment.