Skip to content

Commit 1ac9da6

Browse files
Improve TRestEventTimeSelectionProcess (#559)
* use Interval instead of pair of strings * sort fStartEndTimes * use positive time margins for both active and dead times * add functionality to use the run start and end times * fix applying of start and end run time * set fUseRunStartAndEndTimes to true by default and add documentation * improve documentation --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent 3fc82d2 commit 1ac9da6

File tree

2 files changed

+132
-34
lines changed

2 files changed

+132
-34
lines changed

source/framework/analysis/inc/TRestEventTimeSelectionProcess.h

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@
2727

2828
#include <iostream>
2929

30+
using Interval = std::pair<TTimeStamp, TTimeStamp>;
31+
3032
class TRestEventTimeSelectionProcess : public TRestEventProcess {
3133
private:
3234
TRestEvent* fEvent; //!
@@ -36,7 +38,8 @@ class TRestEventTimeSelectionProcess : public TRestEventProcess {
3638
Long_t fTimeOffsetInSeconds;
3739
Long_t fTimeStartMarginInSeconds;
3840
Long_t fTimeEndMarginInSeconds;
39-
std::vector<std::pair<std::string, std::string>> fStartEndTimes;
41+
std::vector<Interval> fStartEndTimes;
42+
Bool_t fUseRunStartAndEndTimes;
4043

4144
/// Information about the events processed
4245

@@ -69,7 +72,7 @@ class TRestEventTimeSelectionProcess : public TRestEventProcess {
6972
Bool_t GetIsActiveTime() const { return fIsActiveTime; }
7073
Char_t GetDelimiter() const { return fDelimiter; }
7174

72-
std::vector<std::pair<std::string, std::string>> GetStartEndTimes() const { return fStartEndTimes; }
75+
std::vector<Interval> GetStartEndTimes() const { return fStartEndTimes; }
7376
std::string GetTimeStampCut(std::string timeStampObsName = "timeStamp", Bool_t useOffset = true,
7477
Bool_t useMargins = true, Int_t nTimes = -1);
7578
Int_t GetNEventsRejected() const { return fNEventsRejected; }
@@ -80,17 +83,16 @@ class TRestEventTimeSelectionProcess : public TRestEventProcess {
8083
Long_t GetTimeEndMarginInSeconds() const { return fTimeEndMarginInSeconds; }
8184

8285
Double_t CalculateTotalTimeInSeconds();
83-
static std::vector<std::pair<std::string, std::string>> ReadFileWithTimes(std::string fileWithTimes,
84-
Char_t delimiter = ',');
86+
static std::vector<Interval> ReadFileWithTimes(std::string fileWithTimes, Char_t delimiter = ',');
87+
void ApplyStartRunTime(const TTimeStamp& runStartTime);
88+
void ApplyEndRunTime(const TTimeStamp& runEndTime);
8589

8690
void SetAsActiveTime() { fIsActiveTime = true; }
8791
void SetAsDeadTime() { fIsActiveTime = false; }
8892
void SetFileWithTimes(const std::string& fileWithTimes) { fFileWithTimes = fileWithTimes; }
8993
void SetIsActiveTime(Bool_t isActiveTime) { fIsActiveTime = isActiveTime; }
9094
void SetDelimiter(Char_t delimiter) { fDelimiter = delimiter; }
91-
void SetStartEndTimes(const std::vector<std::pair<std::string, std::string>>& startEndTimes) {
92-
fStartEndTimes = startEndTimes;
93-
}
95+
void SetStartEndTimes(const std::vector<Interval>& startEndTimes) { fStartEndTimes = startEndTimes; }
9496
void SetTimeOffsetInSeconds(Long_t timeOffsetInSeconds) { fTimeOffsetInSeconds = timeOffsetInSeconds; }
9597
void SetTimeStartMarginInSeconds(Long_t timeStartMarginInSeconds) {
9698
fTimeStartMarginInSeconds = timeStartMarginInSeconds;
@@ -99,6 +101,6 @@ class TRestEventTimeSelectionProcess : public TRestEventProcess {
99101
fTimeEndMarginInSeconds = timeEndMarginInSeconds;
100102
}
101103

102-
ClassDefOverride(TRestEventTimeSelectionProcess, 1);
104+
ClassDefOverride(TRestEventTimeSelectionProcess, 2);
103105
};
104106
#endif

source/framework/analysis/src/TRestEventTimeSelectionProcess.cxx

Lines changed: 122 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,15 @@
6161
/// before checking if it is within the time ranges.
6262
/// * **startMarginTimeInSeconds**: margin time in seconds to be added to the start time of the time ranges
6363
/// (default is 0). This is useful to consider the events that are close to the start time of the time ranges.
64+
/// Meant to be a positive number, as the process will take care of adding or subtracting it if the time
65+
/// ranges represent active or dead periods of time respectively.
6466
/// * **endMarginTimeInSeconds**: margin time in seconds to be subtracted from the end time of the time ranges
6567
/// (default is 0). This is useful to consider the events that are close to the end time of the time ranges.
68+
/// Meant to be a positive number, as the process will take care of subtracting or adding it if the time
69+
/// ranges represent active or dead periods of time respectively.
70+
///* **useRunStartAndEndTimes**: if `true` (default) the start and end times of the TRestRun
71+
/// will be used to restrict the time ranges to those involved (those that are between the run start and end
72+
/// times).
6673
///
6774
/// ### Observables
6875
/// The process does not produce event observables but it keeps track of the number of events selected and
@@ -131,6 +138,7 @@ void TRestEventTimeSelectionProcess::Initialize() {
131138
fTimeOffsetInSeconds = 0;
132139
fTimeStartMarginInSeconds = 0;
133140
fTimeEndMarginInSeconds = 0;
141+
fUseRunStartAndEndTimes = true;
134142
fNEventsRejected = 0;
135143
fNEventsSelected = 0;
136144
fTotalTimeInSeconds = 0;
@@ -145,14 +153,25 @@ void TRestEventTimeSelectionProcess::InitProcess() {
145153
if (!fFileWithTimes.empty()) {
146154
fStartEndTimes = ReadFileWithTimes(fFileWithTimes, fDelimiter);
147155
}
156+
if (fUseRunStartAndEndTimes) {
157+
TRestRun* run = GetRunInfo();
158+
if (run) {
159+
auto startTimeStamp = run->GetStartTimestamp();
160+
auto endTimeStamp = run->GetEndTimestamp();
161+
ApplyStartRunTime(startTimeStamp);
162+
ApplyEndRunTime(endTimeStamp);
163+
} else {
164+
RESTWarning << "No run information available to get TRestRun start and end times." << RESTendl;
165+
}
166+
}
148167
fTotalTimeInSeconds = CalculateTotalTimeInSeconds();
149168
fNEventsRejected = 0;
150169
fNEventsSelected = 0;
151170
}
152171

153-
std::vector<std::pair<std::string, std::string>> TRestEventTimeSelectionProcess::ReadFileWithTimes(
154-
std::string fileWithTimes, Char_t delimiter) {
155-
std::vector<std::pair<std::string, std::string>> startEndTimes;
172+
std::vector<Interval> TRestEventTimeSelectionProcess::ReadFileWithTimes(std::string fileWithTimes,
173+
Char_t delimiter) {
174+
std::vector<Interval> startEndTimes;
156175
string line;
157176
ifstream file(fileWithTimes);
158177
if (file.is_open()) {
@@ -169,12 +188,17 @@ std::vector<std::pair<std::string, std::string>> TRestEventTimeSelectionProcess:
169188
if (StringToTimeStamp(startDate) < 0 || StringToTimeStamp(endDate) < 0) {
170189
continue;
171190
}
172-
173-
startEndTimes.emplace_back(startDate, endDate);
191+
TTimeStamp sts = StringToTimeStamp(startDate);
192+
TTimeStamp ets = StringToTimeStamp(endDate);
193+
startEndTimes.emplace_back(sts, ets);
174194
}
175195
}
176196
file.close();
177197
}
198+
199+
// sort by start time and then by end time (lexicographically)
200+
std::sort(startEndTimes.begin(), startEndTimes.end());
201+
178202
return startEndTimes;
179203
}
180204

@@ -185,15 +209,15 @@ std::vector<std::pair<std::string, std::string>> TRestEventTimeSelectionProcess:
185209
///
186210
Double_t TRestEventTimeSelectionProcess::CalculateTotalTimeInSeconds() {
187211
Double_t totalTime = 0;
188-
for (auto id : fStartEndTimes) {
189-
TTimeStamp startTime = TTimeStamp(StringToTimeStamp(id.first), 0);
190-
TTimeStamp endTime = TTimeStamp(StringToTimeStamp(id.second), 0);
212+
for (auto se : fStartEndTimes) {
213+
TTimeStamp startTime = se.first;
214+
TTimeStamp endTime = se.second;
191215
// Reduce the time by the margin in both sides
192216
startTime.Add(TTimeStamp(fTimeStartMarginInSeconds));
193217
endTime.Add(TTimeStamp(-fTimeEndMarginInSeconds));
194218
auto timeDiff = endTime.AsDouble() - startTime.AsDouble();
195219
if (timeDiff < 0) {
196-
RESTDebug << "End time is before start time in time range: " << id.first << " to " << id.second
220+
RESTDebug << "End time is before start time in time range: " << se.first << " to " << se.second
197221
<< RESTendl;
198222
continue;
199223
}
@@ -212,12 +236,19 @@ TRestEvent* TRestEventTimeSelectionProcess::ProcessEvent(TRestEvent* inputEvent)
212236
eventTime.Add(TTimeStamp(fTimeOffsetInSeconds));
213237

214238
Bool_t isInsideAnyTimeRange = false;
215-
for (auto id : fStartEndTimes) {
216-
TTimeStamp startTime = TTimeStamp(StringToTimeStamp(id.first), 0);
217-
TTimeStamp endTime = TTimeStamp(StringToTimeStamp(id.second), 0);
218-
// Reduce the time by the margin in both sides
219-
startTime.Add(TTimeStamp(fTimeStartMarginInSeconds));
220-
endTime.Add(TTimeStamp(-fTimeEndMarginInSeconds));
239+
for (auto se : fStartEndTimes) {
240+
TTimeStamp startTime = se.first;
241+
TTimeStamp endTime = se.second;
242+
if (fIsActiveTime) {
243+
// Reduce the active time window by the margin in both sides
244+
startTime.Add(TTimeStamp(fTimeStartMarginInSeconds));
245+
endTime.Add(TTimeStamp(-fTimeEndMarginInSeconds));
246+
} else {
247+
// Increase the dead time window by the margin in both sides
248+
startTime.Add(TTimeStamp(-fTimeStartMarginInSeconds));
249+
endTime.Add(TTimeStamp(fTimeEndMarginInSeconds));
250+
}
251+
221252
if (eventTime >= startTime && eventTime <= endTime) {
222253
isInsideAnyTimeRange = true;
223254
break;
@@ -251,6 +282,63 @@ void TRestEventTimeSelectionProcess::EndProcess() {
251282
// Write here the jobs to do when all the events are processed
252283
}
253284

285+
void TRestEventTimeSelectionProcess::ApplyStartRunTime(const TTimeStamp& runStart) {
286+
size_t startIndex = 0;
287+
bool isInsideTimeRange = false;
288+
for (auto se : fStartEndTimes) {
289+
TTimeStamp s = se.first;
290+
TTimeStamp e = se.second;
291+
292+
if (runStart < s) {
293+
isInsideTimeRange = false;
294+
break;
295+
}
296+
297+
if (runStart >= s && runStart <= e) {
298+
isInsideTimeRange = true;
299+
break;
300+
}
301+
302+
startIndex++;
303+
}
304+
305+
if (isInsideTimeRange) {
306+
// modify the start time of the found interval
307+
fStartEndTimes[startIndex].first = runStart;
308+
}
309+
// remove all intervals before the run start time
310+
fStartEndTimes.erase(fStartEndTimes.begin(), fStartEndTimes.begin() + startIndex);
311+
}
312+
313+
void TRestEventTimeSelectionProcess::ApplyEndRunTime(const TTimeStamp& runEnd) {
314+
size_t endIndex = 0;
315+
bool isInsideTimeRange = false;
316+
for (auto se : fStartEndTimes) {
317+
TTimeStamp s = se.first;
318+
TTimeStamp e = se.second;
319+
320+
if (runEnd < s) {
321+
isInsideTimeRange = false;
322+
break;
323+
}
324+
325+
if (runEnd >= s && runEnd <= e) {
326+
isInsideTimeRange = true;
327+
break;
328+
}
329+
330+
endIndex++;
331+
}
332+
333+
if (isInsideTimeRange) {
334+
// modify the end time of the found interval
335+
fStartEndTimes[endIndex].second = runEnd;
336+
endIndex++; // to erase from the next interval
337+
}
338+
// remove all intervals after the run end time
339+
fStartEndTimes.erase(fStartEndTimes.begin() + endIndex, fStartEndTimes.end());
340+
}
341+
254342
///////////////////////////////////////////////
255343
/// \brief Function to get the cut string that reproduce the time selection
256344
/// done by this process (useful for TRestDataSet::MakeCut() for example).
@@ -272,14 +360,21 @@ std::string TRestEventTimeSelectionProcess::GetTimeStampCut(std::string timeStam
272360
}
273361
if (nTimes < 0) nTimes = fStartEndTimes.size();
274362
Int_t c = 0;
275-
for (auto id : fStartEndTimes) {
363+
for (auto se : fStartEndTimes) {
276364
if (c++ >= nTimes) break;
277-
auto startTime = StringToTimeStamp(id.first);
278-
auto endTime = StringToTimeStamp(id.second);
365+
auto startTime = se.first;
366+
auto endTime = se.second;
279367
// Reduce the time by the margin in both sides
280368
if (useMargins) {
281-
startTime += fTimeStartMarginInSeconds;
282-
endTime -= fTimeEndMarginInSeconds;
369+
if (fIsActiveTime) {
370+
// Reduce the active time window by the margin in both sides
371+
startTime.Add(fTimeStartMarginInSeconds);
372+
endTime.Add(-fTimeEndMarginInSeconds);
373+
} else {
374+
// Increase the dead time window by the margin in both sides
375+
startTime.Add(-fTimeStartMarginInSeconds);
376+
endTime.Add(fTimeEndMarginInSeconds);
377+
}
283378
}
284379

285380
if (startTime >= endTime) {
@@ -312,21 +407,22 @@ void TRestEventTimeSelectionProcess::PrintMetadata() {
312407

313408
RESTMetadata << "File with times: " << fFileWithTimes << RESTendl;
314409
// print periods
410+
RESTMetadata << "Use run start and end: " << (fUseRunStartAndEndTimes ? "true" : "false") << RESTendl;
315411
RESTMetadata << "Offset time: " << fTimeOffsetInSeconds << " seconds" << RESTendl;
316412
RESTMetadata << "Start margin time: " << fTimeStartMarginInSeconds << " seconds" << RESTendl;
317413
RESTMetadata << "End margin time: " << fTimeEndMarginInSeconds << " seconds" << RESTendl;
318414
RESTMetadata << typeOfTime << " time periods: " << RESTendl;
319-
for (auto id : fStartEndTimes) {
320-
RESTMetadata << id.first << " to " << id.second << RESTendl;
321-
TTimeStamp startTime = TTimeStamp(StringToTimeStamp(id.first), 0);
322-
TTimeStamp endTime = TTimeStamp(StringToTimeStamp(id.second), 0);
415+
for (auto se : fStartEndTimes) {
416+
std::string startStr = ToDateTimeString(se.first);
417+
std::string endStr = ToDateTimeString(se.second);
418+
RESTMetadata << startStr << " to " << endStr << RESTendl;
323419
}
324420

325421
// Get total time in seconds
326422
TTimeStamp totalTime = TTimeStamp(fTotalTimeInSeconds, 0);
327423
if (!fStartEndTimes.empty()) {
328-
TTimeStamp firstTime = TTimeStamp(StringToTimeStamp(fStartEndTimes.front().first), 0);
329-
TTimeStamp lastTime = TTimeStamp(StringToTimeStamp(fStartEndTimes.back().second), 0);
424+
TTimeStamp firstTime = fStartEndTimes.front().first;
425+
TTimeStamp lastTime = fStartEndTimes.back().second;
330426
totalTime = lastTime - firstTime;
331427
}
332428

0 commit comments

Comments
 (0)