SendTriggerSignal_module.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 // Class: SendTriggerSignal
3 // Module Type: analyzer
4 // File: SendTriggerSignal_module.cc
5 //
6 // Generated at Mon Nov 19 15:08:59 2012 by Martin Frank using artmod
7 // from art v1_01_01.
8 ////////////////////////////////////////////////////////////////////////
9 
14 
17 
18 // directly from DDTSender:
19 #include <rms/provider/DDSConnection.h>
20 #include <rms/base/RmsDestination.h>
21 #include <rms/RmsSender.h>
22 
23 #include <DAQDataFormats/RawTriggerHeader.h>
24 #include <DAQDataFormats/RawTriggerTime.h>
25 #include <DAQDataFormats/RawTriggerTimingMarker.h>
26 #include <DAQDataFormats/RawTriggerRange.h>
27 #include <DAQDataFormats/RawTriggerMask.h>
28 #include <DAQDataFormats/RawTrigger.h>
29 
30 #include <NovaTimingUtilities/TimingUtilities.h>
31 
32 #include <DAQDataFormats/TriggerDefines.h>
33 #include <DAQMessages/ccpp_GTMessages.h>
34 #include <DAQMessages/ccpp_DDTMessages.h>
35 
36 // #include <NovaGlobalTrigger/GTConfig.h>
37 #include <NovaDAQUtilities/LocationUtils.h>
38 
39 #include <rms/provider/DDSConnection.h>
40 #include <rms/base/RmsDestination.h>
41 #include <rms/RmsSender.h>
42 
43 // Ganglia
44 #include "ganglia.h"
45 #include <NovaDAQMonitorClient/NdmcClient.h>
46 
47 using namespace gov::fnal::cd::rms;
48 
49 namespace novaddt {
50  class SendTriggerSignal;
51 }
52 
54 public:
55  explicit SendTriggerSignal(fhicl::ParameterSet const & p);
56  virtual ~SendTriggerSignal();
57 
58  virtual void analyze(art::Event const & e);
59  // Ganglia master pointer. Needs to be accessed from all over
60  nova::novadaqmonitorclient::NdmcClient _daqMonClient; // daq monitor client
61  void startHeartbeat(); // start ganglia partition heartbeat
62  void stopHeartbeat(); // stop ganglia partition heartbeat
63 
64  double convertTDCtoSeconds(uint64_t tdc);
65 
66 private:
67  uint32_t cast_to_32_bits(uint64_t const& x) const;
68 
69  // for trigger:
70  std::vector<std::string> trigger_labels_;
71 
72  // for messaging (RMS = Responsive Messaging System):
73  bool send_trigger_messages_, verbose_;
76  boost::shared_ptr<provider::DDSConnection> rms_connection_;
77  base::RmsDestination rms_destination_;
80 
81  // Ganglia metrics
84  std::map <std::string, int32_t> m_trigger_rates; // a map of trigger rate metrics
85  std::map <std::string, int32_t> m_trigger_lengths;// a map of trigger length metrics
86  std::map <std::string, int32_t> m_trigger_delays; // a map of trigger delay metrics
87  // Heartbeat for the monitor client
89 };
90 
92  EDAnalyzer(p),
93  trigger_labels_(p.get<std::vector<std::string>>("trigger_labels")),
94  send_trigger_messages_(p.get<bool>("send_trigger_messages", true)),
95  verbose_(p.get<bool>("verbose", false)),
96  rms_partition_(p.get<int>("rms_partition_number")),
97  rms_mailbox_(p.get<std::string>("rms_mailbox")),
98  rms_connection_(new provider::DDSConnection
99  ("GlobalTriggerTestApplication", rms_partition_)),
100  rms_destination_(rms_mailbox_,
101  base::RmsDestination::TRIGGER_CHANNEL),
102  rms_sender_(rms_connection_, rms_destination_),
103  make_ganglia_metrics_(p.get<bool>("make_ganglia_metrics", true))
104 {
105  std::cout << "\nUsing Partition: " << rms_partition_
106  << "\nUsing Mailbox: " << rms_mailbox_ << "\n" << std::endl;
107 
109  // set ganglia partition.
110  _daqMonClient.setPartition(rms_partition_);
111  _daqMonClient.setGroupName("DDT");
112  // starting ganglia heartbeat
113  startHeartbeat();
114 
115  OverallTriggerRate = _daqMonClient.createMetric<double>(
116  "Overall Trigger Rate", "Hz",
118  "Combined rate of all triggers");
119  } // end of make_ganglia_metrics
120 
121  std::cout << "\nSending Messages for the following trigger modules:"
122  << std::endl;
123  for (auto const & trig : trigger_labels_){
124  std::cout << "\t" << trig << std::endl;
126  // setup ganglia metrics
127  // This would be nice to do using the names from TriggerDefines.h,
128  // but at this stage all we have are the module name strings.
129  // The modules themselves have trigger masks hard coded into them, so they're
130  // impossible to access from here, only from the decisions they issue.
131  // As a stop gap we can use the module label
132  m_trigger_rates[trig] = _daqMonClient.createMetric<double>(
133  trig+" Trigger Rate", "Hz",
135  "rate of the "+trig+" trigger");
136 
137  m_trigger_lengths[trig] = _daqMonClient.createMetric<uint32_t>(
138  trig+" Trigger average length", "TDC",
140  "Average length of the "+trig+" trigger");
141 
142  m_trigger_delays[trig] = _daqMonClient.createMetric<double>(
143  trig+" Trigger average delay", "ms",
145  "Average delay of the "+trig+" trigger");
146  } // end of make_ganglia_metrics
147  } // end of loop on trigger_labels_
148 }
149 
151 {
152  try
153  {
154  rms_sender_.close();
155  rms_connection_->close();
156  } catch (...) {
157  std::cerr << "\nAn exception occured when closeing the DDS connections.\n"
158  << std::endl;
159  }
161  // stop ganglia heartbeat
162  stopHeartbeat();
163  } // end of make_ganglia_metrics
164 }
165 
167 {
168 
169  for (auto const& trigger_label : trigger_labels_)
170  {
171  art::Handle<std::vector<TriggerDecision>> trigger_decisions;
172  e.getByLabel(trigger_label, trigger_decisions);
173  if (trigger_decisions.failedToGet()){
174  if (verbose_) std::cout << "\tno trigger decision objects found for trigger module " << trigger_label << std::endl;
175  continue;
176  }
177  if (verbose_ && trigger_decisions->size() > 0)
178  std::cout << "\tsending " << trigger_decisions->size()
179  << " trigger messages for trigger module "
180  << trigger_label << std::endl;
181 
182  unsigned n_decision(0);
183  for (auto const& decision : *trigger_decisions)
184  {
185  if (verbose_)
186  std::cout << "\tTrigger Decision "
187  << "(N, T0, dT, Bit, Prescale, Extra_Info) = ("
188  << ++n_decision
189  << ", " << decision.start()
190  << ", " << decision.duration()
191  << ", " << decision.mask()
192  << ", " << decision.prescale()
193  << ", 0x" << std::hex << decision.extra_info() << std::dec
194  << ")" << std::endl;
195 
196  ddtmessages::DDTTriggerMessage msg;
197 
198  // get the current time and convert it to NOvA time:
199  // daqdataformats::RawTriggerTime triggerTime;
200  timeval now;
201  gettimeofday(&now,0);
202  uint64_t nova_now;
204 
205  msg.trigger_type = decision.mask();
206  msg.start_time = decision.start();
207  msg.enabled = true;
208  msg.decision_time = nova_now;
209 
210  // convert the 64 MHz TDC counts into 2 MHz (500 ns) time windows
211  // and round up by one:
212  msg.duration = cast_to_32_bits(decision.duration() / 32 + 1);
213 
214  msg.time_to_decision = cast_to_32_bits(nova_now - decision.start());
215 
216  msg.prescale = decision.prescale();
217 
218  msg.process_id = decision.extra_info();
219 
220  // the following values have to be obtained from the environment:
221  msg.detector_id = 49;
223 
227  // Send the trigger metrics to ganglia
228  _daqMonClient.setValue(OverallTriggerRate,double(1.));
229  _daqMonClient.setValue(m_trigger_rates[trigger_label],double(1.));
230  _daqMonClient.setValue(m_trigger_lengths[trigger_label],(uint32_t)decision.duration());
231  // convert the delay (which is in TDC) to ms
232  double time_to_decisions_ms = convertTDCtoSeconds(nova_now - msg.start_time)*1000.;
233  _daqMonClient.setValue(m_trigger_delays[trigger_label],time_to_decisions_ms);
234  } // end of make_ganglia_metrics
235  }
236  }
237 }
238 
239 uint32_t novaddt::SendTriggerSignal::cast_to_32_bits(uint64_t const& x) const
240 {
241  uint32_t result;
242  uint32_t down_caster = 0xFFFFFFFF;
243 
244  // Let's grab the lowe 32 bits of the 64-bit input:
245  result = x & down_caster;
246 
247  return result;
248 }
249 
251 {
252  std::string title ="";
253  std::string description="Activity on partition (1=active/0=inactive).";
255 }
256 
258 {
259  _daqMonClient.destroyMetric(_monIdPartitionHeartbeat); // silence heartbeat
261 }
262 
264 {
265  // TDC clock ticks at 64 MHz
266  double one_tdc = 1. / 64e6;
267  return double(TDC) * one_tdc;
268 }
269 
std::map< std::string, int32_t > m_trigger_lengths
double convertTDCtoSeconds(uint64_t tdc)
std::map< std::string, int32_t > m_trigger_rates
virtual void analyze(art::Event const &e)
SendTriggerSignal(fhicl::ParameterSet const &p)
const char * p
Definition: xmltok.h:285
OStream cerr
Definition: OStream.cxx:7
Definition: Ndmc.h:37
boost::shared_ptr< provider::DDSConnection > rms_connection_
DEFINE_ART_MODULE(TestTMapFile)
const XML_Char int const XML_Char int const XML_Char * base
Definition: expat.h:331
std::map< std::string, int32_t > m_trigger_delays
Definition: Ndmc.h:38
void sendMessage(M &message)
Definition: RmsSender.h:117
uint32_t cast_to_32_bits(uint64_t const &x) const
nova::novadaqmonitorclient::NdmcClient _daqMonClient
OStream cout
Definition: OStream.cxx:6
Classes that allow someone to send and receive messages utilizing the Responsive Messaging System...
Definition: RmsCloseable.h:10
bool getByLabel(std::string const &label, std::string const &productInstanceName, Handle< PROD > &result) const
Definition: DataViewImpl.h:344
RmsSender< provider::DDSConnection, ddtmessages::DDTTriggerMessage > rms_sender_
Definition: Ndmc.h:42
Float_t e
Definition: plot.C:35
std::vector< std::string > trigger_labels_
bool failedToGet() const
Definition: Handle.h:196
bool convertUnixTimeToNovaTime(struct timespec const &inputUnixTime, uint64_t &outputNovaTime)
enum BeamMode string