Analysis Software
Documentation for sPHENIX simulation software
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
TpotMon.cc
Go to the documentation of this file. Or view the newest version in sPHENIX GitHub for file TpotMon.cc
1 #include "TpotMon.h"
2 #include "TpotMonDefs.h"
3 
4 #include <onlmon/OnlMon.h> // for OnlMon
5 #include <onlmon/OnlMonServer.h>
6 
7 #include <Event/msg_profile.h>
8 #include <Event/Event.h>
9 
10 #include <TH1.h>
11 #include <TH2.h>
12 #include <TH2Poly.h>
13 
14 #include <cmath>
15 #include <cstdio> // for printf
16 #include <fstream>
17 #include <iostream>
18 #include <memory>
19 #include <sstream>
20 #include <string> // for allocator, string, char_traits
21 
22 namespace
23 {
24 
25  enum
26  {
27  TRGMESSAGE = 1,
28  FILLMESSAGE = 2
29  };
30 
31  // get first member of pairs into a list
32  std::vector<double> get_x( const MicromegasGeometry::point_list_t& point_list )
33  {
34  std::vector<double> out;
35  std::transform( point_list.begin(), point_list.end(), std::back_inserter( out ), []( const auto& p ) { return p.first; } );
36  return out;
37  }
38 
39  // get second member of pairs into a list
40  std::vector<double> get_y( const MicromegasGeometry::point_list_t& point_list )
41  {
42  std::vector<double> out;
43  std::transform( point_list.begin(), point_list.end(), std::back_inserter( out ), []( const auto& p ) { return p.second; } );
44  return out;
45  }
46 }
47 
48 //__________________________________________________
50  : OnlMon(name)
51 {
52  // setup default calibration filename
53  // note: this can be overriden by calling set_calibration_filename from the parent macro
54  const auto tpotcalib = getenv("TPOTCALIB");
55  if (!tpotcalib)
56  {
57  std::cout << "TpotMon::TpotMon - TPOTCALIB environment variable not set" << std::endl;
58  exit(1);
59  }
60 
61  m_calibration_filename = std::string(tpotcalib) + "/" + "TPOT_Pedestal-000.root";
62 }
63 
64 //__________________________________________________
66 {
67 
68  if( Verbosity() )
69  {
70  std::cout << "TpotMon::Init - m_calibration_filename: " << m_calibration_filename << std::endl;
71  std::cout << "TpotMon::Init - m_max_sample: " << m_max_sample << std::endl;
72  }
73 
74  // setup calibrations
75  if( std::ifstream( m_calibration_filename.c_str() ).good() )
76  {
78  } else {
79  std::cout << "TpotMon::Init -"
80  << " file " << m_calibration_filename << " cannot be opened."
81  << " No calibration loaded"
82  << std::endl;
83  }
84 
85  // server instance
86  auto se = OnlMonServer::instance();
87 
88  // map tile centers to fee id
89  const auto fee_id_list = m_mapping.get_fee_id_list();
90  for( const auto& fee_id:fee_id_list )
91  {
92  const auto tile_id = MicromegasDefs::getTileId( m_mapping.get_hitsetkey(fee_id));
93  m_tile_centers.emplace(fee_id, m_geometry.get_tile_center(tile_id));
94  }
95 
96  // counters
97  /* arbitrary counters. First bin is number of events */
98  m_counters = new TH1F( "m_counters", "counters", 10, 0, 10 );
99  m_counters->GetXaxis()->SetBinLabel(TpotMonDefs::kEventCounter, "events" );
100  m_counters->GetXaxis()->SetBinLabel(TpotMonDefs::kValidEventCounter, "valid events" );
101  m_counters->GetXaxis()->SetBinLabel(TpotMonDefs::kFullEventCounter, "full events" );
102  se->registerHisto(this, m_counters);
103 
104  // global occupancy
105  m_detector_multiplicity_phi = new TH2Poly( "m_detector_multiplicity_phi", "multiplicity (#phi); z (cm); x (cm)", -120, 120, -60, 60 );
106  m_detector_occupancy_phi = new TH2Poly( "m_detector_occupancy_phi", "occupancy (#phi); z (cm); x (cm);occupancy (%)", -120, 120, -60, 60 );
107  se->registerHisto(this, m_detector_occupancy_phi);
108 
109  m_detector_multiplicity_z = new TH2Poly( "m_detector_multiplicity_z", "multiplicity (z); z (cm); x (cm)", -120, 120, -60, 60 );
110  m_detector_occupancy_z = new TH2Poly( "m_detector_occupancy_z", "occupancy (z); z (cm); x(cm);occupancy (%)", -120, 120, -60, 60 );
111  se->registerHisto(this, m_detector_occupancy_z);
112 
113  // setup bins
115  {
117  h->GetXaxis()->SetTitleOffset(1);
118  h->GetYaxis()->SetTitleOffset(0.65);
119  h->SetMinimum(0);
120  }
121 
122  // resist region occupancy
123  m_resist_multiplicity_phi = new TH2Poly( "m_resist_multiplicity_phi", "multiplicity (#phi); z (cm); x (cm)", -120, 120, -60, 60 );
124  m_resist_occupancy_phi = new TH2Poly( "m_resist_occupancy_phi", "occupancy (#phi); z (cm); x (cm);occupancy (%)", -120, 120, -60, 60 );
125  se->registerHisto(this, m_resist_occupancy_phi);
126 
127  m_resist_multiplicity_z = new TH2Poly( "m_resist_multiplicity_z", "multiplicity (z); z (cm); x (cm)", -120, 120, -60, 60 );
128  m_resist_occupancy_z = new TH2Poly( "m_resist_occupancy_z", "occupancy (z); z (cm); x(cm);occupancy (%)", -120, 120, -60, 60 );
129  se->registerHisto(this, m_resist_occupancy_z);
130 
131  // setup bins
133  {
135  h->GetXaxis()->SetTitleOffset(1);
136  h->GetYaxis()->SetTitleOffset(0.65);
137  h->SetMinimum(0);
138  }
139 
141  {
143  h->GetXaxis()->SetTitleOffset(1);
144  h->GetYaxis()->SetTitleOffset(0.65);
145  h->SetMinimum(0);
146  }
147 
148  for( const auto& fee_id:fee_id_list )
149  {
150  // local copy of detector name
151  const auto& detector_name=m_mapping.get_detname_sphenix(fee_id);
152 
153  detector_histograms_t detector_histograms;
154 
155  {
156  auto h = detector_histograms.m_counts_sample = new TH1I(
157  Form( "m_counts_sample_%s", detector_name.c_str() ),
158  Form( "hit count vs sample (%s);sample;counts", detector_name.c_str() ),
160  h->GetXaxis()->SetTitleOffset(1.);
161  h->GetYaxis()->SetTitleOffset(1.65);
162  se->registerHisto(this, detector_histograms.m_counts_sample);
163  }
164 
165  {
166  auto h = detector_histograms.m_adc_sample = new TH2I(
167  Form( "m_adc_sample_%s", detector_name.c_str() ),
168  Form( "adc count vs sample (%s);sample;adc", detector_name.c_str() ),
170  1024, 0, 1024 );
171  h->GetXaxis()->SetTitleOffset(1.);
172  h->GetYaxis()->SetTitleOffset(1.65);
173  se->registerHisto(this, detector_histograms.m_adc_sample);
174  }
175 
176  // hit charge
177  static constexpr double max_hit_charge = 1024;
178  detector_histograms.m_hit_charge = new TH1I(
179  Form( "m_hit_charge_%s", detector_name.c_str() ),
180  Form( "hit charge distribution (%s);adc", detector_name.c_str() ),
181  100, 0, max_hit_charge );
182  se->registerHisto(this, detector_histograms.m_hit_charge);
183 
184  // hit multiplicity
185  detector_histograms.m_hit_multiplicity = new TH1I(
186  Form( "m_hit_multiplicity_%s", detector_name.c_str() ),
187  Form( "hit multiplicity (%s);#hits", detector_name.c_str() ),
188  256, 0, 256 );
189  se->registerHisto(this, detector_histograms.m_hit_multiplicity);
190 
191  // hit per channel
192  detector_histograms.m_hit_vs_channel = new TH1I(
193  Form( "m_hit_vs_channel_%s", detector_name.c_str() ),
194  Form( "hit profile (%s);channel", detector_name.c_str() ),
195  256, 0, 256 );
196  se->registerHisto(this, detector_histograms.m_hit_vs_channel);
197 
198  // store in map
199  m_detector_histograms.emplace( fee_id, std::move( detector_histograms ) );
200 
201  }
202 
203  // use monitor name for db table name
204  Reset();
205  return 0;
206 }
207 
208 //________________________________
209 int TpotMon::BeginRun(const int /* runno */)
210 {
211  // if you need to read calibrations on a run by run basis
212  // this is the place to do it
213  return 0;
214 }
215 
216 //________________________________
218 {
219 
220  // increment a given bin number by weight
221  auto increment = []( TH1* h, int bin, double weight = 1.0 )
222  { h->SetBinContent(bin, h->GetBinContent(bin)+weight ); };
223 
224  // increment total number of event
226 
227  // check event and event type
228  if( !event ) { return 0; }
229  if(event->getEvtType() >= 8) { return 0; }
230 
231  // increment total number of valid events
232  ++m_evtcnt;
233 
235 
236  // hit multiplicity vs fee id
237  std::map<int, int> multiplicity;
238 
239  // read the data
240  double fullevent_weight = 0;
241  for( const auto& packet_id:MicromegasDefs::m_packet_ids )
242  {
243  std::unique_ptr<Packet> packet(event->getPacket(packet_id));
244  if( !packet )
245  {
246  // no data
247  if( Verbosity() )
248  { std::cout << "TpotMon::process_event - packet " << packet_id << " not found" << std::endl; }
249  continue;
250  }
251 
252  // get number of datasets (also call waveforms)
253  const auto n_waveforms = packet->iValue(0, "NR_WF" );
254 
255  // add contribution to full event
256  /*
257  * we assume a full event must have m_nchannels_total waveforms
258  * this will break when zero suppression is implemented
259  */
260  fullevent_weight += double(n_waveforms)/MicromegasDefs::m_nchannels_total;
261 
262  if( Verbosity() )
263  { std::cout << "TpotMon::process_event - n_waveforms: " << n_waveforms << std::endl; }
264  for( int i=0; i<n_waveforms; ++i )
265  {
266  auto channel = packet->iValue( i, "CHANNEL" );
267  int fee_id = packet->iValue(i, "FEE" );
268  int samples = packet->iValue( i, "SAMPLES" );
269 
270  // get channel rms and pedestal from calibration data
271  const double pedestal = m_calibration_data.get_pedestal( fee_id, channel );
272  const double rms = m_calibration_data.get_rms( fee_id, channel );
273 
274  // get detector index from fee id
275  const auto iter = m_detector_histograms.find( fee_id );
276  if( iter == m_detector_histograms.end() )
277  {
278  std::cout << "TpotMon::process_event - invalid fee_id: " << fee_id << std::endl;
279  continue;
280  }
281  const auto& detector_histograms = iter->second;
282 
283  // get tile center, segmentation
284  const auto& [tile_x, tile_y] = m_tile_centers.at(fee_id);
285  const auto segmentation = MicromegasDefs::getSegmentationType( m_mapping.get_hitsetkey(fee_id));
286 
287  if( Verbosity()>1 )
288  {
289  std::cout
290  << "TpotMon::process_event -"
291  << " waveform: " << i
292  << " fee: " << fee_id
293  << " channel: " << channel
294  << " samples: " << samples
295  << std::endl;
296  }
297 
298  for( int is = 0; is < samples; ++is )
299  {
300  const auto adc = packet->iValue( i, is );
301  const bool is_signal = rms>0 && (adc > m_min_adc) && (adc> pedestal+m_n_sigma*rms);
302  if( is_signal ) detector_histograms.m_counts_sample->Fill( is );
303  detector_histograms.m_adc_sample->Fill( is, adc );
304  detector_histograms.m_hit_charge->Fill( adc );
305  }
306 
307  // define if hit is signal
308  bool is_signal = false;
309  for( int is = std::max<int>(0,m_sample_window_signal.first); is < std::min<int>(samples,m_sample_window_signal.second); ++is )
310  {
311  const auto adc = packet->iValue( i, is );
312  if( rms>0 && (adc > m_min_adc) && (adc>pedestal + m_n_sigma*rms) )
313  {
314  is_signal = true;
315  break;
316  }
317  }
318 
319  // fill hit profile for this channel
320  if( is_signal )
321  {
322  const auto strip_index = m_mapping.get_physical_strip(fee_id, channel );
323  detector_histograms.m_hit_vs_channel->Fill( strip_index );
324 
325  // update multiplicity for this detector
326  ++multiplicity[fee_id];
327 
328  // fill detector multiplicity
329  switch( segmentation )
330  {
332  m_detector_multiplicity_z->Fill( tile_x, tile_y );
333  m_resist_multiplicity_z->Fill( tile_x + MicromegasGeometry::m_tile_length*( double(strip_index)/MicromegasDefs::m_nchannels_fee - 0.5), tile_y );
334  break;
335 
337  m_detector_multiplicity_phi->Fill( tile_x, tile_y );
338  m_resist_multiplicity_phi->Fill( tile_x, tile_y + MicromegasGeometry::m_tile_width*( double(strip_index)/MicromegasDefs::m_nchannels_fee - 0.5) );
339  break;
340  }
341  }
342  }
343  }
344 
345  // increment full event counter and counters histogram
346  m_fullevtcnt += fullevent_weight;
347  increment( m_counters, TpotMonDefs::kFullEventCounter, fullevent_weight );
348 
349  // fill hit multiplicities
350  for( auto&& [fee_id, detector_histograms]:m_detector_histograms )
351  { detector_histograms.m_hit_multiplicity->Fill( multiplicity[fee_id] ); }
352 
353  // convert multiplicity histogram into occupancy
354  auto copy_content = []( TH2Poly* source, TH2Poly* destination, double scale )
355  {
356  for( int bin = 0; bin < source->GetNumberOfBins(); ++bin )
357  { destination->SetBinContent( bin+1, source->GetBinContent( bin+1 )*scale ); }
358  };
359 
361  copy_content( m_detector_multiplicity_phi, m_detector_occupancy_phi, 100./(m_fullevtcnt*MicromegasDefs::m_nchannels_fee) );
362  copy_content( m_resist_multiplicity_z, m_resist_occupancy_z, 400./(m_fullevtcnt*MicromegasDefs::m_nchannels_fee) );
363  copy_content( m_resist_multiplicity_phi, m_resist_occupancy_phi, 400./(m_fullevtcnt*MicromegasDefs::m_nchannels_fee) );
364 
365  return 0;
366 }
367 
368 //________________________________
370 {
371  // reset our internal counters
372  m_evtcnt = 0;
373  m_fullevtcnt = 0;
374 
375  // reset all histograms
376  for( TH1* h:{
381  { h->Reset(); }
382 
383  for( const auto& [fee_id,hlist]:m_detector_histograms )
384  {
385  for( TH1* h:std::initializer_list<TH1*>{hlist.m_counts_sample, hlist.m_adc_sample, hlist.m_hit_charge, hlist.m_hit_multiplicity, hlist.m_hit_vs_channel } )
386  { h->Reset(); }
387  }
388 
389  return 0;
390 }
391 
392 //________________________________
394 {
395  // loop over tile centers
396  for( size_t i = 0; i < m_geometry.get_ntiles(); ++i )
397  {
398  const auto boundaries = m_geometry.get_tile_boundaries( i );
399  h2->AddBin( boundaries.size(), &get_x( boundaries )[0], &get_y( boundaries )[0] );
400  }
401 }
402 
403 //________________________________
405 {
406  // loop over tile centers
407  for( size_t itile = 0; itile < m_geometry.get_ntiles(); ++itile )
408  {
409  for( size_t iresist = 0; iresist < MicromegasGeometry::m_nresist; ++iresist )
410  {
411  const auto boundaries = m_geometry.get_resist_boundaries( itile, iresist, segmentation );
412  h2->AddBin( boundaries.size(), &get_x( boundaries )[0], &get_y( boundaries )[0] );
413  }
414  }
415 }