AlcapDAQ  1
MdEdxPlot.cpp
Go to the documentation of this file.
1 /********************************************************************\
2 
3 Name: MdEdxPlot
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 typedef std::vector<std::vector<TPulseIsland*>::iterator> vecOfIterToPulses;
37 
38 /*-- Module declaration --------------------------------------------*/
39 INT MdEdxPlot_init(void);
40 INT MdEdxPlot(EVENT_HEADER*, void*);
41 std::map<double, double> MakePulseTimeHeightMap(std::vector<TPulseIsland*> thePulses);
42 std::map<double, double> MakePulseHeightSums(std::vector<std::map<double, double> > timeHeightMapsVector, double time_difference);
43 
44 extern HNDLE hDB;
45 extern TGlobalData* gData;
46 extern TSetupData* gSetup;
47 
48 static TH2D* hdEdx_left;
49 static TH2D* hdEdx_right;
50 
51 std::vector<std::string> left_thin_banknames;
52 std::vector<std::string> left_thick_banknames;
53 std::vector<std::string> right_thin_banknames;
54 std::vector<std::string> right_thick_banknames;
55 
56 ANA_MODULE MdEdxPlot_module =
57 {
58  "MdEdxPlot", /* module name */
59  "Andrew Edmonds", /* author */
60  MdEdxPlot, /* event routine */
61  NULL, /* BOR routine */
62  NULL, /* EOR routine */
63  MdEdxPlot_init, /* init routine */
64  NULL, /* exit routine */
65  NULL, /* parameter structure */
66  0, /* structure size */
67  NULL, /* initial parameters */
68 };
69 
73 {
74  // The dE/dx histogram is created for the left and right arms of the detector:
75  // energy in Si1 (x-axis) vs total energy in Si1 + Si2 (y-axis)
76 
77  std::map<std::string, std::string> bank_to_detector_map = gSetup->fBankToDetectorMap;
78  for(std::map<std::string, std::string>::iterator mapIter = bank_to_detector_map.begin();
79  mapIter != bank_to_detector_map.end(); mapIter++) {
80 
81  std::string bankname = mapIter->first;
82  std::string detname = gSetup->GetDetectorName(bankname);
83 
84  if (detname.substr(0,4) == "SiL1" && detname.substr(7,4) == "slow")
85  left_thin_banknames.push_back(bankname);
86  else if (detname.substr(0,4) == "SiL2" && detname.substr(5,4) == "slow")
87  left_thick_banknames.push_back(bankname);
88  else if (detname.substr(0,4) == "SiR1" && detname.substr(7,4) == "slow")
89  right_thin_banknames.push_back(bankname);
90  else if (detname.substr(0,4) == "SiR2" && detname.substr(5,4) == "slow")
91  right_thick_banknames.push_back(bankname);
92  }
93 
94  int max_adc_value = 4096; // probably want to check which channel we're in before setting this
95  max_adc_value = 7500;
96  // hdEdx
97  std::string histname = "hdEdx_left";
98  std::string histtitle = "dE/dx plot for the left arm";
99  hdEdx_left = new TH2D(histname.c_str(), histtitle.c_str(), max_adc_value,0,max_adc_value, max_adc_value,0,max_adc_value);
100  hdEdx_left->GetXaxis()->SetTitle("Pulse Height in Si1");
101  hdEdx_left->GetYaxis()->SetTitle("Total Pulse Height in Si1 and Si2");
102 
103  histname = "hdEdx_right";
104  histtitle = "dE/dx plot for the right arm";
105  hdEdx_right = new TH2D(histname.c_str(), histtitle.c_str(), max_adc_value,0,max_adc_value, max_adc_value,0,max_adc_value);
106  hdEdx_right->GetXaxis()->SetTitle("Pulse Height in Si1");
107  hdEdx_right->GetYaxis()->SetTitle("Total Pulse Height in Si1 and Si2");
108 
109  return SUCCESS;
110 }
111 
115 INT MdEdxPlot(EVENT_HEADER *pheader, void *pevent)
116 {
117  // Get the event number
118  int midas_event_number = pheader->serial_number;
119 
120  // Some typedefs
121  typedef map<string, vector<TPulseIsland*> > TStringPulseIslandMap;
122  typedef pair<string, vector<TPulseIsland*> > TStringPulseIslandPair;
123  typedef map<string, vector<TPulseIsland*> >::iterator map_iterator;
124 
125  // Fetch a reference to the gData structure that stores a map
126  // of (bank_name, vector<TPulseIsland*>) pairs
127  TStringPulseIslandMap& pulse_islands_map =
129 
131  // SiL
132  // Just loop over the banks we know are connected to these detectors
133  std::vector<std::map<double, double> > thinSiLeft_TimeHeightMaps;
134  for (std::vector<std::string>::iterator bankNameIter = left_thin_banknames.begin();
135  bankNameIter != left_thin_banknames.end(); bankNameIter++) {
136 
137  std::vector<TPulseIsland*> temp_vector = gData->fPulseIslandToChannelMap[*bankNameIter];
138  //skip bank if it doesen't exist
139  if (temp_vector.size() == 0) continue;
140 
141  thinSiLeft_TimeHeightMaps.push_back(MakePulseTimeHeightMap(temp_vector));
142  }
143  std::map<double, double> thinLeftSum;
144  if (thinSiLeft_TimeHeightMaps.size() != 0)
145  thinLeftSum = MakePulseHeightSums(thinSiLeft_TimeHeightMaps, 1000);
146 
147  std::vector<std::map<double, double> > totalLeft_TimeHeightMaps;
148  for (std::vector<std::string>::iterator leftThickIter = left_thick_banknames.begin();
149  leftThickIter != left_thick_banknames.end(); leftThickIter++) {
150 
151  std::vector<TPulseIsland*> temp_vector = gData->fPulseIslandToChannelMap[*leftThickIter];
152  //skip bank if it doesen't exist
153  if (temp_vector.size() == 0) continue;
154 
155  totalLeft_TimeHeightMaps.push_back(MakePulseTimeHeightMap(temp_vector));
156  }
157  if (thinLeftSum.size() != 0)
158  totalLeft_TimeHeightMaps.push_back(thinLeftSum);
159 
160  std::map<double, double> totalLeftSum;
161  if (totalLeft_TimeHeightMaps.size() != 0)
162  totalLeftSum = MakePulseHeightSums(totalLeft_TimeHeightMaps, 1000);
163 
164  for (std::map<double, double>::iterator thinHit = thinLeftSum.begin(), totalHit = totalLeftSum.begin();
165  thinHit != thinLeftSum.end() || totalHit != totalLeftSum.end(); thinHit++, totalHit++) {
166 
167  hdEdx_left->Fill((*thinHit).second, (*totalHit).second);
168  }
169  //
171 
172 
174  // SiR
175  // Just loop over the banks we know are connected to these detectors
176  std::vector<std::map<double, double> > thinSiRight_TimeHeightMaps;
177  for (std::vector<std::string>::iterator bankNameIter = right_thin_banknames.begin();
178  bankNameIter != right_thin_banknames.end(); bankNameIter++) {
179 
180  std::vector<TPulseIsland*> temp_vector = gData->fPulseIslandToChannelMap[*bankNameIter];
181  //skip bank if it doesen't exist
182  if (temp_vector.size() == 0) continue;
183 
184  thinSiRight_TimeHeightMaps.push_back(MakePulseTimeHeightMap(temp_vector));
185  }
186  std::map<double, double> thinRightSum;
187  if (thinSiRight_TimeHeightMaps.size() != 0)
188  thinRightSum = MakePulseHeightSums(thinSiRight_TimeHeightMaps, 1000);
189 
190  std::vector<std::map<double, double> > totalRight_TimeHeightMaps;
191  for (std::vector<std::string>::iterator rightThickIter = right_thick_banknames.begin();
192  rightThickIter != right_thick_banknames.end(); rightThickIter++) {
193 
194  std::vector<TPulseIsland*> temp_vector = gData->fPulseIslandToChannelMap[*rightThickIter];
195  //skip bank if it doesen't exist
196  if (temp_vector.size() == 0) continue;
197 
198  totalRight_TimeHeightMaps.push_back(MakePulseTimeHeightMap(temp_vector));
199  }
200  if (thinRightSum.size() != 0)
201  totalRight_TimeHeightMaps.push_back(thinRightSum);
202 
203  std::map<double, double> totalRightSum;
204  if (totalRight_TimeHeightMaps.size() != 0)
205  totalRightSum = MakePulseHeightSums(totalRight_TimeHeightMaps, 1000);
206 
207  for (std::map<double, double>::iterator thinHit = thinRightSum.begin(), totalHit = totalRightSum.begin();
208  thinHit != thinRightSum.end() || totalHit != totalRightSum.end(); thinHit++, totalHit++) {
209 
210  hdEdx_right->Fill((*thinHit).second, (*totalHit).second);
211  }
212 
213  return SUCCESS;
214 }
215 
216 // MakePulseTimeHeightMap()
217 // -- Takes a vector of TPulseIsland* and creates a map of pulse time and pulse height
218 // -- This is used to add pulses for the thin Si (and also for any detectors?)
219 std::map<double, double> MakePulseTimeHeightMap(std::vector<TPulseIsland*> thePulses) {
220 
221  std::map<double, double> output;
222 
223  for (std::vector<TPulseIsland*>::iterator pulseIter = thePulses.begin();
224  pulseIter != thePulses.end(); pulseIter++) {
225 
226  output[(*pulseIter)->GetPulseTime()] = (*pulseIter)->GetPulseHeight();
227  }
228 
229  return output;
230 }
231 
232 // MakePulseHeightSums()
233 // -- Creates a map of (time, total height) from the a vector of (time, height) maps
234 // -- This function also checks that the pulses are within a certain time difference of each other
235 std::map<double, double> MakePulseHeightSums(std::vector<std::map<double, double> > timeHeightMapsVector, double time_difference) {
236 
237  // Create the iterators
238  std::vector<std::map<double, double>::iterator > pulseIters;
239  std::vector<std::map<double, double>::iterator > backwardIters;
240 
241  for (int b = 0; b < timeHeightMapsVector.size(); b++) {
242  pulseIters.push_back((timeHeightMapsVector.at(b)).begin());
243  backwardIters.push_back((timeHeightMapsVector.at(b)).end());
244  }
245 
246  // Prepare the output map:
247  std::map<double, double> output;
248 
249  while ( pulseIters.size() > 0 ) {
250 
251  //Iterators/pointers into pulseIters and backwardIters must not be held past
252  //one loop cycle as they may become invalidated.
253 
254  //Get the time of the next (unused) TPulseIslands (one from each bank)
255  //work out which is the earliest
256  double min_time = 99999999999.; //something huge.
257  for (int b = 0; b < pulseIters.size(); ++b){
258  double time = (pulseIters.at(b))->first;
259  min_time = std::min(min_time , time);
260  // printf("Bank #%d: time = %f ms\n", b, time * 1e-6);
261  //Or use GetTimeStamp()?
262  }
263  // printf("Min time = %f ms\n", min_time*1e-6);
264 
265  //Sum all the pulseHeights at a given time
266  double pulseHeight = 0;
267  double pulseTime = 0;
268  int nSummed = 0;
269  for (int b = 0; b < pulseIters.size(); ++b){
270  std::pair<double, double> timeHeightPair = *(pulseIters.at(b));
271  //Need to define a comparison for CONSISTENT_TIME
272  if ( std::abs(timeHeightPair.first - min_time) < time_difference ) {
273  pulseHeight += timeHeightPair.second;
274  pulseTime += timeHeightPair.first;
275  ++nSummed;
276  //and increment the iterator because we used the island
277  ++(pulseIters.at(b));
278  // printf("Bank #%d: height = %f, time = %f ms\n", b, timeHeightPair.second, timeHeightPair.first * 1e-6);
279  }
280  } // for (int b)
281 
282  //append to output
283  // printf("Summed time = %f ms, Summed height = %f\n", (pulseTime/nSummed)*1e-6, pulseHeight);
284  output[pulseTime/nSummed] = pulseHeight;
285 
286 
287  //Delete the iterators to finished banks. Go through in reverse to
288  //avoid invalidation problems
289  for (int b = pulseIters.size()-1; b >= 0 ; --b){
290  if (pulseIters.at(b) == backwardIters.at(b)){
291  pulseIters.erase(pulseIters.begin() + b);
292  backwardIters.erase(backwardIters.begin() + b);
293  }
294  } // for (int b -reversed)
295  } // while (size > 0)
296 
297  return output;
298 }