Belle II Software  release-08-01-10
TOPWaveformQualityPlotterModule.cc
1 /**************************************************************************
2  * basf2 (Belle II Analysis Software Framework) *
3  * Author: The Belle II Collaboration *
4  * *
5  * See git log for contributors and copyright holders. *
6  * This file is licensed under LGPL-3.0, see LICENSE.md. *
7  **************************************************************************/
8 
9 // basf2
10 #include <framework/core/HistoModule.h>
11 #include <top/modules/TOPWaveformQualityPlotter/TOPWaveformQualityPlotterModule.h>
12 
13 // stl
14 #include <utility>
15 
16 //ROOT
17 #include "TDirectory.h"
18 #include "TCanvas.h"
19 #include "TGraphErrors.h"
20 
21 using namespace std;
22 
23 namespace Belle2 {
29  //-----------------------------------------------------------------
31  //-----------------------------------------------------------------
32 
33  REG_MODULE(TOPWaveformQualityPlotter);
34 
35  //-----------------------------------------------------------------
36  // Implementation
37  //-----------------------------------------------------------------
38 
39  TOPWaveformQualityPlotterModule::TOPWaveformQualityPlotterModule()
40  : HistoModule()
41  {
42  setDescription("TOP DQM histogram module");
43  addParam("histogramDirectoryName", m_histogramDirectoryName,
44  "histogram directory in ROOT file", string("TOP"));
45  addParam("drawWaves", m_DRAWWAVES, "option to draw waveforms", true);
46  addParam("debugHistos", m_DEBUGGING, "option to draw debug histograms", true);
47  addParam("noisemaps", m_NOISE, "option to draw noisemaps", false);
48  }
49 
50 
52  {
53  TDirectory* oldDir = gDirectory;
54  m_directory = oldDir->mkdir(m_histogramDirectoryName.c_str());
55  m_directory->cd();
56  m_samples = new TH1F("ADCvalues", "ADC values ", 100, -50, 50);
57  m_samples->GetXaxis()->SetTitle("ADC Value");
58  m_samples->GetYaxis()->SetTitle("Number of Samples");
59  m_scrod_id = new TH1F("scrodID", "scrodID", 100, 0, 100);
60  m_asic = new TH1F("IRSX", "IRSX", 4, 0, 4);
61  m_carrier = new TH1F("carrier", "asic col", 4, 0, 4);
62  m_asic_ch = new TH1F("asicCh", "channel", 8, 0, 8);
63  m_errorFlag = new TH1F("errorFlag", "errorFlag", 1000, 0, 1000);
64  m_asic_win = new TH1F("window", "window", 4, 0, 4);
65  m_entries = new TH1F("entries", "entries", 100, 0, 2600);
66  m_moduleID = new TH1F("moduleID", "moduleID", 16, 1, 17);
67  m_pixelID = new TH1F("pixelID", "pixelID", 512, 1, 513);
68  oldDir->cd();
69  }
70 
71 
73  {
74  // Register histograms (calls back defineHisto)
75  REG_HISTOGRAM;
76  //Get Waveform from datastore
77  m_waveform.isRequired();
78  }
79 
80 
82  {
83  int scrodid = v.getScrodID();
84  int asicid = v.getASICNumber();
85  int channelid = v.getASICChannel();
86  int carrierid = v.getCarrierNumber();
87  m_scrod_id->Fill(scrodid);
88  m_asic_ch->Fill(channelid);
89  m_asic->Fill(asicid);
90  m_carrier->Fill(carrierid);
91  m_asic_win->Fill(v.getStorageWindow());
92  m_entries->Fill(v.getWaveform().size());
93  m_moduleID->Fill(v.getModuleID());
94  m_pixelID->Fill(v.getPixelID());
95 
96  if (m_hitmap.find(scrodid) == m_hitmap.end()) {
97  m_hitmap[scrodid] = new TH2F((string("scrod ") + to_string(scrodid) + string("Hitmap")).c_str(),
98  (string("scrod ") + to_string(scrodid) + string("carrier vs. asic;asic;carrier")).c_str(), 4, 0, 4, 4, 0, 4);
99  }
100  m_hitmap[scrodid]->Fill(asicid, carrierid);
101  const vector<short>& waveform = v.getWaveform();
102  if (waveform.empty()) {
103  return;
104  }
105  for (short adc : waveform) {
106  m_samples->Fill(adc);
107  }
108  }
109 
110  void
112  {
113  vector<short> waveform = v.getWaveform();
114  if (waveform.empty()) {
115  return;
116  }
117  int scrodid = v.getScrodID();
118  // skip broken events
119  if (scrodid == 0) {
120  return;
121  }
122  int asicNumber = v.getASICNumber();
123  int carrierNumber = v.getCarrierNumber();
124  int iChannel = v.getASICChannel();
125  string gname = string("scrod_") + to_string(scrodid) + string("_carrier") + to_string(carrierNumber) + string("_asic") + to_string(
126  asicNumber) + to_string(iChannel);
127  if (m_waveformHists[scrodid][carrierNumber][asicNumber].find(iChannel) ==
128  m_waveformHists[scrodid][carrierNumber][asicNumber].end()) {
129  // FIXME ? This assumes exactly 256 samples in a waveform (FE data)
130  auto h = new TProfile(gname.c_str(), gname.c_str(), 256, 0, 256);
131  h->Sumw2(false); // unweighted filling.
132  m_waveformHists[scrodid][carrierNumber][asicNumber][iChannel] = h;
133  }
134  // FIXME assumes 256 samples in a waveform
135  for (size_t i = 0; i < 256; ++i) {
136  // exit broken waveforms early
137  if (i >= waveform.size()) {
138  break;
139  }
140  m_waveformHists[scrodid][carrierNumber][asicNumber][iChannel]->Fill(i + 0.5, iChannel * 1500 + waveform[i]);
141  }
142  }
143 
144 
146  {
147  if (not m_waveform) {
148  return;
149  }
150  for (auto evtwave : m_waveform) {
151  if (m_DRAWWAVES) {
152  drawWaveforms(evtwave);
153  }
154  if (m_DEBUGGING) {
155  basicDebuggingPlots(evtwave);
156  }
157  if (m_NOISE) {
158  auto channelID = evtwave.getChannel();
159  const vector<short> v_samples = evtwave.getWaveform();
160  size_t nsamples = v_samples.size();
161  if (m_channelNoiseMap.find(channelID) == m_channelNoiseMap.end()) {
162  string idName = string("noise_") + to_string(channelID);
163  m_channelNoiseMap.insert(make_pair(channelID, new TH1F(idName.c_str(), idName.c_str(), 200, -100, 100)));
164  m_channelEventMap.insert(make_pair(channelID, m_iEvent));
165  }
166  TH1F* noise = m_channelNoiseMap[channelID];
167  // Plot all samples in common histogram for quick sanity check
168  for (size_t s = 0; s < nsamples; s++) {
169  double adc = v_samples.at(s);
170  m_samples->Fill(adc);
171  if (s < nsamples - 1) {
172  noise->Fill(v_samples[s + 1] - adc);
173  }
174  }
175  }
176  }
177  m_iEvent += 1;
178  return;
179  }
180 
182  {
183  if (m_DRAWWAVES) {
184  // Each waveform was stored in a TH1F
185  // This now gets transformed to a TGraph
186  // All 8 channels for a given ASIC are put in the same TMultiGraph
187  // Then we make one canvas of several TMultigraphs for each scrod
188  // FIXME: This is going to get called at the end of the run; the mem leak I am introducing here should be fixed by somebody more patient with ROOT memory management than me.
189  for (auto scrod_it : m_waveformHists) {
190  int scrodid = scrod_it.first;
191  string name = string("scrod_") + to_string(scrodid);
192  TCanvas* c = new TCanvas(name.c_str(), name.c_str());
193  c->Divide(4, 4);
194  int canvasPad = 0;
195  for (auto carrier_it : scrod_it.second) {
196  int carrierNumber = carrier_it.first;
197  for (auto asic_it : carrier_it.second) {
198  int asicNumber = asic_it.first;
199  canvasPad += 1;
200  string gname = string("scrod_") + to_string(scrodid) + string("_carrier") + to_string(carrierNumber) + string("_asic") + to_string(
201  asicNumber);
202  TMultiGraph* mg = new TMultiGraph(gname.c_str(), gname.c_str());
203  for (auto channel_it : asic_it.second) {
204  // read the data from the TProfile
205  TGraphErrors* g = new TGraphErrors(channel_it.second);
206  g->SetMarkerStyle(7);
207  mg->Add(g);
208  }
209  // FIXME nSamples is hard-coded to 256
210  TH2F* h = new TH2F(gname.c_str(), gname.c_str(), 256, 0, 256, 8, -500, -500 + 8 * 1500);
211  for (int ibin = 0; ibin < 8; ibin++) {
212  h->GetYaxis()->SetBinLabel(ibin + 1, to_string(ibin).c_str());
213  }
214  h->GetYaxis()->SetTickSize(0);
215  h->GetYaxis()->SetTickLength(0);
216  h->SetStats(0);
217  c->cd(canvasPad);
218  h->Draw();
219  mg->Draw("P");
220  }
221  }
222  m_directory->WriteTObject(c);
223  }
224  }
225  }
226 
228 } // end Belle2 namespace
HistoModule.h is supposed to be used instead of Module.h for the modules with histogram definitions t...
Definition: HistoModule.h:29
void setDescription(const std::string &description)
Sets the description of the module.
Definition: Module.cc:214
Class to store raw data waveforms.
unsigned getASICNumber() const
Returns ASIC number.
unsigned getCarrierNumber() const
Returns carrier board number.
int getPixelID() const
Returns pixel ID (1-based)
int getModuleID() const
Returns module ID.
unsigned getASICChannel() const
Returns ASIC channel number.
unsigned getStorageWindow() const
Returns hardware logic window number (storage window)
unsigned getScrodID() const
Returns SCROD ID.
const std::vector< short > & getWaveform() const
Returns waveform.
std::map< top_channel_id_t, int > m_channelEventMap
to find in which chunk a given channel is
TH1F * m_asic_ch
plot of ASIC channel ID debugging
std::map< int, std::map< int, std::map< int, std::map< int, TProfile * > > > > m_waveformHists
scrod, carrier, asic, channel
int m_iEvent
keeps track of iterations within run
TH1F * m_pixelID
plot of pixel ID for debugging
std::string m_histogramDirectoryName
the name of the directory inside the output file
std::map< int, TH2F * > m_hitmap
hitmaps for each SCROD
std::map< top_channel_id_t, TH1F * > m_channelNoiseMap
histogram of the values after correction
TH1F * m_carrier
plot of carrier IDs for debugging
StoreArray< TOPRawWaveform > m_waveform
the raw waveforms
TH1F * m_errorFlag
plot of error flag (not impemented)
TH1F * m_scrod_id
plot of SCROD IDs for debugging
TH1F * m_asic
plot of ASIC number for debugging
void addParam(const std::string &name, T &paramVariable, const std::string &description, const T &defaultValue)
Adds a new parameter to the module.
Definition: Module.h:560
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
Definition: Module.h:650
void initialize() override
Module initialization, calls defineHisto and gets waveform.
void basicDebuggingPlots(const TOPRawWaveform &rawwave)
Fills the debugging 1D histograms and hitmaps.
void drawWaveforms(const TOPRawWaveform &rawwave)
Draws the full waveforms onto the TProfiles.
void defineHisto() override
Books the empty histograms.
Abstract base class for different kinds of events.