AlcapDAQ  1
MCombinePulses.cpp
Go to the documentation of this file.
1 /********************************************************************\
2 
3 Name: MCombinePulses
4 Created by: Andrew Edmonds
5 
6 Contents: One module that fills out histograms for the pulse heights, pulse shapes and the raw counts for all digitizer channels. These are all in one module to be more efficient in terms of minimising the number of times we loop through the channels.
7 
8 \********************************************************************/
9 
10 /* Standard includes */
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string>
14 #include <map>
15 #include <utility>
16 #include <sstream>
17 #include <cmath>
18 
19 /* MIDAS includes */
20 #include "midas.h"
21 
22 /* ROOT includes */
23 #include <TH1.h>
24 #include <TH2.h>
25 
26 /* AlCap includes */
27 #include "TGlobalData.h"
28 #include "TSetupData.h"
29 #include "TPulseIsland.h"
30 
31 using std::string;
32 using std::map;
33 using std::vector;
34 using std::pair;
35 
36 /*-- Module declaration --------------------------------------------*/
37 INT MCombinePulses_init(void);
38 INT MCombinePulses_bor(INT);
39 INT MCombinePulses(EVENT_HEADER*, void*);
40 
41 std::vector<std::vector<int> > SumPulses(std::vector<std::vector<TPulseIsland*> > timeHeightMapsVector, double time_difference);
42 
43 extern HNDLE hDB;
44 extern TGlobalData* gData;
45 extern TSetupData* gSetup;
46 
47 static std::vector<std::string> left_thin_banknames;
48 static std::vector<std::string> right_thin_banknames;
49 static TH2D* hSiL1PulseShapes;
50 static TH2D* hSiR1PulseShapes;
51 static TH1I* hSiL1PulseHeights;
52 static TH1I* hSiR1PulseHeights;
53 
55 {
56  "MCombinePulses", /* module name */
57  "Andrew Edmonds", /* author */
58  MCombinePulses, /* event routine */
59  MCombinePulses_bor, /* BOR routine */
60  NULL, /* EOR routine */
61  MCombinePulses_init, /* init routine */
62  NULL, /* exit routine */
63  NULL, /* parameter structure */
64  0, /* structure size */
65  NULL, /* initial parameters */
66 };
67 
71 {
72  // The following histograms are created for each channel:
73  // hPulseHeights: ADC value (x-axis) vs number of pulses (y-axis)
74  // hPulseTimes: time stamp (x-axis) vs number of pulses (y-axis)
75  // hPulseRawCount: number of pulses (y-axis) - channels on x-axis?
76  // hPulseShapes: sample number (x-axis) vs ADC value (y-axis) vs pulse (z-axis)
77 
78  std::map<std::string, std::string> bank_to_detector_map = gSetup->fBankToDetectorMap;
79  for(std::map<std::string, std::string>::iterator mapIter = bank_to_detector_map.begin();
80  mapIter != bank_to_detector_map.end(); mapIter++) {
81 
82  std::string bankname = mapIter->first;
83  std::string detname = gSetup->GetDetectorName(bankname);
84 
85  if (detname.substr(0,4) == "SiL1" && detname.substr(7,1) == "S")
86  left_thin_banknames.push_back(bankname);
87  else if (detname.substr(0,4) == "SiR1" && detname.substr(7,1) == "S")
88  right_thin_banknames.push_back(bankname);
89  }
90 
91  long max_adc_value = 13000;
92 
93  // hSiL1PulseShapes
94  std::string histname = "hSiL1PulseShapes";
95  std::string histtitle = "Plot of the combined pulse shapes in SiL1";
96  hSiL1PulseShapes = new TH2D(histname.c_str(), histtitle.c_str(), 64,-0.5,63.5,max_adc_value+1,0,max_adc_value+1);
97  hSiL1PulseShapes->GetXaxis()->SetTitle("Time Stamp");
98  hSiL1PulseShapes->GetYaxis()->SetTitle("ADC Value");
99 
100  // hSiR1PulseShapes
101  histname = "hSiR1PulseShapes";
102  histtitle = "Plot of the combined pulse shapes in SiR1";
103  hSiR1PulseShapes = new TH2D(histname.c_str(), histtitle.c_str(), 64,-0.5,63.5,max_adc_value+1,0,max_adc_value+1);
104  hSiR1PulseShapes->GetXaxis()->SetTitle("Time Stamp");
105  hSiR1PulseShapes->GetYaxis()->SetTitle("ADC Value");
106 
107  // hSiL1PulseHeights
108  histname = "hSiL1PulseHeights";
109  histtitle = "Plot of the combined pulse heights in SiL1";
110  hSiL1PulseHeights = new TH1I(histname.c_str(), histtitle.c_str(), max_adc_value+1,0,max_adc_value+1);
111  hSiL1PulseHeights->GetXaxis()->SetTitle("ADC Value");
112  hSiL1PulseHeights->GetYaxis()->SetTitle("Number of Pulses");
113 
114  // hSiR1PulseHeights
115  histname = "hSiR1PulseHeights";
116  histtitle = "Plot of the combined pulse heights in SiR1";
117  hSiR1PulseHeights = new TH1I(histname.c_str(), histtitle.c_str(), max_adc_value+1,0,max_adc_value+1);
118  hSiR1PulseHeights->GetXaxis()->SetTitle("ADC Value");
119  hSiR1PulseHeights->GetYaxis()->SetTitle("Number of Pulses");
120 
121  return SUCCESS;
122 }
123 
124 // Resets the histograms at the beginning of each run so that the online display updates
126 
127  hSiL1PulseShapes->Reset();
128  hSiR1PulseShapes->Reset();
129  hSiL1PulseHeights->Reset();
130  hSiR1PulseHeights->Reset();
131 }
132 
136 INT MCombinePulses(EVENT_HEADER *pheader, void *pevent)
137 {
138  // Get the event number
139  int midas_event_number = pheader->serial_number;
140 
141  // Some typedefs
142  typedef map<string, vector<TPulseIsland*> > TStringPulseIslandMap;
143  typedef pair<string, vector<TPulseIsland*> > TStringPulseIslandPair;
144  typedef map<string, vector<TPulseIsland*> >::iterator map_iterator;
145 
146  // Fetch a reference to the gData structure that stores a map
147  // of (bank_name, vector<TPulseIsland*>) pairs
148  TStringPulseIslandMap& pulse_islands_map =
150 
152  // SiL
153  // Just loop over the banks we know are connected to these detectors
154  std::vector<std::vector<TPulseIsland*> > thinSiLeftPulses;
155  for (std::vector<std::string>::iterator bankNameIter = left_thin_banknames.begin();
156  bankNameIter != left_thin_banknames.end(); bankNameIter++) {
157 
158  std::vector<TPulseIsland*> temp_vector = gData->fPulseIslandToChannelMap[*bankNameIter];
159  //skip bank if it doesen't exist
160  if (temp_vector.size() == 0) continue;
161 
162  thinSiLeftPulses.push_back(temp_vector);
163  }
164  std::vector<std::vector<int> > allPulses = SumPulses(thinSiLeftPulses, 1000);
165 
166  for (std::vector<std::vector<int> >::iterator allPulseIter = allPulses.begin(); allPulseIter != allPulses.end(); ++allPulseIter) {
167 
168  // While filling the persistent scope histogram, look for the minimum sample value for the pulse height
169  int min_sample_value = 99999;
170  for (std::vector<int>::iterator sampleIter = (*allPulseIter).begin(); sampleIter != (*allPulseIter).end(); ++sampleIter) {
171 
172  // printf("Filling %d at position %d\n", *sampleIter, sampleIter - (*allPulseIter).begin());
173  if (*sampleIter < min_sample_value)
174  min_sample_value = *sampleIter;
175 
176  hSiL1PulseShapes->Fill(sampleIter - (*allPulseIter).begin(), *sampleIter);
177  }
178 
179  // Take into account the number of channels seen otherwise we get a 4 peak plot
180  if (min_sample_value < 6000)
181  min_sample_value /= 2;
182  else if (min_sample_value < 9000)
183  min_sample_value /= 3;
184  else if (min_sample_value < 12000)
185  min_sample_value /= 4;
186 
187  hSiL1PulseHeights->Fill( -1*(min_sample_value - ((thinSiLeftPulses[0])[0])->GetPedestal(10)) );
188  }
190 
191 
192 
194  // SiR
195  // Just loop over the banks we know are connected to these detectors
196  std::vector<std::vector<TPulseIsland*> > thinSiRightPulses;
197  for (std::vector<std::string>::iterator bankNameIter = right_thin_banknames.begin();
198  bankNameIter != right_thin_banknames.end(); bankNameIter++) {
199 
200  std::vector<TPulseIsland*> temp_vector = gData->fPulseIslandToChannelMap[*bankNameIter];
201  //skip bank if it doesen't exist
202  if (temp_vector.size() == 0) continue;
203 
204  thinSiRightPulses.push_back(temp_vector);
205  }
206  allPulses = SumPulses(thinSiRightPulses, 1000);
207 
208  for (std::vector<std::vector<int> >::iterator allPulseIter = allPulses.begin(); allPulseIter != allPulses.end(); ++allPulseIter) {
209 
210  // While filling the persistent scope histogram, look for the minimum sample value for the pulse height
211  int min_sample_value = 99999;
212  for (std::vector<int>::iterator sampleIter = (*allPulseIter).begin(); sampleIter != (*allPulseIter).end(); ++sampleIter) {
213 
214  // printf("Filling %d at position %d\n", *sampleIter, sampleIter - (*allPulseIter).begin());
215  if (*sampleIter < min_sample_value)
216  min_sample_value = *sampleIter;
217 
218  hSiR1PulseShapes->Fill(sampleIter - (*allPulseIter).begin(), *sampleIter);
219  }
220 
221  // Take into account the number of channels seen otherwise we get a 4 peak plot
222  if (min_sample_value < 6000)
223  min_sample_value /= 2;
224  else if (min_sample_value < 9000)
225  min_sample_value /= 3;
226  else if (min_sample_value < 12000)
227  min_sample_value /= 4;
228 
229  hSiR1PulseHeights->Fill( -1*(min_sample_value - ((thinSiRightPulses[0])[0])->GetPedestal(10)) );
230  }
232  return SUCCESS;
233 }
234 
235 // SumPulses()
236 // -- Creates a vector of sample vectors from a vector of TPulseIsland vectors
237 // -- This function also checks that the pulses are within a certain time difference of each other
238 std::vector<std::vector<int> > SumPulses(std::vector<std::vector<TPulseIsland*> > pulses, double time_difference) {
239 
240  // Create the iterators
241  std::vector<std::vector<TPulseIsland*>::iterator > pulseIters;
242  std::vector<std::vector<TPulseIsland*>::iterator > backwardIters;
243 
244  for (int b = 0; b < pulses.size(); b++) {
245  pulseIters.push_back((pulses.at(b)).begin());
246  backwardIters.push_back((pulses.at(b)).end());
247  }
248 
249  // Prepare the output map:
250  std::vector<std::vector<int> > output;
251 
252  while ( pulseIters.size() > 0 ) {
253 
254  //Iterators/pointers into pulseIters and backwardIters must not be held past
255  //one loop cycle as they may become invalidated.
256 
257  //Get the time of the next (unused) TPulseIslands (one from each bank)
258  //work out which is the earliest
259  double min_time = 99999999999.; //something huge.
260  for (int b = 0; b < pulseIters.size(); ++b){
261  double time = (*(pulseIters.at(b)))->GetPulseTime();
262  min_time = std::min(min_time , time);
263  // printf("Bank #%d: time = %f ms\n", b, time * 1e-6);
264  //Or use GetTimeStamp()?
265  }
266  // printf("Min time = %f ms\n", min_time*1e-6);
267 
268  //Sum all the pulseHeights at a given time
269  std::vector<int> temp_output;
270  for (int b = 0; b < pulseIters.size(); ++b){
271  TPulseIsland* pulse = *(pulseIters.at(b));
272  //Need to define a comparison for CONSISTENT_TIME
273  if ( std::abs(pulse->GetPulseTime() - min_time) < time_difference ) {
274  // printf("New Pulse\n");
275  // Now loop through the samples
276  std::vector<int> theSamples = pulse->GetSamples();
277 
278  // if we haven't set the size of temp_output yet, then reserve the number of elements we need
279  if (temp_output.size() == 0) {
280  for (int i = 0; i < theSamples.size(); ++i) {
281  temp_output.push_back(0);
282  }
283  }
284  // if temp_output is larger than the given samples vector, reduce the size
285  else if (temp_output.size() >= theSamples.size())
286  temp_output.erase(temp_output.end() - (temp_output.size() - theSamples.size()), temp_output.end());
287 
288  for (std::vector<int>::iterator sampleIter = theSamples.begin(); sampleIter != theSamples.end(); ++sampleIter) {
289  //printf("Value in pulse: %d\n", *sampleIter);
290  // printf("Value in temp_output: %d\n", temp_output.at(sampleIter - theSamples.begin()));
291  if ( (sampleIter - theSamples.begin()) >= temp_output.size() )
292  break;
293 
294  temp_output.at(sampleIter - theSamples.begin()) += *sampleIter;
295  }
296 
297  //and increment the iterator because we used the island
298  ++(pulseIters.at(b));
299  }
300  } // for (int b)
301  output.push_back(temp_output);
302 
303  //Delete the iterators to finished banks. Go through in reverse to
304  //avoid invalidation problems
305  for (int b = pulseIters.size()-1; b >= 0 ; --b){
306  if (pulseIters.at(b) == backwardIters.at(b)){
307  pulseIters.erase(pulseIters.begin() + b);
308  backwardIters.erase(backwardIters.begin() + b);
309  }
310  } // for (int b -reversed)
311  } // while (size > 0)
312 
313  return output;
314 }