artdaq  v3_06_00
RandomDelayFilter_module.cc
1 // Class: RandomDelayFilter
3 // Module Type: filter
4 // File: RandomDelayFilter_module.cc
5 //
6 // Generated at Fri Mar 4 10:45:30 2016 by Eric Flumerfelt using artmod
7 // from cetpkgsupport v1_09_00.
9 
10 #define TRACE_NAME "RandomDelayFilter"
11 
12 #include "art/Framework/Core/EDFilter.h"
13 #include "art/Framework/Core/ModuleMacros.h"
14 #include "art/Framework/Principal/Event.h"
15 #include "art/Framework/Principal/Handle.h"
16 #include "art/Framework/Principal/Run.h"
17 #include "art/Framework/Principal/SubRun.h"
18 #include "canvas/Utilities/InputTag.h"
19 #include "fhiclcpp/ParameterSet.h"
20 
21 #include "artdaq/DAQdata/Globals.hh"
22 
23 #include <memory>
24 #include <random>
25 #include <chrono>
26 
27 namespace artdaq
28 {
29  class RandomDelayFilter;
30 }
31 
39 class artdaq::RandomDelayFilter : public art::EDFilter
40 {
41 public:
56  explicit RandomDelayFilter(fhicl::ParameterSet const& p);
57 
61  RandomDelayFilter(RandomDelayFilter const&) = delete;
62 
67 
73 
79 
89  bool filter(art::Event& e) override;
90 
91 private:
92  // Random Delay Parameters (min/max for uniform, mean/sigma for normal)
93  double min_ms_;
94  double max_ms_;
95  double mean_ms_;
96  double sigma_ms_;
97 
98  int pass_factor_;
99  double load_factor_;
100 
101  // Random Engine Setup
102  std::mt19937 engine_;
103  std::unique_ptr<std::uniform_real_distribution<double>> uniform_distn_;
104  std::unique_ptr<std::normal_distribution<double>> normal_distn_;
105  std::unique_ptr<std::exponential_distribution<double>> exponential_distn_;
106  std::unique_ptr<std::uniform_int_distribution<int>> pass_distn_;
107 
108  enum class DistType {
109  Fixed,
110  Uniform,
111  Normal,
112  Exponential
113  };
114  DistType distribution_type_;
115 };
116 
117 
118 artdaq::RandomDelayFilter::RandomDelayFilter(fhicl::ParameterSet const& p):
119  #if ART_HEX_VERSION >= 0x30200
120  art::EDFilter(p),
121  #endif
122  min_ms_(p.get<double>("minimum_delay_ms", 0))
123  , max_ms_(p.get<double>("maximum_delay_ms", 1000))
124  , mean_ms_(p.get<double>("mean_delay_ms", 500))
125  , sigma_ms_(p.get<double>("sigma_delay_ms", 100))
126  , pass_factor_(p.get<int>("pass_filter_percentage", 100))
127  , load_factor_(p.get<double>("cpu_load_ratio", 0.5))
128  , engine_(p.get<int64_t>("random_seed", time(0)))
129  , pass_distn_(new std::uniform_int_distribution<int>(0, 100))
130 {
131  // Set limits on parameters
132  if (pass_factor_ > 100) pass_factor_ = 100;
133  if (pass_factor_ < 0) pass_factor_ = 0;
134  if (load_factor_ < 0.0) load_factor_ = 0.0;
135  if (load_factor_ > 1.0) load_factor_ = 1.0;
136 
137  if (min_ms_ < 0) min_ms_ = 0;
138  if (min_ms_ > max_ms_) max_ms_ = min_ms_;
139  if (mean_ms_ < 0) mean_ms_ = 0;
140  if (sigma_ms_ < 0) sigma_ms_ = 0;
141 
142  auto type = p.get<std::string>("distribution_type", "Uniform");
143  assert(type.size() >= 1);
144  switch (type[0])
145  {
146  case 'n':
147  case 'N':
148  TLOG(TLVL_INFO) << "Generating delay times using Normal distribution with mean " << mean_ms_ << " ms, std. dev. " << sigma_ms_ << " ms, min " << min_ms_ << " ms and max " << max_ms_ << "ms.";
149  distribution_type_ = DistType::Normal;
150  if(mean_ms_ < min_ms_) {
151  TLOG(TLVL_WARNING) << "Mean is smaller than min, setting to min";
152  mean_ms_ = min_ms_;
153  }
154  mean_ms_ -= min_ms_; // When we sample the distribution, we offset by min_ms_
155  normal_distn_.reset(new std::normal_distribution<double>(mean_ms_, sigma_ms_));
156  break;
157  case 'e':
158  case 'E':
159  TLOG(TLVL_INFO) << "Generating delay times using Exponential distribution with mean " << mean_ms_ << " ms, min " << min_ms_ << " ms and max " << max_ms_ << " ms.";
160  distribution_type_ = DistType::Exponential;
161  if(mean_ms_ < min_ms_) {
162  TLOG(TLVL_WARNING) << "Mean is smaller than min, setting to min";
163  mean_ms_ = min_ms_;
164  }
165  mean_ms_ -= min_ms_; // When we sample the distribution, we offset by min_ms_
166  if (mean_ms_ == 0) mean_ms_ = 1;
167  exponential_distn_.reset(new std::exponential_distribution<double>(1/mean_ms_));
168  break;
169  case 'U':
170  case 'u':
171  TLOG(TLVL_INFO) << "Generating delay times using Uniform distribution with min " << min_ms_ << " ms and max " << max_ms_ << " ms.";
172  distribution_type_ = DistType::Uniform;
173  uniform_distn_.reset(new std::uniform_real_distribution<double>(min_ms_, max_ms_));
174  break;
175  case 'f':
176  case 'F':
177  default:
178  TLOG(TLVL_INFO) << "Delay time set to " << min_ms_ << " ms.";
179  distribution_type_ = DistType::Fixed;
180  break;
181  }
182 }
183 
185 {
186  double delay = min_ms_;
187  do {
188  switch (distribution_type_)
189  {
190  case DistType::Normal:
191  delay += (*normal_distn_)(engine_);
192  break;
193  case DistType::Exponential:
194  delay += (*exponential_distn_)(engine_);
195  break;
196  case DistType::Uniform:
197  delay = (*uniform_distn_)(engine_);
198  break;
199  case DistType::Fixed:
200  break;
201  }
202  } while(delay > max_ms_ && delay < min_ms_);
203  TLOG(TLVL_DEBUG) << "Simulating processing of event " << e.event() << " by delaying " << delay << "ms." ;
204 
205  usleep(1000 * (1 - load_factor_) * delay);
206 
207  auto i = 0;
208  auto now = std::chrono::steady_clock::now();
209  while (TimeUtils::GetElapsedTimeMilliseconds(now) < static_cast<size_t>(delay * load_factor_))
210  {
211  i = i + 1 % std::numeric_limits<int>::max();
212  }
213 
214  return (*pass_distn_)(engine_) < pass_factor_;
215 }
216 
217 DEFINE_ART_MODULE(artdaq::RandomDelayFilter)
RandomDelayFilter(fhicl::ParameterSet const &p)
RandomDelayFilter Constructor.
bool filter(art::Event &e) override
Filter is a required override of art::EDFilter, and is called for each event.
A filter which delays for a random amount of time, then drops a random fraction of events...
RandomDelayFilter & operator=(RandomDelayFilter const &)=delete
Copy Assignment operator is deleted.