PAASS
Software suite to Acquire and Analyze Data from Pixie16
filterer.cpp
Go to the documentation of this file.
1 #include <iostream>
2 
3 // PixieCore libraries
4 #include "ScanMain.hpp"
5 #include "PixieEvent.hpp"
6 
7 // Local files
8 #include "filterer.hpp"
9 
10 // Root files
11 #include "TApplication.h"
12 #include "TSystem.h"
13 #include "TCanvas.h"
14 #include "TGraph.h"
15 #include "TFile.h"
16 #include "TAxis.h"
17 
18 #define ADC_CLOCK_uSEC 4E-3 // us
19 #define ADC_TIME_STEP 4 // ns
20 #define SLEEP_WAIT 1E4 // When not in shared memory mode, length of time to wait between calls to gSystem->ProcessEvents (in us).
21 
22 void Filterer::Filter(float *trace_, const size_t &length_, float *filtered1, const unsigned int &risetime_, const unsigned int &flattop_){
23  float sum;
24  size_t a1, a2, a3, a4;
25 
26  for(size_t i = 0; i < 2*risetime_ + flattop_; i++){
27  filtered1[i] = 0;
28  }
29 
30  for(size_t i = 2*risetime_ + flattop_; i < length_; i++){
31  sum = 0.0;
32  a1 = i - (2*risetime_ + flattop_);
33  a2 = i - (risetime_ + flattop_);
34  a3 = i - risetime_;
35  a4 = i;
36  for(size_t j = a1; j <= a2; j++){
37  sum += -1*trace_[j];
38  }
39  for(size_t j = a3; j <= a4; j++){
40  sum += trace_[j];
41  }
42  filtered1[i] = sum/risetime_;
43  }
44 }
45 
46 Filterer::Filterer(int mod /*= 0*/, int chan/*=0*/) :
47  mod_(mod),
48  chan_(chan),
49  acqRun_(true),
50  singleCapture_(false),
51  threshLow_(0),
52  threshHigh_(-1),
53  delay_(2),
54  num_traces(0),
55  num_displayed(0)
56 {
57  time(&last_trace);
58 
59  trig_rise = 4;
60  trig_flat = 0;
61 
62  energy_rise = 10;
63  energy_flat = 10;
64 
65  // Variables for root graphics
66  rootapp = new TApplication("filterer", 0, NULL);
67  gSystem->Load("libTree");
68 
69  canvas = new TCanvas("filterer_canvas", "Filterer");
70  canvas->cd();
71 
72  graph = new TGraph();
73  f_fast = new TGraph();
74  f_slow = new TGraph();
75 
76  f_fast->SetLineColor(2);
77  f_slow->SetLineColor(3);
78 }
79 
81  canvas->Close();
82  delete canvas;
83  delete graph;
84  delete f_fast;
85  delete f_slow;
86 
87  // Call Unpacker::Close() to finish cleanup.
88  Close();
89 }
90 
91 void Filterer::ResetGraph(unsigned int size) {
92  if(size != x_vals.size()){
93  std::cout << message_head << "Changing trace length from " << x_vals.size()*ADC_TIME_STEP << " to " << size*ADC_TIME_STEP << " ns.\n";
94  delete fast_filter_y;
95  delete slow_filter_y;
96  fast_filter_y = new float[size];
97  slow_filter_y = new float[size];
98  x_vals.resize(size);
99  for(size_t index = 0; index < x_vals.size(); index++){
100  fast_filter_y[index] = 0.0;
101  slow_filter_y[index] = 0.0;
102  x_vals[index] = ADC_TIME_STEP * index;
103  }
104  while ((unsigned int) graph->GetN() > size) graph->RemovePoint(graph->GetN());
105  }
106 
107  std::stringstream stream;
108  stream << "M" << mod_ << "C" << chan_;
109  graph->SetTitle(stream.str().c_str());
110 
111  resetGraph_ = false;
112 }
113 
115 
117  static float axisMin, axisMax;
118 
119  // Draw the trace
120 
121  if(event_->size != x_vals.size()){ // The length of the trace has changed.
122  resetGraph_ = true;
123  }
124  if (resetGraph_) {
125  ResetGraph(event_->size);
126  axisMax = 0;
127  axisMin = 1E9;
128  }
129 
130  // Run the fast filter (trigger) on the trace.
131  Filter(event_->yvals, event_->size, fast_filter_y, trig_rise, trig_flat);
132 
133  // Run the slow filter (energy) on the trace.
134  Filter(event_->yvals, event_->size, slow_filter_y, energy_rise, energy_flat);
135 
136  for (size_t i = 0; i < event_->size ; i++) {
137  graph->SetPoint(i, x_vals[i], event_->yvals[i]);
138  f_fast->SetPoint(i, x_vals[i], fast_filter_y[i]);
139  f_slow->SetPoint(i, x_vals[i], slow_filter_y[i]);
140  }
141 
142  if (graph->GetYaxis()->GetXmax() > axisMax) axisMax = graph->GetYaxis()->GetXmax();
143  if (graph->GetYaxis()->GetXmin() < axisMin) axisMin = graph->GetYaxis()->GetXmin();
144 
145  if (f_fast->GetYaxis()->GetXmax() > axisMax) axisMax = f_fast->GetYaxis()->GetXmax();
146  if (f_fast->GetYaxis()->GetXmin() < axisMin) axisMin = f_fast->GetYaxis()->GetXmin();
147 
148  if (f_slow->GetYaxis()->GetXmax() > axisMax) axisMax = f_slow->GetYaxis()->GetXmax();
149  if (f_slow->GetYaxis()->GetXmin() < axisMin) axisMin = f_slow->GetYaxis()->GetXmin();
150 
151  graph->GetYaxis()->SetLimits(axisMin, axisMax);
152  graph->GetYaxis()->SetRangeUser(axisMin, axisMax);
153 
154  graph->Draw("APL");
155  f_fast->Draw("LSAME");
156  f_slow->Draw("LSAME");
157 
158  canvas->Update();
159 
160  num_displayed++;
161 
162  num_traces++;
163 }
164 
166  PixieEvent *current_event = NULL;
167 
168  // Fill the processor event deques with events
169  while(!rawEvent.empty()){
170  if(kill_all){ break; }
171  //If the acquistion is not running we clear the events.
172  // For the SHM mode we simply break and wait for the next data packet.
173  // For the ldf mode we sleep and check acqRun again.
174  while(!acqRun_) {
175  //Clean up any stored waveforms.
176  if(shm_mode || kill_all){ return; }
177  usleep(SLEEP_WAIT);
178  gSystem->ProcessEvents();
179  }
180 
181  //Get the first event int he FIFO.
182  current_event = rawEvent.front();
183  rawEvent.pop_front();
184 
185  // Safety catches for null event or empty adcTrace.
186  if(!current_event || current_event->adcTrace.empty()){
187  continue;
188  }
189 
190  // Pass this event to the correct processor
191  if(current_event->modNum == mod_ && current_event->chanNum == chan_){
192  ChannelEvent *channel_event = new ChannelEvent(current_event);
193 
194  channel_event->CorrectBaseline();
195  if (channel_event->maximum < threshLow_) {
196  delete channel_event;
197  continue;
198  }
199  //Check threhsold.
200  if (threshHigh_ > threshLow_ && channel_event->maximum > threshHigh_) {
201  delete channel_event;
202  continue;
203  }
204 
205  //Process the waveform.
206  channel_event->FindLeadingEdge();
207  channel_event->FindQDC();
208 
209  time_t cur_time;
210  time(&cur_time);
211  while(difftime(cur_time, last_trace) < delay_) {
212  usleep(SLEEP_WAIT);
213  gSystem->ProcessEvents();
214  time(&cur_time);
215  }
216 
217  Plot(channel_event);
218 
219  //If this is a single capture we stop the plotting.
220  if (singleCapture_) acqRun_ = false;
221 
222  time(&last_trace);
223  }
224  gSystem->ProcessEvents();
225  }
226 }
227 
228 bool Filterer::Initialize(std::string prefix_){
229  if(init){ return false; }
230 
231  // Print a small welcome message.
232  std::cout << prefix_ << "Displaying traces for mod = " << mod_ << ", chan = " << chan_ << ".\n";
233 
234  return (init = true);
235 }
236 
240 void Filterer::ArgHelp(std::string prefix_){
241  std::cout << prefix_ << "--mod [module] | Module of signal of interest (default=0)\n";
242  std::cout << prefix_ << "--chan [channel] | Channel of signal of interest (default=0)\n";
243 }
244 
249 void Filterer::CmdHelp(std::string prefix_){
250  std::cout << prefix_ << "set [mod] [chan] - Set the module and channel of signal of interest (default = 0, 0).\n";
251  std::cout << prefix_ << "single - Perform a single capture.\n";
252  std::cout << prefix_ << "thresh [low] <high> - Set the plotting window for trace maximum.\n";
253  std::cout << prefix_ << "delay [time] - Set the delay between drawing traces (in seconds, default = 1 s).\n";
254  std::cout << prefix_ << "log - Toggle log/linear mode on the y-axis.\n";
255  std::cout << prefix_ << "trise [risetime] - Set the length of the fast filter (in μs).\n";
256  std::cout << prefix_ << "tflat [flattop] - Set the gap of the fast filter (in μs).\n";
257  std::cout << prefix_ << "erise [risetime] - Set the length of the slow filter (in μs).\n";
258  std::cout << prefix_ << "eflat [flattop] - Set the gap of the slow filter (in μs).\n";
259 }
260 
265 bool Filterer::SetArgs(std::deque<std::string> &args_, std::string &filename_){
266  std::string current_arg;
267  while(!args_.empty()){
268  current_arg = args_.front();
269  args_.pop_front();
270 
271  if(current_arg == "--mod"){
272  if(args_.empty()){
273  std::cout << " Error: Missing required argument to option '--mod'!\n";
274  return false;
275  }
276  mod_ = atoi(args_.front().c_str());
277  args_.pop_front();
278  }
279  else if(current_arg == "--chan"){
280  if(args_.empty()){
281  std::cout << " Error: Missing required argument to option '--chan'!\n";
282  return false;
283  }
284  chan_ = atoi(args_.front().c_str());
285  args_.pop_front();
286  }
287  else{ filename_ = current_arg; }
288  }
289 
290  return true;
291 }
292 
293 bool Filterer::CommandControl(std::string cmd_, const std::vector<std::string> &args_){
294  if(cmd_ == "set"){ // Toggle debug mode
295  if(args_.size() == 2){
296  //Set the module and channel.
297  mod_ = atoi(args_.at(0).c_str());
298  chan_ = atoi(args_.at(1).c_str());
299 
300  //Store previous run status.
301  bool runStatus = acqRun_;
302  //Stop the run to force the buffer to be cleared.
303  acqRun_ = false;
304  //Resotre the previous run status.
305  acqRun_ = runStatus;
306 
307  resetGraph_ = true;
308  }
309  else{
310  std::cout << message_head << "Invalid number of parameters to 'set'\n";
311  std::cout << message_head << " -SYNTAX- set [module] [channel]\n";
312  }
313  }
314  else if(cmd_ == "single") {
316  }
317  else if (cmd_ == "thresh") {
318  if (args_.size() == 1) {
319  threshLow_ = atoi(args_.at(0).c_str());
320  threshHigh_ = -1;
321  }
322  else if (args_.size() == 2) {
323  threshLow_ = atoi(args_.at(0).c_str());
324  threshHigh_ = atoi(args_.at(1).c_str());
325  }
326  else {
327  std::cout << message_head << "Invalid number of parameters to 'thresh'\n";
328  std::cout << message_head << " -SYNTAX- thresh <lowerThresh> [upperThresh]\n";
329  }
330  }
331  else if(cmd_ == "delay"){
332  if(args_.size() == 1){ delay_ = atoi(args_.at(0).c_str()); }
333  else{
334  std::cout << message_head << "Invalid number of parameters to 'delay'\n";
335  std::cout << message_head << " -SYNTAX- delay [time]\n";
336  }
337  }
338  else if(cmd_ == "log"){
339  if(canvas->GetLogy()){
340  canvas->SetLogy(0);
341  std::cout << message_head << "y-axis set to linear.\n";
342  }
343  else{
344  canvas->SetLogy(1);
345  std::cout << message_head << "y-axis set to log.\n";
346  }
347  }
348  else if(cmd_ == "trise"){ // Set the TRIGGER_RISETIME.
349  if(args_.size() == 1){
350  float temp = atof(args_.at(0).c_str());
351  trig_rise = (int)(temp/ADC_CLOCK_uSEC);
352  std::cout << message_head << "Set TRIGGER_RISETIME to " << trig_rise << " ADC ticks (" << trig_rise*ADC_CLOCK_uSEC << " μs).\n";
353  }
354  else{ std::cout << message_head << "TRIGGER_RISETIME = " << trig_rise*ADC_CLOCK_uSEC << " μs.\n"; }
355  }
356  else if(cmd_ == "tflat"){ // Set the TRIGGER_FLATTOP.
357  if(args_.size() == 1){
358  float temp = atof(args_.at(0).c_str());
359  trig_flat = (int)(temp/ADC_CLOCK_uSEC);
360  std::cout << message_head << "Set TRIGGER_FLATTOP to " << trig_flat << " ADC ticks (" << trig_flat*ADC_CLOCK_uSEC << " μs).\n";
361  }
362  else{ std::cout << message_head << "TRIGGER_FLATTOP = " << trig_flat*ADC_CLOCK_uSEC << " μs.\n"; }
363  }
364  else if(cmd_ == "erise"){ // Set the ENERGY_RISETIME.
365  if(args_.size() == 1){
366  float temp = atof(args_.at(0).c_str());
367  energy_rise = (int)(temp/ADC_CLOCK_uSEC);
368  std::cout << message_head << "Set ENERGY_RISETIME to " << energy_rise << " ADC ticks (" << energy_rise*ADC_CLOCK_uSEC << " μs).\n";
369  }
370  else{ std::cout << message_head << "ENERGY_RISETIME = " << energy_rise*ADC_CLOCK_uSEC << " μs.\n"; }
371  }
372  else if(cmd_ == "eflat"){ // Set the ENERGY_FLATTOP.
373  if(args_.size() == 1){
374  float temp = atof(args_.at(0).c_str());
375  energy_flat = (int)(temp/ADC_CLOCK_uSEC);
376  std::cout << message_head << "Set ENERGY_FLATTOP to " << energy_flat << " ADC ticks (" << energy_flat*ADC_CLOCK_uSEC << " μs).\n";
377  }
378  else{ std::cout << message_head << "ENERGY_FLATTOP = " << energy_flat*ADC_CLOCK_uSEC << " μs.\n"; }
379  }
380  else{ return false; }
381 
382  return true;
383 }
384 
387  acqRun_ = false;
388 }
389 
392  acqRun_ = true;
393 }
394 
396  gSystem->ProcessEvents();
397 }
398 
399 int main(int argc, char *argv[]){
400  ScanMain scan_main((Unpacker*)(new Filterer()));
401 
402  scan_main.Initialize(argc, argv);
403 
404  scan_main.SetMessageHeader("Filterer: ");
405 
406  return scan_main.Execute();
407 }
bool Initialize(std::string prefix_="")
Definition: filterer.cpp:228
int threshHigh_
Definition: filterer.hpp:22
#define ADC_TIME_STEP
Definition: filterer.cpp:19
~Filterer()
Definition: filterer.cpp:80
TCanvas * canvas
The main plotting canvas.
Definition: filterer.hpp:48
void Plot(ChannelEvent *event_)
Plot the current event.
Definition: filterer.cpp:114
#define ADC_CLOCK_uSEC
Definition: filterer.cpp:18
bool SetArgs(std::deque< std::string > &args_, std::string &filename_)
Scan input arguments and set class variables.
Definition: filterer.cpp:265
void ProcessRawEvent()
Process all events in the event list.
Definition: filterer.cpp:165
float CorrectBaseline()
void Filter(float *trace_, const size_t &length_, float *filtered1, const unsigned int &risetime_, const unsigned int &flattop_)
Definition: filterer.cpp:22
float * yvals
x values used for fitting.
void StartAcquisition()
Scan has started data acquisition.
Definition: filterer.cpp:391
bool acqRun_
Definition: filterer.hpp:19
bool CommandControl(std::string cmd_, const std::vector< std::string > &args_)
Definition: filterer.cpp:293
void ResetGraph(unsigned int size_)
Definition: filterer.cpp:91
void ArgHelp(std::string prefix_="")
Print a command line help dialogue for recognized command line arguments.
Definition: filterer.cpp:240
std::deque< XiaData * > rawEvent
The list of all events in a spill.
Definition: Unpacker.hpp:118
unsigned int num_traces
The total number of traces.
Definition: filterer.hpp:42
TApplication * rootapp
Root application pointer.
Definition: filterer.hpp:46
unsigned int energy_flat
Set the slow filter risetime. Analogous to setting ENERGY_RISETIME.
Definition: filterer.hpp:27
virtual void IdleTask()
Perform tasks when waiting for a spill.
Definition: filterer.cpp:395
std::vector< int > x_vals
The number of seconds to wait between drawing traces.
Definition: filterer.hpp:36
int threshLow_
Definition: filterer.hpp:21
int chan_
The channel of the signal of interest.
Definition: filterer.hpp:18
Filterer(int mod=0, int chan=0)
Definition: filterer.cpp:46
float maximum
Standard deviation of the baseline.
bool resetGraph_
Definition: filterer.hpp:38
float FindQDC(const size_t &start_=0, const size_t &stop_=0)
Integrate the baseline corrected trace in the range [start_, stop_] and return the result...
TGraph * graph
The TGraph for plotting traces.
Definition: filterer.hpp:50
TGraph * f_fast
The TGraph for plotting the fast filter.
Definition: filterer.hpp:51
TGraph * f_slow
The TGraph for plotting the slow filter.
Definition: filterer.hpp:52
void CmdHelp(std::string prefix_="")
Print an in-terminal help dialogue for recognized commands.
Definition: filterer.cpp:249
size_t size
y values for the cfd analyzed waveform.
bool singleCapture_
Definition: filterer.hpp:20
unsigned int num_displayed
The number of displayed traces.
Definition: filterer.hpp:44
void StopAcquisition()
Scan has stopped data acquisition.
Definition: filterer.cpp:386
time_t last_trace
The time of the last trace.
Definition: filterer.hpp:40
float * slow_filter_y
Definition: filterer.hpp:30
unsigned int trig_flat
Set the fast filter length. Analogous to setting TRIGGER_RISETIME.
Definition: filterer.hpp:25
#define SLEEP_WAIT
Definition: filterer.cpp:20
int mod_
The module of the signal of interest.
Definition: filterer.hpp:17
int main(int argc, char *argv[])
Definition: filterer.cpp:399
unsigned int energy_rise
Set the fast filter gap. Analogous to setting TRIGGER_FLATTOP.
Definition: filterer.hpp:26
float * fast_filter_y
Set the slow filter gap. Analogous to setting ENERGY_FLATTOP.
Definition: filterer.hpp:29
unsigned int trig_rise
Definition: filterer.hpp:24
float FindLeadingEdge(const float &thresh_=0.05)
Find the leading edge of the pulse at a given percentage of pulse maximum.
int delay_
Set to true if the graph range needs updated.
Definition: filterer.hpp:34