From 72a1ffe66f1b44a6e266b2955fe8f8d915c5f8f1 Mon Sep 17 00:00:00 2001 From: Alvaro Ezquerro Date: Tue, 19 Nov 2024 14:25:10 +0100 Subject: [PATCH 01/17] Implementation of process to select events by their timeStamp --- .../inc/TRestEventTimeSelectionProcess.h | 84 ++++++ .../src/TRestEventTimeSelectionProcess.cxx | 271 ++++++++++++++++++ 2 files changed, 355 insertions(+) create mode 100644 source/framework/analysis/inc/TRestEventTimeSelectionProcess.h create mode 100644 source/framework/analysis/src/TRestEventTimeSelectionProcess.cxx diff --git a/source/framework/analysis/inc/TRestEventTimeSelectionProcess.h b/source/framework/analysis/inc/TRestEventTimeSelectionProcess.h new file mode 100644 index 000000000..54820b05f --- /dev/null +++ b/source/framework/analysis/inc/TRestEventTimeSelectionProcess.h @@ -0,0 +1,84 @@ +/************************************************************************* + * This file is part of the REST software framework. * + * * + * Copyright (C) 2016 GIFNA/TREX (University of Zaragoza) * + * For more information see http://gifna.unizar.es/trex * + * * + * REST is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * REST is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have a copy of the GNU General Public License along with * + * REST in $REST_PATH/LICENSE. * + * If not, see http://www.gnu.org/licenses/. * + * For the list of contributors see $REST_PATH/CREDITS. * + *************************************************************************/ + +#ifndef RestProcess_TRestEventTimeSelectionProcess +#define RestProcess_TRestEventTimeSelectionProcess + +#include + +#include + + +class TRestEventTimeSelectionProcess : public TRestEventProcess { + private: + TRestEvent* fEvent; //! + std::string fFileWithTimes; + Bool_t fIsActiveTime; + Char_t fDelimiter; + Long_t fOffsetTimeInSeconds; + std::vector> fStartEndTimes; + + /// Information about the events processed + + Int_t fNEventsRejected; + Int_t fNEventsSelected; + Double_t fTotalTimeInSeconds; + + void Initialize() override; + + protected: + public: + RESTValue GetInputEvent() const override { return fEvent; } + RESTValue GetOutputEvent() const override { return fEvent; } + + void InitProcess() override; + TRestEvent* ProcessEvent(TRestEvent* inputEvent) override; + void EndProcess() override; + + void PrintMetadata() override; + + // Constructor + TRestEventTimeSelectionProcess(); + // Destructor + ~TRestEventTimeSelectionProcess() {} + + const char* GetProcessName() const override { return "EventTimeSelectionProcess"; } + + std::string GetFileWithTimes() const { return fFileWithTimes; } + + Bool_t GetIsActiveTime() const { return fIsActiveTime; } + Char_t GetDelimiter() const { return fDelimiter; } + + std::vector> GetStartEndTimes() const { return fStartEndTimes; } + std::string GetTimeStampCut(std::string timeStampObsName = "timeStamp", Bool_t useOffset = true, Int_t nTimes = -1); + Int_t GetNEventsRejected() const { return fNEventsRejected; } + Int_t GetNEventsSelected() const { return fNEventsSelected; } + Double_t GetTotalTimeInSeconds() const { return fTotalTimeInSeconds; } + + void SetFileWithTimes(const std::string& fileWithTimes) { fFileWithTimes = fileWithTimes; } + void SetIsActiveTime(Bool_t isActiveTime) { fIsActiveTime = isActiveTime; } + void SetDelimiter(Char_t delimiter) { fDelimiter = delimiter; } + void SetStartEndTimes(const std::vector>& startEndTimes) { fStartEndTimes = startEndTimes; } + + ClassDefOverride(TRestEventTimeSelectionProcess, 1); +}; +#endif diff --git a/source/framework/analysis/src/TRestEventTimeSelectionProcess.cxx b/source/framework/analysis/src/TRestEventTimeSelectionProcess.cxx new file mode 100644 index 000000000..d0b1e107f --- /dev/null +++ b/source/framework/analysis/src/TRestEventTimeSelectionProcess.cxx @@ -0,0 +1,271 @@ +/************************************************************************* + * This file is part of the REST software framework. * + * * + * Copyright (C) 2016 GIFNA/TREX (University of Zaragoza) * + * For more information see http://gifna.unizar.es/trex * + * * + * REST is free software: you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation, either version 3 of the License, or * + * (at your option) any later version. * + * * + * REST is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have a copy of the GNU General Public License along with * + * REST in $REST_PATH/LICENSE. * + * If not, see http://www.gnu.org/licenses/. * + * For the list of contributors see $REST_PATH/CREDITS. * + *************************************************************************/ + +////////////////////////////////////////////////////////////////////////// +/// The TRestEventTimeSelectionProcess allows processing of events that are within +/// a certain time range. The time ranges are read from a file that contains +/// the start and end times of the periods. The file should have the following +/// format (it can have more columns separated by the same delimiter, but the first +/// two columns should be the start and end times and all the other columns +/// will be ignored): +/// \code +/// # This is a comment +/// # Start time,End time +/// 2021-01-01 00:00:00,2021-01-01 01:00:00 +/// 2021-01-01 02:00:00,2021-01-01 03:00:00 +/// 2021-01-01 04:00:00,2021-01-01 05:00:00 +/// \endcode +/// The default delimiter is a comma, but it can be changed by setting the +/// `delimiter` parameter (single character only). The time format is +/// given by the accepted formats of the StringToTimeStamp function. +/// +/// The time ranges can be active or dead periods of time. If the time ranges +/// are active periods of time, the events that are within the time ranges will +/// be selected. If the time ranges are dead periods of time, the events that +/// are outside the time ranges will be selected. Set the `isActiveTime` parameter +/// to `true` to select the events within the time ranges (they represent active periods +/// of time) or to `false` to select the events outside the time ranges (they represent +/// dead periods of time). +/// +/// The number of events selected, rejected and the total time selected are stored in the +/// metadata members. The total time selected is calculated as the sum of the time +/// of all the time ranges, so it represents the total active time in the case of +/// active periods of time, or the total dead time in the case of dead periods of time. +/// +/// ### Parameters +/// * **fileWithTimes**: name of the file that contains the time ranges. +/// * **isActiveTime**: if `true` (default) the time ranges represent active periods of time, if `false` the time ranges represent dead periods of time. +/// * **delimiter**: delimiter used in the file with the time ranges (default is `,`). +/// * **offsetTimeInSeconds**: offset time in seconds to be added to the event time (default is 0). This is useful +/// to correct the time of the events if needed. This number of seconds will be added to the event time before +/// checking if it is within the time ranges. +/// +/// ### Examples +/// Examples for rml files: +/// \code +/// +/// \endcode +///
+/// +/// \warning ** REST is under continuous development.** This documentation +/// is offered to you by the REST community. Your HELP is needed to keep this code +/// up to date. Your feedback will be worth to support this software, please report +/// any problems/suggestions you may find while using it at [The REST Framework +/// forum](http://ezpc10.unizar.es). You are welcome to contribute fixing typos, +/// updating information or adding/proposing new contributions. See also our +/// Contribution +/// Guide. +/// +/// +///-------------------------------------------------------------------------- +/// +/// RESTsoft - Software for Rare Event Searches with TPCs +/// +/// History of developments: +/// 2024-Jun: Use of the processing file itself (no need for external fileWithIDs) +/// Alvaro Ezquerro +/// +/// \class TRestEventTimeSelectionProcess +/// \author Alvaro Ezquerro +/// +///
+/// + +#include "TRestEventTimeSelectionProcess.h" + +using namespace std; + +ClassImp(TRestEventTimeSelectionProcess); + +/////////////////////////////////////////////// +/// \brief Default constructor +/// +TRestEventTimeSelectionProcess::TRestEventTimeSelectionProcess() { Initialize(); } + +/////////////////////////////////////////////// +/// \brief Function to initialize input/output event members and define the +/// section name +/// +void TRestEventTimeSelectionProcess::Initialize() { + SetSectionName(this->ClassName()); + fEvent = nullptr; + fFileWithTimes = ""; + fIsActiveTime = true; + fDelimiter = ','; + fStartEndTimes.clear(); + fOffsetTimeInSeconds = 0; + fNEventsRejected = 0; + fNEventsSelected = 0; + fTotalTimeInSeconds = 0; +} + +/////////////////////////////////////////////// +/// \brief Process initialization. +/// +/// +void TRestEventTimeSelectionProcess::InitProcess() { + // Read the file with the time ranges + if (!fFileWithTimes.empty()) { + fStartEndTimes.clear(); + string line; + ifstream file(fFileWithTimes); + if (file.is_open()) { + while (getline(file, line)) { + if (line[0] == '#') { // understand as comment + continue; + } + std::istringstream lineStream(line); + std::string startDate, endDate; + if (std::getline(lineStream, startDate, fDelimiter) && std::getline(lineStream, endDate, fDelimiter)) { + fStartEndTimes.emplace_back(startDate, endDate); + RESTDebug << "Start: " << startDate << " End: " << endDate << RESTendl; + } + } + file.close(); + } + } + fTotalTimeInSeconds = 0; + for (auto id : fStartEndTimes) { + TTimeStamp startTime = TTimeStamp(StringToTimeStamp(id.first), 0); + TTimeStamp endTime = TTimeStamp(StringToTimeStamp(id.second), 0); + fTotalTimeInSeconds += endTime.AsDouble() - startTime.AsDouble(); + } + fNEventsRejected = 0; + fNEventsSelected = 0; +} + +/////////////////////////////////////////////// +/// \brief The main processing event function +/// +TRestEvent* TRestEventTimeSelectionProcess::ProcessEvent(TRestEvent* inputEvent) { + fEvent = inputEvent; + + TTimeStamp eventTime = fEvent->GetTimeStamp(); + eventTime.Add(TTimeStamp(fOffsetTimeInSeconds)); + if (fIsActiveTime){ // time ranges represent active periods of time + for (auto id : fStartEndTimes) { + TTimeStamp startTime = TTimeStamp(StringToTimeStamp(id.first), 0); + TTimeStamp endTime = TTimeStamp(StringToTimeStamp(id.second), 0); + if (eventTime >= startTime && eventTime <= endTime) { + fNEventsSelected++; + return fEvent; + } + } + } + + if (!fIsActiveTime){ // time ranges represent dead periods of time + Bool_t isInDeadPeriod = false; + for (auto id : fStartEndTimes) { + TTimeStamp startTime = TTimeStamp(StringToTimeStamp(id.first), 0); + TTimeStamp endTime = TTimeStamp(StringToTimeStamp(id.second), 0); + if (eventTime >= startTime && eventTime <= endTime) { + isInDeadPeriod = true; + break; + } + } + if (!isInDeadPeriod) { + fNEventsSelected++; + return fEvent; + } + } + + fNEventsRejected++; + return nullptr; +} + +/////////////////////////////////////////////// +/// \brief Function to include required actions after all events have been +/// processed. +/// +void TRestEventTimeSelectionProcess::EndProcess() { + // Write here the jobs to do when all the events are processed +} + +/////////////////////////////////////////////// +/// \brief Function to get the cut string that reproduce the time selection +/// done by this process (useful for TRestDataSet::MakeCut() for example). +/// \note The cut string can be really long if there are many time ranges and +/// this may cause the following error +/// 'Error in : Too many operators !' when trying to +/// use the cut in TTree->Draw(). In such case, use +/// \code +/// ROOT::v5::TFormula::SetMaxima(10000) // or any other big enough number +/// \endcode +/// to increase the maximum number of operators allowed in a formula. +/// +std::string TRestEventTimeSelectionProcess::GetTimeStampCut(std::string timeStampObsName, Bool_t useOffset, Int_t nTimes) { + std::string timeCut = ""; + std::string timeStampObsNameWithOffset = timeStampObsName; + if (useOffset) { + timeStampObsNameWithOffset += "+" + to_string(fOffsetTimeInSeconds); + } + if (nTimes<0) nTimes = fStartEndTimes.size(); + Int_t c = 0; + for (auto id : fStartEndTimes) { + if (c++ >= nTimes) break; + auto startTime = StringToTimeStamp(id.first); + auto endTime = StringToTimeStamp(id.second); + if (!timeCut.empty()){ + if (fIsActiveTime) timeCut += " || "; + else timeCut += " && "; + } + if (!fIsActiveTime) timeCut += "!"; + timeCut += "("; + timeCut += timeStampObsNameWithOffset + ">=" + to_string(startTime); + timeCut += "&&"; + timeCut += timeStampObsNameWithOffset + "<=" + to_string(endTime); + timeCut += ")"; + } + return timeCut; +} +/////////////////////////////////////////////// +/// \brief Prints on screen the process data members +/// +void TRestEventTimeSelectionProcess::PrintMetadata() { + BeginPrintProcess(); + std::string typeOfTime = fIsActiveTime ? "Active" : "Dead"; + + RESTMetadata << "File with times: " << fFileWithTimes << RESTendl; + // print periods + RESTMetadata << "Offset time: " << fOffsetTimeInSeconds << " seconds" << RESTendl; + RESTMetadata << typeOfTime << " time periods: " << RESTendl; + for (auto id : fStartEndTimes) { + RESTMetadata << id.first << " to " << id.second << RESTendl; + } + + if ((Int_t) (fTotalTimeInSeconds / 24/3600) != 0 ) // order of days + RESTMetadata << "Total " << typeOfTime << " time: " << fTotalTimeInSeconds / 24/3600 << " days" << RESTendl; + else if ((Int_t) (fTotalTimeInSeconds / 3600) != 0 ) // order of hours + RESTMetadata << "Total " << typeOfTime << " time: " << fTotalTimeInSeconds / 3600 << " hours" << RESTendl; + else if ((Int_t) (fTotalTimeInSeconds / 60) != 0 ) // order of minutes + RESTMetadata << "Total " << typeOfTime << " time: " << fTotalTimeInSeconds / 60 << " minutes" << RESTendl; + else + RESTMetadata << "Total " << typeOfTime << " time: " << fTotalTimeInSeconds << RESTendl; + + RESTMetadata << "Number of events rejected: " << fNEventsRejected << " (" + << fNEventsRejected*1. / (fNEventsRejected + fNEventsSelected) * 100 << " %)" << RESTendl; + RESTMetadata << "Number of events selected: " << fNEventsSelected << " (" + << fNEventsSelected*1. / (fNEventsRejected + fNEventsSelected) * 100 << " %)" << RESTendl; + + EndPrintProcess(); +} From b7ce5a361389316afeff70dc5985211108c094fd Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 19 Nov 2024 13:34:50 +0000 Subject: [PATCH 02/17] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- .../inc/TRestEventTimeSelectionProcess.h | 12 ++-- .../src/TRestEventTimeSelectionProcess.cxx | 72 ++++++++++--------- 2 files changed, 46 insertions(+), 38 deletions(-) diff --git a/source/framework/analysis/inc/TRestEventTimeSelectionProcess.h b/source/framework/analysis/inc/TRestEventTimeSelectionProcess.h index 54820b05f..57b10fe08 100644 --- a/source/framework/analysis/inc/TRestEventTimeSelectionProcess.h +++ b/source/framework/analysis/inc/TRestEventTimeSelectionProcess.h @@ -27,7 +27,6 @@ #include - class TRestEventTimeSelectionProcess : public TRestEventProcess { private: TRestEvent* fEvent; //! @@ -35,7 +34,7 @@ class TRestEventTimeSelectionProcess : public TRestEventProcess { Bool_t fIsActiveTime; Char_t fDelimiter; Long_t fOffsetTimeInSeconds; - std::vector> fStartEndTimes; + std::vector> fStartEndTimes; /// Information about the events processed @@ -68,8 +67,9 @@ class TRestEventTimeSelectionProcess : public TRestEventProcess { Bool_t GetIsActiveTime() const { return fIsActiveTime; } Char_t GetDelimiter() const { return fDelimiter; } - std::vector> GetStartEndTimes() const { return fStartEndTimes; } - std::string GetTimeStampCut(std::string timeStampObsName = "timeStamp", Bool_t useOffset = true, Int_t nTimes = -1); + std::vector> GetStartEndTimes() const { return fStartEndTimes; } + std::string GetTimeStampCut(std::string timeStampObsName = "timeStamp", Bool_t useOffset = true, + Int_t nTimes = -1); Int_t GetNEventsRejected() const { return fNEventsRejected; } Int_t GetNEventsSelected() const { return fNEventsSelected; } Double_t GetTotalTimeInSeconds() const { return fTotalTimeInSeconds; } @@ -77,7 +77,9 @@ class TRestEventTimeSelectionProcess : public TRestEventProcess { void SetFileWithTimes(const std::string& fileWithTimes) { fFileWithTimes = fileWithTimes; } void SetIsActiveTime(Bool_t isActiveTime) { fIsActiveTime = isActiveTime; } void SetDelimiter(Char_t delimiter) { fDelimiter = delimiter; } - void SetStartEndTimes(const std::vector>& startEndTimes) { fStartEndTimes = startEndTimes; } + void SetStartEndTimes(const std::vector>& startEndTimes) { + fStartEndTimes = startEndTimes; + } ClassDefOverride(TRestEventTimeSelectionProcess, 1); }; diff --git a/source/framework/analysis/src/TRestEventTimeSelectionProcess.cxx b/source/framework/analysis/src/TRestEventTimeSelectionProcess.cxx index d0b1e107f..362fd483e 100644 --- a/source/framework/analysis/src/TRestEventTimeSelectionProcess.cxx +++ b/source/framework/analysis/src/TRestEventTimeSelectionProcess.cxx @@ -53,19 +53,18 @@ /// /// ### Parameters /// * **fileWithTimes**: name of the file that contains the time ranges. -/// * **isActiveTime**: if `true` (default) the time ranges represent active periods of time, if `false` the time ranges represent dead periods of time. +/// * **isActiveTime**: if `true` (default) the time ranges represent active periods of time, if `false` the +/// time ranges represent dead periods of time. /// * **delimiter**: delimiter used in the file with the time ranges (default is `,`). -/// * **offsetTimeInSeconds**: offset time in seconds to be added to the event time (default is 0). This is useful -/// to correct the time of the events if needed. This number of seconds will be added to the event time before -/// checking if it is within the time ranges. +/// * **offsetTimeInSeconds**: offset time in seconds to be added to the event time (default is 0). This is +/// useful to correct the time of the events if needed. This number of seconds will be added to the event time +/// before checking if it is within the time ranges. /// /// ### Examples /// Examples for rml files: /// \code -/// -/// \endcode -///
+/// \endcode
/// /// \warning ** REST is under continuous development.** This documentation /// is offered to you by the REST community. Your HELP is needed to keep this code @@ -131,12 +130,13 @@ void TRestEventTimeSelectionProcess::InitProcess() { ifstream file(fFileWithTimes); if (file.is_open()) { while (getline(file, line)) { - if (line[0] == '#') { // understand as comment + if (line[0] == '#') { // understand as comment continue; } std::istringstream lineStream(line); std::string startDate, endDate; - if (std::getline(lineStream, startDate, fDelimiter) && std::getline(lineStream, endDate, fDelimiter)) { + if (std::getline(lineStream, startDate, fDelimiter) && + std::getline(lineStream, endDate, fDelimiter)) { fStartEndTimes.emplace_back(startDate, endDate); RESTDebug << "Start: " << startDate << " End: " << endDate << RESTendl; } @@ -162,7 +162,7 @@ TRestEvent* TRestEventTimeSelectionProcess::ProcessEvent(TRestEvent* inputEvent) TTimeStamp eventTime = fEvent->GetTimeStamp(); eventTime.Add(TTimeStamp(fOffsetTimeInSeconds)); - if (fIsActiveTime){ // time ranges represent active periods of time + if (fIsActiveTime) { // time ranges represent active periods of time for (auto id : fStartEndTimes) { TTimeStamp startTime = TTimeStamp(StringToTimeStamp(id.first), 0); TTimeStamp endTime = TTimeStamp(StringToTimeStamp(id.second), 0); @@ -173,7 +173,7 @@ TRestEvent* TRestEventTimeSelectionProcess::ProcessEvent(TRestEvent* inputEvent) } } - if (!fIsActiveTime){ // time ranges represent dead periods of time + if (!fIsActiveTime) { // time ranges represent dead periods of time Bool_t isInDeadPeriod = false; for (auto id : fStartEndTimes) { TTimeStamp startTime = TTimeStamp(StringToTimeStamp(id.first), 0); @@ -193,10 +193,10 @@ TRestEvent* TRestEventTimeSelectionProcess::ProcessEvent(TRestEvent* inputEvent) return nullptr; } -/////////////////////////////////////////////// +/////////////////////////////////////////////// /// \brief Function to include required actions after all events have been -/// processed. -/// +/// processed. +/// void TRestEventTimeSelectionProcess::EndProcess() { // Write here the jobs to do when all the events are processed } @@ -205,29 +205,32 @@ void TRestEventTimeSelectionProcess::EndProcess() { /// \brief Function to get the cut string that reproduce the time selection /// done by this process (useful for TRestDataSet::MakeCut() for example). /// \note The cut string can be really long if there are many time ranges and -/// this may cause the following error -/// 'Error in : Too many operators !' when trying to -/// use the cut in TTree->Draw(). In such case, use -/// \code +/// this may cause the following error +/// 'Error in : Too many operators !' when trying to +/// use the cut in TTree->Draw(). In such case, use +/// \code /// ROOT::v5::TFormula::SetMaxima(10000) // or any other big enough number /// \endcode /// to increase the maximum number of operators allowed in a formula. /// -std::string TRestEventTimeSelectionProcess::GetTimeStampCut(std::string timeStampObsName, Bool_t useOffset, Int_t nTimes) { +std::string TRestEventTimeSelectionProcess::GetTimeStampCut(std::string timeStampObsName, Bool_t useOffset, + Int_t nTimes) { std::string timeCut = ""; std::string timeStampObsNameWithOffset = timeStampObsName; if (useOffset) { timeStampObsNameWithOffset += "+" + to_string(fOffsetTimeInSeconds); } - if (nTimes<0) nTimes = fStartEndTimes.size(); + if (nTimes < 0) nTimes = fStartEndTimes.size(); Int_t c = 0; for (auto id : fStartEndTimes) { if (c++ >= nTimes) break; auto startTime = StringToTimeStamp(id.first); auto endTime = StringToTimeStamp(id.second); - if (!timeCut.empty()){ - if (fIsActiveTime) timeCut += " || "; - else timeCut += " && "; + if (!timeCut.empty()) { + if (fIsActiveTime) + timeCut += " || "; + else + timeCut += " && "; } if (!fIsActiveTime) timeCut += "!"; timeCut += "("; @@ -252,20 +255,23 @@ void TRestEventTimeSelectionProcess::PrintMetadata() { for (auto id : fStartEndTimes) { RESTMetadata << id.first << " to " << id.second << RESTendl; } - - if ((Int_t) (fTotalTimeInSeconds / 24/3600) != 0 ) // order of days - RESTMetadata << "Total " << typeOfTime << " time: " << fTotalTimeInSeconds / 24/3600 << " days" << RESTendl; - else if ((Int_t) (fTotalTimeInSeconds / 3600) != 0 ) // order of hours - RESTMetadata << "Total " << typeOfTime << " time: " << fTotalTimeInSeconds / 3600 << " hours" << RESTendl; - else if ((Int_t) (fTotalTimeInSeconds / 60) != 0 ) // order of minutes - RESTMetadata << "Total " << typeOfTime << " time: " << fTotalTimeInSeconds / 60 << " minutes" << RESTendl; + + if ((Int_t)(fTotalTimeInSeconds / 24 / 3600) != 0) // order of days + RESTMetadata << "Total " << typeOfTime << " time: " << fTotalTimeInSeconds / 24 / 3600 << " days" + << RESTendl; + else if ((Int_t)(fTotalTimeInSeconds / 3600) != 0) // order of hours + RESTMetadata << "Total " << typeOfTime << " time: " << fTotalTimeInSeconds / 3600 << " hours" + << RESTendl; + else if ((Int_t)(fTotalTimeInSeconds / 60) != 0) // order of minutes + RESTMetadata << "Total " << typeOfTime << " time: " << fTotalTimeInSeconds / 60 << " minutes" + << RESTendl; else RESTMetadata << "Total " << typeOfTime << " time: " << fTotalTimeInSeconds << RESTendl; RESTMetadata << "Number of events rejected: " << fNEventsRejected << " (" - << fNEventsRejected*1. / (fNEventsRejected + fNEventsSelected) * 100 << " %)" << RESTendl; + << fNEventsRejected * 1. / (fNEventsRejected + fNEventsSelected) * 100 << " %)" << RESTendl; RESTMetadata << "Number of events selected: " << fNEventsSelected << " (" - << fNEventsSelected*1. / (fNEventsRejected + fNEventsSelected) * 100 << " %)" << RESTendl; + << fNEventsSelected * 1. / (fNEventsRejected + fNEventsSelected) * 100 << " %)" << RESTendl; EndPrintProcess(); } From 3b6fc33bb78cca7b9ef85eebecc6ed6ef3ce18ff Mon Sep 17 00:00:00 2001 From: Alvaro Ezquerro Date: Tue, 14 Jan 2025 12:33:09 +0100 Subject: [PATCH 03/17] implement start and end time margins --- .../inc/TRestEventTimeSelectionProcess.h | 18 +++++-- .../src/TRestEventTimeSelectionProcess.cxx | 48 ++++++++++++++----- 2 files changed, 49 insertions(+), 17 deletions(-) diff --git a/source/framework/analysis/inc/TRestEventTimeSelectionProcess.h b/source/framework/analysis/inc/TRestEventTimeSelectionProcess.h index 57b10fe08..daca471c9 100644 --- a/source/framework/analysis/inc/TRestEventTimeSelectionProcess.h +++ b/source/framework/analysis/inc/TRestEventTimeSelectionProcess.h @@ -33,8 +33,10 @@ class TRestEventTimeSelectionProcess : public TRestEventProcess { std::string fFileWithTimes; Bool_t fIsActiveTime; Char_t fDelimiter; - Long_t fOffsetTimeInSeconds; - std::vector> fStartEndTimes; + Long_t fTimeOffsetInSeconds; + Long_t fTimeStartMarginInSeconds; + Long_t fTimeEndMarginInSeconds; + std::vector> fStartEndTimes; /// Information about the events processed @@ -73,13 +75,19 @@ class TRestEventTimeSelectionProcess : public TRestEventProcess { Int_t GetNEventsRejected() const { return fNEventsRejected; } Int_t GetNEventsSelected() const { return fNEventsSelected; } Double_t GetTotalTimeInSeconds() const { return fTotalTimeInSeconds; } + Long_t GetTimeOffsetInSeconds() const { return fTimeOffsetInSeconds; } + Long_t GetTimeStartMarginInSeconds() const { return fTimeStartMarginInSeconds; } + Long_t GetTimeEndMarginInSeconds() const { return fTimeEndMarginInSeconds; } + + Double_t CalculateTotalTimeInSeconds(); void SetFileWithTimes(const std::string& fileWithTimes) { fFileWithTimes = fileWithTimes; } void SetIsActiveTime(Bool_t isActiveTime) { fIsActiveTime = isActiveTime; } void SetDelimiter(Char_t delimiter) { fDelimiter = delimiter; } - void SetStartEndTimes(const std::vector>& startEndTimes) { - fStartEndTimes = startEndTimes; - } + void SetStartEndTimes(const std::vector>& startEndTimes) { fStartEndTimes = startEndTimes; } + void SetTimeOffsetInSeconds(Long_t timeOffsetInSeconds) { fTimeOffsetInSeconds = timeOffsetInSeconds; } + void SetTimeStartMarginInSeconds(Long_t timeStartMarginInSeconds) { fTimeStartMarginInSeconds = timeStartMarginInSeconds; } + void SetTimeEndMarginInSeconds(Long_t timeEndMarginInSeconds) { fTimeEndMarginInSeconds = timeEndMarginInSeconds; } ClassDefOverride(TRestEventTimeSelectionProcess, 1); }; diff --git a/source/framework/analysis/src/TRestEventTimeSelectionProcess.cxx b/source/framework/analysis/src/TRestEventTimeSelectionProcess.cxx index 362fd483e..5634674e8 100644 --- a/source/framework/analysis/src/TRestEventTimeSelectionProcess.cxx +++ b/source/framework/analysis/src/TRestEventTimeSelectionProcess.cxx @@ -112,7 +112,9 @@ void TRestEventTimeSelectionProcess::Initialize() { fIsActiveTime = true; fDelimiter = ','; fStartEndTimes.clear(); - fOffsetTimeInSeconds = 0; + fTimeOffsetInSeconds = 0; + fTimeStartMarginInSeconds = 0; + fTimeEndMarginInSeconds = 0; fNEventsRejected = 0; fNEventsSelected = 0; fTotalTimeInSeconds = 0; @@ -144,14 +146,27 @@ void TRestEventTimeSelectionProcess::InitProcess() { file.close(); } } - fTotalTimeInSeconds = 0; + fTotalTimeInSeconds = CalculateTotalTimeInSeconds(); + fNEventsRejected = 0; + fNEventsSelected = 0; +} + +Double_t TRestEventTimeSelectionProcess::CalculateTotalTimeInSeconds(){ + Double_t totalTime = 0; for (auto id : fStartEndTimes) { TTimeStamp startTime = TTimeStamp(StringToTimeStamp(id.first), 0); TTimeStamp endTime = TTimeStamp(StringToTimeStamp(id.second), 0); - fTotalTimeInSeconds += endTime.AsDouble() - startTime.AsDouble(); + // Reduce the time by the margin in both sides + startTime.Add(TTimeStamp(fTimeStartMarginInSeconds)); + endTime.Add(TTimeStamp(-fTimeEndMarginInSeconds)); + auto timeDiff = endTime.AsDouble() - startTime.AsDouble(); + if (timeDiff < 0) { + RESTDebug << "End time is before start time in time range: " << id.first << " to " << id.second << RESTendl; + continue; + } + totalTime += endTime.AsDouble() - startTime.AsDouble(); } - fNEventsRejected = 0; - fNEventsSelected = 0; + return totalTime; } /////////////////////////////////////////////// @@ -166,6 +181,9 @@ TRestEvent* TRestEventTimeSelectionProcess::ProcessEvent(TRestEvent* inputEvent) for (auto id : fStartEndTimes) { TTimeStamp startTime = TTimeStamp(StringToTimeStamp(id.first), 0); TTimeStamp endTime = TTimeStamp(StringToTimeStamp(id.second), 0); + // Reduce the time by the margin in both sides + startTime.Add(TTimeStamp(fTimeStartMarginInSeconds)); + endTime.Add(TTimeStamp(-fTimeEndMarginInSeconds)); if (eventTime >= startTime && eventTime <= endTime) { fNEventsSelected++; return fEvent; @@ -178,6 +196,9 @@ TRestEvent* TRestEventTimeSelectionProcess::ProcessEvent(TRestEvent* inputEvent) for (auto id : fStartEndTimes) { TTimeStamp startTime = TTimeStamp(StringToTimeStamp(id.first), 0); TTimeStamp endTime = TTimeStamp(StringToTimeStamp(id.second), 0); + // Reduce the time by the margin in both sides + startTime.Add(TTimeStamp(fTimeStartMarginInSeconds)); + endTime.Add(TTimeStamp(-fTimeEndMarginInSeconds)); if (eventTime >= startTime && eventTime <= endTime) { isInDeadPeriod = true; break; @@ -218,7 +239,7 @@ std::string TRestEventTimeSelectionProcess::GetTimeStampCut(std::string timeStam std::string timeCut = ""; std::string timeStampObsNameWithOffset = timeStampObsName; if (useOffset) { - timeStampObsNameWithOffset += "+" + to_string(fOffsetTimeInSeconds); + timeStampObsNameWithOffset += "+" + to_string(fTimeOffsetInSeconds); } if (nTimes < 0) nTimes = fStartEndTimes.size(); Int_t c = 0; @@ -226,11 +247,12 @@ std::string TRestEventTimeSelectionProcess::GetTimeStampCut(std::string timeStam if (c++ >= nTimes) break; auto startTime = StringToTimeStamp(id.first); auto endTime = StringToTimeStamp(id.second); - if (!timeCut.empty()) { - if (fIsActiveTime) - timeCut += " || "; - else - timeCut += " && "; + // Reduce the time by the margin in both sides + startTime += fTimeStartMarginInSeconds; + endTime -= fTimeEndMarginInSeconds; + if (!timeCut.empty()){ + if (fIsActiveTime) timeCut += " || "; + else timeCut += " && "; } if (!fIsActiveTime) timeCut += "!"; timeCut += "("; @@ -250,7 +272,9 @@ void TRestEventTimeSelectionProcess::PrintMetadata() { RESTMetadata << "File with times: " << fFileWithTimes << RESTendl; // print periods - RESTMetadata << "Offset time: " << fOffsetTimeInSeconds << " seconds" << RESTendl; + RESTMetadata << "Offset time: " << fTimeOffsetInSeconds << " seconds" << RESTendl; + RESTMetadata << "Start margin time: " << fTimeStartMarginInSeconds << " seconds" << RESTendl; + RESTMetadata << "End margin time: " << fTimeEndMarginInSeconds << " seconds" << RESTendl; RESTMetadata << typeOfTime << " time periods: " << RESTendl; for (auto id : fStartEndTimes) { RESTMetadata << id.first << " to " << id.second << RESTendl; From 176741a2559806424cdfd01a85c4d8b3b1e5e05e Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Tue, 14 Jan 2025 11:38:33 +0000 Subject: [PATCH 04/17] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- .../analysis/inc/TRestEventTimeSelectionProcess.h | 14 ++++++++++---- .../src/TRestEventTimeSelectionProcess.cxx | 13 ++++++++----- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/source/framework/analysis/inc/TRestEventTimeSelectionProcess.h b/source/framework/analysis/inc/TRestEventTimeSelectionProcess.h index daca471c9..7a0a0559f 100644 --- a/source/framework/analysis/inc/TRestEventTimeSelectionProcess.h +++ b/source/framework/analysis/inc/TRestEventTimeSelectionProcess.h @@ -36,7 +36,7 @@ class TRestEventTimeSelectionProcess : public TRestEventProcess { Long_t fTimeOffsetInSeconds; Long_t fTimeStartMarginInSeconds; Long_t fTimeEndMarginInSeconds; - std::vector> fStartEndTimes; + std::vector> fStartEndTimes; /// Information about the events processed @@ -84,10 +84,16 @@ class TRestEventTimeSelectionProcess : public TRestEventProcess { void SetFileWithTimes(const std::string& fileWithTimes) { fFileWithTimes = fileWithTimes; } void SetIsActiveTime(Bool_t isActiveTime) { fIsActiveTime = isActiveTime; } void SetDelimiter(Char_t delimiter) { fDelimiter = delimiter; } - void SetStartEndTimes(const std::vector>& startEndTimes) { fStartEndTimes = startEndTimes; } + void SetStartEndTimes(const std::vector>& startEndTimes) { + fStartEndTimes = startEndTimes; + } void SetTimeOffsetInSeconds(Long_t timeOffsetInSeconds) { fTimeOffsetInSeconds = timeOffsetInSeconds; } - void SetTimeStartMarginInSeconds(Long_t timeStartMarginInSeconds) { fTimeStartMarginInSeconds = timeStartMarginInSeconds; } - void SetTimeEndMarginInSeconds(Long_t timeEndMarginInSeconds) { fTimeEndMarginInSeconds = timeEndMarginInSeconds; } + void SetTimeStartMarginInSeconds(Long_t timeStartMarginInSeconds) { + fTimeStartMarginInSeconds = timeStartMarginInSeconds; + } + void SetTimeEndMarginInSeconds(Long_t timeEndMarginInSeconds) { + fTimeEndMarginInSeconds = timeEndMarginInSeconds; + } ClassDefOverride(TRestEventTimeSelectionProcess, 1); }; diff --git a/source/framework/analysis/src/TRestEventTimeSelectionProcess.cxx b/source/framework/analysis/src/TRestEventTimeSelectionProcess.cxx index 5634674e8..1cce1ef8e 100644 --- a/source/framework/analysis/src/TRestEventTimeSelectionProcess.cxx +++ b/source/framework/analysis/src/TRestEventTimeSelectionProcess.cxx @@ -151,7 +151,7 @@ void TRestEventTimeSelectionProcess::InitProcess() { fNEventsSelected = 0; } -Double_t TRestEventTimeSelectionProcess::CalculateTotalTimeInSeconds(){ +Double_t TRestEventTimeSelectionProcess::CalculateTotalTimeInSeconds() { Double_t totalTime = 0; for (auto id : fStartEndTimes) { TTimeStamp startTime = TTimeStamp(StringToTimeStamp(id.first), 0); @@ -161,7 +161,8 @@ Double_t TRestEventTimeSelectionProcess::CalculateTotalTimeInSeconds(){ endTime.Add(TTimeStamp(-fTimeEndMarginInSeconds)); auto timeDiff = endTime.AsDouble() - startTime.AsDouble(); if (timeDiff < 0) { - RESTDebug << "End time is before start time in time range: " << id.first << " to " << id.second << RESTendl; + RESTDebug << "End time is before start time in time range: " << id.first << " to " << id.second + << RESTendl; continue; } totalTime += endTime.AsDouble() - startTime.AsDouble(); @@ -250,9 +251,11 @@ std::string TRestEventTimeSelectionProcess::GetTimeStampCut(std::string timeStam // Reduce the time by the margin in both sides startTime += fTimeStartMarginInSeconds; endTime -= fTimeEndMarginInSeconds; - if (!timeCut.empty()){ - if (fIsActiveTime) timeCut += " || "; - else timeCut += " && "; + if (!timeCut.empty()) { + if (fIsActiveTime) + timeCut += " || "; + else + timeCut += " && "; } if (!fIsActiveTime) timeCut += "!"; timeCut += "("; From d1e99bd734f09bcd0ea378fc1ed5c83d69c718c1 Mon Sep 17 00:00:00 2001 From: Alvaro Ezquerro Date: Fri, 17 Jan 2025 10:52:33 +0100 Subject: [PATCH 05/17] fix typo --- .../framework/analysis/src/TRestEventTimeSelectionProcess.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/framework/analysis/src/TRestEventTimeSelectionProcess.cxx b/source/framework/analysis/src/TRestEventTimeSelectionProcess.cxx index 1cce1ef8e..cf4fb6c4c 100644 --- a/source/framework/analysis/src/TRestEventTimeSelectionProcess.cxx +++ b/source/framework/analysis/src/TRestEventTimeSelectionProcess.cxx @@ -177,7 +177,7 @@ TRestEvent* TRestEventTimeSelectionProcess::ProcessEvent(TRestEvent* inputEvent) fEvent = inputEvent; TTimeStamp eventTime = fEvent->GetTimeStamp(); - eventTime.Add(TTimeStamp(fOffsetTimeInSeconds)); + eventTime.Add(TTimeStamp(fTimeOffsetInSeconds)); if (fIsActiveTime) { // time ranges represent active periods of time for (auto id : fStartEndTimes) { TTimeStamp startTime = TTimeStamp(StringToTimeStamp(id.first), 0); From 5946603fc45e13dcc20590997a7e7fc3435eea25 Mon Sep 17 00:00:00 2001 From: Alvaro Ezquerro Date: Fri, 17 Jan 2025 11:29:26 +0100 Subject: [PATCH 06/17] refactor event time selection logic for clarity --- .../src/TRestEventTimeSelectionProcess.cxx | 44 +++++++++---------- 1 file changed, 20 insertions(+), 24 deletions(-) diff --git a/source/framework/analysis/src/TRestEventTimeSelectionProcess.cxx b/source/framework/analysis/src/TRestEventTimeSelectionProcess.cxx index cf4fb6c4c..e62ffaab8 100644 --- a/source/framework/analysis/src/TRestEventTimeSelectionProcess.cxx +++ b/source/framework/analysis/src/TRestEventTimeSelectionProcess.cxx @@ -178,39 +178,35 @@ TRestEvent* TRestEventTimeSelectionProcess::ProcessEvent(TRestEvent* inputEvent) TTimeStamp eventTime = fEvent->GetTimeStamp(); eventTime.Add(TTimeStamp(fTimeOffsetInSeconds)); - if (fIsActiveTime) { // time ranges represent active periods of time - for (auto id : fStartEndTimes) { - TTimeStamp startTime = TTimeStamp(StringToTimeStamp(id.first), 0); - TTimeStamp endTime = TTimeStamp(StringToTimeStamp(id.second), 0); - // Reduce the time by the margin in both sides - startTime.Add(TTimeStamp(fTimeStartMarginInSeconds)); - endTime.Add(TTimeStamp(-fTimeEndMarginInSeconds)); - if (eventTime >= startTime && eventTime <= endTime) { - fNEventsSelected++; - return fEvent; - } + + Bool_t isInsideAnyTimeRange = false; + for (auto id : fStartEndTimes) { + TTimeStamp startTime = TTimeStamp(StringToTimeStamp(id.first), 0); + TTimeStamp endTime = TTimeStamp(StringToTimeStamp(id.second), 0); + // Reduce the time by the margin in both sides + startTime.Add(TTimeStamp(fTimeStartMarginInSeconds)); + endTime.Add(TTimeStamp(-fTimeEndMarginInSeconds)); + if (eventTime >= startTime && eventTime <= endTime) { + isInsideAnyTimeRange = true; + break; } } - if (!fIsActiveTime) { // time ranges represent dead periods of time - Bool_t isInDeadPeriod = false; - for (auto id : fStartEndTimes) { - TTimeStamp startTime = TTimeStamp(StringToTimeStamp(id.first), 0); - TTimeStamp endTime = TTimeStamp(StringToTimeStamp(id.second), 0); - // Reduce the time by the margin in both sides - startTime.Add(TTimeStamp(fTimeStartMarginInSeconds)); - endTime.Add(TTimeStamp(-fTimeEndMarginInSeconds)); - if (eventTime >= startTime && eventTime <= endTime) { - isInDeadPeriod = true; - break; - } + // Decide if the event is selected or rejected based on the time ranges + // and their meaning (active or dead periods of time). + if (fIsActiveTime) { // time ranges represent active periods of time + if (isInsideAnyTimeRange) { // time is inside an active period of time + fNEventsSelected++; + return fEvent; } - if (!isInDeadPeriod) { + } else { // time ranges represent dead periods of time + if (!isInsideAnyTimeRange) { // time is outside all dead period of time fNEventsSelected++; return fEvent; } } + // rejected events are not returned fNEventsRejected++; return nullptr; } From 39d8baa581ce803f81f124df1fe517ca16dc5b59 Mon Sep 17 00:00:00 2001 From: Alvaro Ezquerro Date: Fri, 17 Jan 2025 11:30:04 +0100 Subject: [PATCH 07/17] improve documentation --- .../analysis/src/TRestEventTimeSelectionProcess.cxx | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/source/framework/analysis/src/TRestEventTimeSelectionProcess.cxx b/source/framework/analysis/src/TRestEventTimeSelectionProcess.cxx index e62ffaab8..f3ef89afc 100644 --- a/source/framework/analysis/src/TRestEventTimeSelectionProcess.cxx +++ b/source/framework/analysis/src/TRestEventTimeSelectionProcess.cxx @@ -151,6 +151,11 @@ void TRestEventTimeSelectionProcess::InitProcess() { fNEventsSelected = 0; } +/////////////////////////////////////////////// +/// \brief Function to calculate the total time in seconds of all the time ranges +/// (active or dead periods of time). It takes into account the time offset, +/// and both the start and end margins. +/// Double_t TRestEventTimeSelectionProcess::CalculateTotalTimeInSeconds() { Double_t totalTime = 0; for (auto id : fStartEndTimes) { From cc9ab7ad278d70d047c6e3d7becfcd0f2c182981 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 17 Jan 2025 10:30:49 +0000 Subject: [PATCH 08/17] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- .../analysis/src/TRestEventTimeSelectionProcess.cxx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/source/framework/analysis/src/TRestEventTimeSelectionProcess.cxx b/source/framework/analysis/src/TRestEventTimeSelectionProcess.cxx index f3ef89afc..69be8db16 100644 --- a/source/framework/analysis/src/TRestEventTimeSelectionProcess.cxx +++ b/source/framework/analysis/src/TRestEventTimeSelectionProcess.cxx @@ -199,13 +199,13 @@ TRestEvent* TRestEventTimeSelectionProcess::ProcessEvent(TRestEvent* inputEvent) // Decide if the event is selected or rejected based on the time ranges // and their meaning (active or dead periods of time). - if (fIsActiveTime) { // time ranges represent active periods of time - if (isInsideAnyTimeRange) { // time is inside an active period of time + if (fIsActiveTime) { // time ranges represent active periods of time + if (isInsideAnyTimeRange) { // time is inside an active period of time fNEventsSelected++; return fEvent; } - } else { // time ranges represent dead periods of time - if (!isInsideAnyTimeRange) { // time is outside all dead period of time + } else { // time ranges represent dead periods of time + if (!isInsideAnyTimeRange) { // time is outside all dead period of time fNEventsSelected++; return fEvent; } From 69c176a0e8598235ceaef304ebfb8d901b56a17a Mon Sep 17 00:00:00 2001 From: Alvaro Ezquerro Date: Sat, 18 Jan 2025 18:02:15 +0100 Subject: [PATCH 09/17] validate time format in event time selection process --- .../analysis/src/TRestEventTimeSelectionProcess.cxx | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/source/framework/analysis/src/TRestEventTimeSelectionProcess.cxx b/source/framework/analysis/src/TRestEventTimeSelectionProcess.cxx index 69be8db16..52280f09f 100644 --- a/source/framework/analysis/src/TRestEventTimeSelectionProcess.cxx +++ b/source/framework/analysis/src/TRestEventTimeSelectionProcess.cxx @@ -139,6 +139,14 @@ void TRestEventTimeSelectionProcess::InitProcess() { std::string startDate, endDate; if (std::getline(lineStream, startDate, fDelimiter) && std::getline(lineStream, endDate, fDelimiter)) { + + // check if the time format is correct. TODO: use better way to check + // (StringToTimeStamp usually returns a negative big number if not) + if (StringToTimeStamp(startDate)<0 || StringToTimeStamp(endDate)<0) { + RESTDebug << "Time format is not correct in line: " << line << RESTendl; + continue; + } + fStartEndTimes.emplace_back(startDate, endDate); RESTDebug << "Start: " << startDate << " End: " << endDate << RESTendl; } From 7651fd6fd9c41a7dd85f69beb1ae56c770d89dea Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sat, 18 Jan 2025 17:02:59 +0000 Subject: [PATCH 10/17] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- .../framework/analysis/src/TRestEventTimeSelectionProcess.cxx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/source/framework/analysis/src/TRestEventTimeSelectionProcess.cxx b/source/framework/analysis/src/TRestEventTimeSelectionProcess.cxx index 52280f09f..1926d923e 100644 --- a/source/framework/analysis/src/TRestEventTimeSelectionProcess.cxx +++ b/source/framework/analysis/src/TRestEventTimeSelectionProcess.cxx @@ -139,10 +139,9 @@ void TRestEventTimeSelectionProcess::InitProcess() { std::string startDate, endDate; if (std::getline(lineStream, startDate, fDelimiter) && std::getline(lineStream, endDate, fDelimiter)) { - // check if the time format is correct. TODO: use better way to check // (StringToTimeStamp usually returns a negative big number if not) - if (StringToTimeStamp(startDate)<0 || StringToTimeStamp(endDate)<0) { + if (StringToTimeStamp(startDate) < 0 || StringToTimeStamp(endDate) < 0) { RESTDebug << "Time format is not correct in line: " << line << RESTendl; continue; } From 0387113a55800fe39699619d923c263d022c7019 Mon Sep 17 00:00:00 2001 From: Alvaro Ezquerro Date: Sun, 19 Jan 2025 15:42:01 +0100 Subject: [PATCH 11/17] improve GetTimeStampCut method --- .../inc/TRestEventTimeSelectionProcess.h | 2 +- .../src/TRestEventTimeSelectionProcess.cxx | 29 ++++++++++++------- 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/source/framework/analysis/inc/TRestEventTimeSelectionProcess.h b/source/framework/analysis/inc/TRestEventTimeSelectionProcess.h index 7a0a0559f..c16334d1b 100644 --- a/source/framework/analysis/inc/TRestEventTimeSelectionProcess.h +++ b/source/framework/analysis/inc/TRestEventTimeSelectionProcess.h @@ -71,7 +71,7 @@ class TRestEventTimeSelectionProcess : public TRestEventProcess { std::vector> GetStartEndTimes() const { return fStartEndTimes; } std::string GetTimeStampCut(std::string timeStampObsName = "timeStamp", Bool_t useOffset = true, - Int_t nTimes = -1); + Bool_t useMargins = true, Int_t nTimes = -1); Int_t GetNEventsRejected() const { return fNEventsRejected; } Int_t GetNEventsSelected() const { return fNEventsSelected; } Double_t GetTotalTimeInSeconds() const { return fTotalTimeInSeconds; } diff --git a/source/framework/analysis/src/TRestEventTimeSelectionProcess.cxx b/source/framework/analysis/src/TRestEventTimeSelectionProcess.cxx index 1926d923e..6b7845d27 100644 --- a/source/framework/analysis/src/TRestEventTimeSelectionProcess.cxx +++ b/source/framework/analysis/src/TRestEventTimeSelectionProcess.cxx @@ -244,10 +244,10 @@ void TRestEventTimeSelectionProcess::EndProcess() { /// to increase the maximum number of operators allowed in a formula. /// std::string TRestEventTimeSelectionProcess::GetTimeStampCut(std::string timeStampObsName, Bool_t useOffset, - Int_t nTimes) { + Bool_t useMargins, Int_t nTimes) { std::string timeCut = ""; std::string timeStampObsNameWithOffset = timeStampObsName; - if (useOffset) { + if (useOffset && fTimeOffsetInSeconds != 0) { timeStampObsNameWithOffset += "+" + to_string(fTimeOffsetInSeconds); } if (nTimes < 0) nTimes = fStartEndTimes.size(); @@ -257,19 +257,28 @@ std::string TRestEventTimeSelectionProcess::GetTimeStampCut(std::string timeStam auto startTime = StringToTimeStamp(id.first); auto endTime = StringToTimeStamp(id.second); // Reduce the time by the margin in both sides - startTime += fTimeStartMarginInSeconds; - endTime -= fTimeEndMarginInSeconds; + if (useMargins) { + startTime += fTimeStartMarginInSeconds; + endTime -= fTimeEndMarginInSeconds; + } + + if (startTime >= endTime) { + continue; + } + + // Build the cut string if (!timeCut.empty()) { if (fIsActiveTime) - timeCut += " || "; + timeCut += " || "; // inside ANY time range else - timeCut += " && "; + timeCut += " && "; // outside ALL time ranges } - if (!fIsActiveTime) timeCut += "!"; + if (!fIsActiveTime) timeCut += "!"; // NOT inside the time range + // inside the time range timeCut += "("; - timeCut += timeStampObsNameWithOffset + ">=" + to_string(startTime); - timeCut += "&&"; - timeCut += timeStampObsNameWithOffset + "<=" + to_string(endTime); + timeCut += "(" + timeStampObsNameWithOffset + ">=" + to_string(startTime) + ")"; + timeCut += " && "; + timeCut += "(" + timeStampObsNameWithOffset + "<=" + to_string(endTime) + ")"; timeCut += ")"; } return timeCut; From ab5a0e17b1a5e34afbfc2e684e1322d2821250c1 Mon Sep 17 00:00:00 2001 From: Alvaro Ezquerro Date: Sun, 19 Jan 2025 15:43:51 +0100 Subject: [PATCH 12/17] enhance PrintMetadata output with total time fraction --- .../src/TRestEventTimeSelectionProcess.cxx | 22 +++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/source/framework/analysis/src/TRestEventTimeSelectionProcess.cxx b/source/framework/analysis/src/TRestEventTimeSelectionProcess.cxx index 6b7845d27..5b0056021 100644 --- a/source/framework/analysis/src/TRestEventTimeSelectionProcess.cxx +++ b/source/framework/analysis/src/TRestEventTimeSelectionProcess.cxx @@ -298,19 +298,33 @@ void TRestEventTimeSelectionProcess::PrintMetadata() { RESTMetadata << typeOfTime << " time periods: " << RESTendl; for (auto id : fStartEndTimes) { RESTMetadata << id.first << " to " << id.second << RESTendl; + TTimeStamp startTime = TTimeStamp(StringToTimeStamp(id.first), 0); + TTimeStamp endTime = TTimeStamp(StringToTimeStamp(id.second), 0); } + // Get total time in seconds + TTimeStamp totalTime = TTimeStamp(fTotalTimeInSeconds, 0); + if (!fStartEndTimes.empty()) { + TTimeStamp firstTime = TTimeStamp(StringToTimeStamp(fStartEndTimes.front().first), 0); + TTimeStamp lastTime = TTimeStamp(StringToTimeStamp(fStartEndTimes.back().second), 0); + totalTime = lastTime - firstTime; + } + + double fractionOfTime = fTotalTimeInSeconds / totalTime.AsDouble() * 100; + std::string fractionOfTimeStr = StringWithPrecision(fractionOfTime, 4) + " %"; if ((Int_t)(fTotalTimeInSeconds / 24 / 3600) != 0) // order of days RESTMetadata << "Total " << typeOfTime << " time: " << fTotalTimeInSeconds / 24 / 3600 << " days" - << RESTendl; + << " (" << fractionOfTimeStr << ")" << RESTendl; else if ((Int_t)(fTotalTimeInSeconds / 3600) != 0) // order of hours RESTMetadata << "Total " << typeOfTime << " time: " << fTotalTimeInSeconds / 3600 << " hours" - << RESTendl; + << " (" << fractionOfTimeStr << ")" << RESTendl; else if ((Int_t)(fTotalTimeInSeconds / 60) != 0) // order of minutes RESTMetadata << "Total " << typeOfTime << " time: " << fTotalTimeInSeconds / 60 << " minutes" - << RESTendl; + << " (" << fractionOfTimeStr << ")" << RESTendl; else - RESTMetadata << "Total " << typeOfTime << " time: " << fTotalTimeInSeconds << RESTendl; + RESTMetadata << "Total " << typeOfTime << " time: " << fTotalTimeInSeconds << " seconds" + << " (" << fractionOfTimeStr << ")" << RESTendl; + RESTMetadata << "Number of events rejected: " << fNEventsRejected << " (" << fNEventsRejected * 1. / (fNEventsRejected + fNEventsSelected) * 100 << " %)" << RESTendl; From 4541f363bc00975402597a6358dd325b0f37708d Mon Sep 17 00:00:00 2001 From: Alvaro Ezquerro Date: Sun, 19 Jan 2025 15:46:07 +0100 Subject: [PATCH 13/17] add ReadFileWithTimes method to streamline time range file processing --- .../inc/TRestEventTimeSelectionProcess.h | 2 + .../src/TRestEventTimeSelectionProcess.cxx | 51 ++++++++++--------- 2 files changed, 30 insertions(+), 23 deletions(-) diff --git a/source/framework/analysis/inc/TRestEventTimeSelectionProcess.h b/source/framework/analysis/inc/TRestEventTimeSelectionProcess.h index c16334d1b..7ab17e9af 100644 --- a/source/framework/analysis/inc/TRestEventTimeSelectionProcess.h +++ b/source/framework/analysis/inc/TRestEventTimeSelectionProcess.h @@ -80,6 +80,8 @@ class TRestEventTimeSelectionProcess : public TRestEventProcess { Long_t GetTimeEndMarginInSeconds() const { return fTimeEndMarginInSeconds; } Double_t CalculateTotalTimeInSeconds(); + static std::vector> ReadFileWithTimes(std::string fileWithTimes, + Char_t delimiter = ','); void SetFileWithTimes(const std::string& fileWithTimes) { fFileWithTimes = fileWithTimes; } void SetIsActiveTime(Bool_t isActiveTime) { fIsActiveTime = isActiveTime; } diff --git a/source/framework/analysis/src/TRestEventTimeSelectionProcess.cxx b/source/framework/analysis/src/TRestEventTimeSelectionProcess.cxx index 5b0056021..69d7b37a1 100644 --- a/source/framework/analysis/src/TRestEventTimeSelectionProcess.cxx +++ b/source/framework/analysis/src/TRestEventTimeSelectionProcess.cxx @@ -127,37 +127,42 @@ void TRestEventTimeSelectionProcess::Initialize() { void TRestEventTimeSelectionProcess::InitProcess() { // Read the file with the time ranges if (!fFileWithTimes.empty()) { - fStartEndTimes.clear(); - string line; - ifstream file(fFileWithTimes); - if (file.is_open()) { - while (getline(file, line)) { - if (line[0] == '#') { // understand as comment + fStartEndTimes = ReadFileWithTimes(fFileWithTimes, fDelimiter); + } + fTotalTimeInSeconds = CalculateTotalTimeInSeconds(); + fNEventsRejected = 0; + fNEventsSelected = 0; +} + +std::vector> TRestEventTimeSelectionProcess::ReadFileWithTimes( + std::string fileWithTimes, Char_t delimiter) { + std::vector> startEndTimes; + string line; + ifstream file(fileWithTimes); + if (file.is_open()) { + while (getline(file, line)) { + if (line[0] == '#') { // understand as comment + continue; + } + std::istringstream lineStream(line); + std::string startDate, endDate; + if (std::getline(lineStream, startDate, delimiter) && + std::getline(lineStream, endDate, delimiter)) { + // check if the time format is correct. TODO: use better way to check + // (StringToTimeStamp usually returns a negative big number if not) + if (StringToTimeStamp(startDate) < 0 || StringToTimeStamp(endDate) < 0) { continue; } - std::istringstream lineStream(line); - std::string startDate, endDate; - if (std::getline(lineStream, startDate, fDelimiter) && - std::getline(lineStream, endDate, fDelimiter)) { - // check if the time format is correct. TODO: use better way to check - // (StringToTimeStamp usually returns a negative big number if not) - if (StringToTimeStamp(startDate) < 0 || StringToTimeStamp(endDate) < 0) { - RESTDebug << "Time format is not correct in line: " << line << RESTendl; - continue; - } - fStartEndTimes.emplace_back(startDate, endDate); - RESTDebug << "Start: " << startDate << " End: " << endDate << RESTendl; - } + startEndTimes.emplace_back(startDate, endDate); } - file.close(); } + file.close(); } - fTotalTimeInSeconds = CalculateTotalTimeInSeconds(); - fNEventsRejected = 0; - fNEventsSelected = 0; + return startEndTimes; } + /////////////////////////////////////////////// /// \brief Function to calculate the total time in seconds of all the time ranges /// (active or dead periods of time). It takes into account the time offset, From c019c541a7c8b24e6bf273476447595631e6b2c7 Mon Sep 17 00:00:00 2001 From: Alvaro Ezquerro Date: Sun, 19 Jan 2025 15:46:26 +0100 Subject: [PATCH 14/17] add specific methods to set active and dead time states --- source/framework/analysis/inc/TRestEventTimeSelectionProcess.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/source/framework/analysis/inc/TRestEventTimeSelectionProcess.h b/source/framework/analysis/inc/TRestEventTimeSelectionProcess.h index 7ab17e9af..98604e53b 100644 --- a/source/framework/analysis/inc/TRestEventTimeSelectionProcess.h +++ b/source/framework/analysis/inc/TRestEventTimeSelectionProcess.h @@ -83,6 +83,8 @@ class TRestEventTimeSelectionProcess : public TRestEventProcess { static std::vector> ReadFileWithTimes(std::string fileWithTimes, Char_t delimiter = ','); + void SetAsActiveTime() { fIsActiveTime = true; } + void SetAsDeadTime() { fIsActiveTime = false; } void SetFileWithTimes(const std::string& fileWithTimes) { fFileWithTimes = fileWithTimes; } void SetIsActiveTime(Bool_t isActiveTime) { fIsActiveTime = isActiveTime; } void SetDelimiter(Char_t delimiter) { fDelimiter = delimiter; } From 3a5de6cb2ecdb56c4929da503c0b1f60a47ef79c Mon Sep 17 00:00:00 2001 From: Alvaro Ezquerro Date: Sun, 19 Jan 2025 15:46:53 +0100 Subject: [PATCH 15/17] add margin time parameters to documentation --- .../analysis/src/TRestEventTimeSelectionProcess.cxx | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/source/framework/analysis/src/TRestEventTimeSelectionProcess.cxx b/source/framework/analysis/src/TRestEventTimeSelectionProcess.cxx index 69d7b37a1..58771e0bb 100644 --- a/source/framework/analysis/src/TRestEventTimeSelectionProcess.cxx +++ b/source/framework/analysis/src/TRestEventTimeSelectionProcess.cxx @@ -59,6 +59,14 @@ /// * **offsetTimeInSeconds**: offset time in seconds to be added to the event time (default is 0). This is /// useful to correct the time of the events if needed. This number of seconds will be added to the event time /// before checking if it is within the time ranges. +/// * **startMarginTimeInSeconds**: margin time in seconds to be added to the start time of the time ranges +/// (default is 0). This is useful to consider the events that are close to the start time of the time ranges. +/// * **endMarginTimeInSeconds**: margin time in seconds to be subtracted from the end time of the time ranges +/// (default is 0). This is useful to consider the events that are close to the end time of the time ranges. +/// +/// ### Observables +/// The process does not produce event observables but it keeps track of the number of events selected and rejected +/// and the total time of the time ranges in the metadata members. /// /// ### Examples /// Examples for rml files: @@ -81,7 +89,7 @@ /// RESTsoft - Software for Rare Event Searches with TPCs /// /// History of developments: -/// 2024-Jun: Use of the processing file itself (no need for external fileWithIDs) +/// 2025-Jan - First version of the code /// Alvaro Ezquerro /// /// \class TRestEventTimeSelectionProcess From fc27a124730d645e53fbeda84c760d748110d24a Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Sun, 19 Jan 2025 14:47:22 +0000 Subject: [PATCH 16/17] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- .../src/TRestEventTimeSelectionProcess.cxx | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/source/framework/analysis/src/TRestEventTimeSelectionProcess.cxx b/source/framework/analysis/src/TRestEventTimeSelectionProcess.cxx index 58771e0bb..b5e4716eb 100644 --- a/source/framework/analysis/src/TRestEventTimeSelectionProcess.cxx +++ b/source/framework/analysis/src/TRestEventTimeSelectionProcess.cxx @@ -65,8 +65,8 @@ /// (default is 0). This is useful to consider the events that are close to the end time of the time ranges. /// /// ### Observables -/// The process does not produce event observables but it keeps track of the number of events selected and rejected -/// and the total time of the time ranges in the metadata members. +/// The process does not produce event observables but it keeps track of the number of events selected and +/// rejected and the total time of the time ranges in the metadata members. /// /// ### Examples /// Examples for rml files: @@ -170,7 +170,6 @@ std::vector> TRestEventTimeSelectionProcess: return startEndTimes; } - /////////////////////////////////////////////// /// \brief Function to calculate the total time in seconds of all the time ranges /// (active or dead periods of time). It takes into account the time offset, @@ -282,11 +281,11 @@ std::string TRestEventTimeSelectionProcess::GetTimeStampCut(std::string timeStam // Build the cut string if (!timeCut.empty()) { if (fIsActiveTime) - timeCut += " || "; // inside ANY time range + timeCut += " || "; // inside ANY time range else - timeCut += " && "; // outside ALL time ranges + timeCut += " && "; // outside ALL time ranges } - if (!fIsActiveTime) timeCut += "!"; // NOT inside the time range + if (!fIsActiveTime) timeCut += "!"; // NOT inside the time range // inside the time range timeCut += "("; timeCut += "(" + timeStampObsNameWithOffset + ">=" + to_string(startTime) + ")"; @@ -327,17 +326,16 @@ void TRestEventTimeSelectionProcess::PrintMetadata() { std::string fractionOfTimeStr = StringWithPrecision(fractionOfTime, 4) + " %"; if ((Int_t)(fTotalTimeInSeconds / 24 / 3600) != 0) // order of days RESTMetadata << "Total " << typeOfTime << " time: " << fTotalTimeInSeconds / 24 / 3600 << " days" - << " (" << fractionOfTimeStr << ")" << RESTendl; + << " (" << fractionOfTimeStr << ")" << RESTendl; else if ((Int_t)(fTotalTimeInSeconds / 3600) != 0) // order of hours RESTMetadata << "Total " << typeOfTime << " time: " << fTotalTimeInSeconds / 3600 << " hours" - << " (" << fractionOfTimeStr << ")" << RESTendl; + << " (" << fractionOfTimeStr << ")" << RESTendl; else if ((Int_t)(fTotalTimeInSeconds / 60) != 0) // order of minutes RESTMetadata << "Total " << typeOfTime << " time: " << fTotalTimeInSeconds / 60 << " minutes" - << " (" << fractionOfTimeStr << ")" << RESTendl; + << " (" << fractionOfTimeStr << ")" << RESTendl; else RESTMetadata << "Total " << typeOfTime << " time: " << fTotalTimeInSeconds << " seconds" - << " (" << fractionOfTimeStr << ")" << RESTendl; - + << " (" << fractionOfTimeStr << ")" << RESTendl; RESTMetadata << "Number of events rejected: " << fNEventsRejected << " (" << fNEventsRejected * 1. / (fNEventsRejected + fNEventsSelected) * 100 << " %)" << RESTendl; From 3d272b6b1bd566575b4cc24c4a02dbf65412744c Mon Sep 17 00:00:00 2001 From: Alvaro Ezquerro Date: Sun, 19 Jan 2025 19:21:17 +0100 Subject: [PATCH 17/17] improve the example in the doc --- .../src/TRestEventTimeSelectionProcess.cxx | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/source/framework/analysis/src/TRestEventTimeSelectionProcess.cxx b/source/framework/analysis/src/TRestEventTimeSelectionProcess.cxx index b5e4716eb..9a2db9f5d 100644 --- a/source/framework/analysis/src/TRestEventTimeSelectionProcess.cxx +++ b/source/framework/analysis/src/TRestEventTimeSelectionProcess.cxx @@ -66,13 +66,21 @@ /// /// ### Observables /// The process does not produce event observables but it keeps track of the number of events selected and -/// rejected and the total time of the time ranges in the metadata members. +/// rejected and the total time of the time ranges in the metadata members: +/// * **nEventsRejected**: number of events rejected. +/// * **nEventsSelected**: number of events selected. /// /// ### Examples /// Examples for rml files: /// \code -/// \endcode
+/// +/// +/// +/// +/// +/// +/// +/// \endcode
/// /// \warning ** REST is under continuous development.** This documentation /// is offered to you by the REST community. Your HELP is needed to keep this code