Hall-D Software  alpha
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
HistogramTools.h
Go to the documentation of this file.
1 #ifndef __HistogramTools__
2 #define __HistogramTools__
3 
4 #include <iostream>
5 #include <stdexcept>
6 
7 #include <JANA/JApplication.h>
8 #include <TH1I.h>
9 #include <TH2I.h>
10 #include <TH3I.h>
11 #include <TProfile.h>
12 #include <TProfile2D.h>
13 #include <TDirectory.h>
14 
15 using namespace std;
16 using namespace jana;
17 
18 #ifndef ansi_escape
19 #define ansi_escape ((char)0x1b)
20 #define ansi_bold ansi_escape<<"[1m"
21 #define ansi_italic ansi_escape<<"[3m"
22 #define ansi_underline ansi_escape<<"[4m"
23 #define ansi_blink ansi_escape<<"[5m"
24 #define ansi_rapid_blink ansi_escape<<"[6m"
25 #define ansi_reverse ansi_escape<<"[7m"
26 #define ansi_black ansi_escape<<"[30m"
27 #define ansi_red ansi_escape<<"[31m"
28 #define ansi_green ansi_escape<<"[32m"
29 #define ansi_blue ansi_escape<<"[34m"
30 #define ansi_normal ansi_escape<<"[0m"
31 #define ansi_up(A) ansi_escape<<"["<<(A)<<"A"
32 #define ansi_down(A) ansi_escape<<"["<<(A)<<"B"
33 #define ansi_forward(A) ansi_escape<<"["<<(A)<<"C"
34 #define ansi_back(A) ansi_escape<<"["<<(A)<<"D"
35 #endif // ansi_escape
36 
37 vector <TDirectory *>& GetAllDirectories(void){
38  static vector <TDirectory *> allDirectories;
39  return allDirectories;
40 }
41 
42 map<TString, pair<TH1I*, pthread_rwlock_t*> >& Get1DMap(void){
43  static map<TString, pair<TH1I*, pthread_rwlock_t*> > TH1IMap;
44  return TH1IMap;
45 }
46 
47 map<TString, pair<TH1D*, pthread_rwlock_t*> >& Get1DWeightedMap(void){
48  static map<TString, pair<TH1D*, pthread_rwlock_t*> > TH1DMap;
49  return TH1DMap;
50 }
51 
52 map<TString, pair<TH2I*, pthread_rwlock_t*> >& Get2DMap(void){
53  static map<TString, pair<TH2I*, pthread_rwlock_t*> > TH2IMap;
54  return TH2IMap;
55 }
56 
57 map<TString, pair<TH2D*, pthread_rwlock_t*> >& Get2DWeightedMap(void){
58  static map<TString, pair<TH2D*, pthread_rwlock_t*> > TH2DMap;
59  return TH2DMap;
60 }
61 
62 map<TString, pair<TH3I*, pthread_rwlock_t*> >& Get3DMap(void){
63  static map<TString, pair<TH3I*, pthread_rwlock_t*> > TH3IMap;
64  return TH3IMap;
65 }
66 
67 map<TString, pair<TProfile*, pthread_rwlock_t*> >& Get1DProfileMap(void){
68  static map<TString, pair<TProfile*, pthread_rwlock_t*> > TProfile1DMap;
69  return TProfile1DMap;
70 }
71 
72 map<TString, pair<TProfile2D*, pthread_rwlock_t*> >& Get2DProfileMap(void){
73  static map<TString, pair<TProfile2D*, pthread_rwlock_t*> > TProfile2DMap;
74  return TProfile2DMap;
75 }
76 
77 pthread_rwlock_t* InitializeMapLock(){
78  pthread_rwlock_t *thisLock = new pthread_rwlock_t();
79  pthread_rwlock_init(thisLock, NULL);
80  return thisLock;
81 }
82 
83 void Fill1DHistogram (const char * plugin, const char * directoryName, const char * name, const double value, const char * title , int nBins, double xmin, double xmax, bool print = false){
84  static pthread_rwlock_t *mapLock = InitializeMapLock();
85  TH1I * histogram;
86  pair<TH1I*, pthread_rwlock_t*> histogramPair;
87 
88  char fullNameChar[500];
89  sprintf(fullNameChar, "%s/%s/%s", plugin, directoryName, name);
90  TString fullName = TString(fullNameChar);
91 
92  try {
93  pthread_rwlock_rdlock(mapLock); // Grab the read lock
94  histogramPair = Get1DMap().at(fullName); // If the exception is caught, it bails immediately and will not release the lock
95  pthread_rwlock_unlock(mapLock);
96  }
97  catch (const std::out_of_range& oor) {
98  // Drop the read lock and grab the write lock
99  pthread_rwlock_unlock(mapLock);
100  pthread_rwlock_wrlock(mapLock);
101  // At this point, more than one thread might have made it through the try and ended up in the catch.
102  // do a single threaded (write locked) "try" again to be sure we aren't duplicating the histogram
103  try {
104  histogramPair = Get1DMap().at(fullName);
105  }
106  catch(const std::out_of_range& oor) {
107  // This now must be the first thread to get here, so we should make the histogram, fill and move on
108  if (print) std::cerr << ansi_green << plugin << " ===> Making New 1D Histogram " << fullName << ansi_normal << endl;
109  // Initialize the histogram lock
110  pthread_rwlock_t *histogramLock = new pthread_rwlock_t();
111  pthread_rwlock_init(histogramLock, NULL);
112  // Get the ROOT lock and create the histogram
113  // WARNING: Locking inside a lock is bad practice, but sometimes not easy to avoid.
114  // there would be a problem if there was another function that tried to grab the map lock
115  // inside a root lock. In this code, this will not happen.
116  japp->RootWriteLock();
117  TDirectory *homedir = gDirectory;
118  TDirectory *temp;
119  temp = gDirectory->mkdir(plugin);
120  if(temp) GetAllDirectories().push_back(temp);
121  gDirectory->cd(plugin);
122  GetAllDirectories().push_back(gDirectory->mkdir(directoryName));
123  gDirectory->cd(directoryName);
124  histogram = new TH1I( name, title, nBins, xmin, xmax);
125  histogram->Fill(value);
126  homedir->cd();
127  japp->RootUnLock();
128 
129  Get1DMap()[fullName] = make_pair(histogram, histogramLock);
130  pthread_rwlock_unlock(mapLock);
131  return;
132  }
133  // If nothing is caught, the histogram must have been created by another thread
134  // while we were waiting to grab the write lock. Drop the lock and carry on...
135  pthread_rwlock_unlock(mapLock);
136  }
137 
138  histogram = histogramPair.first;
139  pthread_rwlock_t *histogramLockPtr = histogramPair.second;
140  pthread_rwlock_wrlock(histogramLockPtr);
141  histogram->Fill(value);
142  pthread_rwlock_unlock(histogramLockPtr);
143 
144  return;
145 }
146 
147 // This overloaded function allows the creation of a 1D histogram with variable bin sizes.
148 void Fill1DHistogram (const char * plugin, const char * directoryName, const char * name, const double value, const char * title , int nBins, double *xbins) {//, bool print = false){
149  static pthread_rwlock_t *mapLock = InitializeMapLock();
150  TH1I * histogram;
151  pair<TH1I*, pthread_rwlock_t*> histogramPair;
152 
153  char fullNameChar[500];
154  sprintf(fullNameChar, "%s/%s/%s", plugin, directoryName, name);
155  TString fullName = TString(fullNameChar);
156 
157  try {
158  pthread_rwlock_rdlock(mapLock); // Grab the read lock
159  histogramPair = Get1DMap().at(fullName); // If the exception is caught, it bails immediately and will not release the lock
160  pthread_rwlock_unlock(mapLock);
161  }
162  catch (const std::out_of_range& oor) {
163  // Drop the read lock and grab the write lock
164  pthread_rwlock_unlock(mapLock);
165  pthread_rwlock_wrlock(mapLock);
166  // At this point, more than one thread might have made it through the try and ended up in the catch.
167  // do a single threaded (write locked) "try" again to be sure we aren't duplicating the histogram
168  try {
169  histogramPair = Get1DMap().at(fullName);
170  }
171  catch(const std::out_of_range& oor) {
172  // This now must be the first thread to get here, so we should make the histogram, fill and move on
173  //if (print) std::cerr << ansi_green << plugin << " ===> Making New 1D Histogram " << fullName << ansi_normal << endl;
174  // Initialize the histogram lock
175  pthread_rwlock_t *histogramLock = new pthread_rwlock_t();
176  pthread_rwlock_init(histogramLock, NULL);
177  // Get the ROOT lock and create the histogram
178  // WARNING: Locking inside a lock is bad practice, but sometimes not easy to avoid.
179  // there would be a problem if there was another function that tried to grab the map lock
180  // inside a root lock. In this code, this will not happen.
181  japp->RootWriteLock();
182  TDirectory *homedir = gDirectory;
183  TDirectory *temp;
184  temp = gDirectory->mkdir(plugin);
185  if(temp) GetAllDirectories().push_back(temp);
186  gDirectory->cd(plugin);
187  GetAllDirectories().push_back(gDirectory->mkdir(directoryName));
188  gDirectory->cd(directoryName);
189  histogram = new TH1I( name, title, nBins, xbins);
190  histogram->Fill(value);
191  homedir->cd();
192  japp->RootUnLock();
193 
194  Get1DMap()[fullName] = make_pair(histogram, histogramLock);
195  pthread_rwlock_unlock(mapLock);
196  return;
197  }
198  // If nothing is caught, the histogram must have been created by another thread
199  // while we were waiting to grab the write lock. Drop the lock and carry on...
200  pthread_rwlock_unlock(mapLock);
201  }
202 
203  histogram = histogramPair.first;
204  pthread_rwlock_t *histogramLockPtr = histogramPair.second;
205  pthread_rwlock_wrlock(histogramLockPtr);
206  histogram->Fill(value);
207  pthread_rwlock_unlock(histogramLockPtr);
208 
209  return;
210 }
211 
212 
213 
214 void Fill1DWeightedHistogram (const char * plugin, const char * directoryName, const char * name, const double value, const double weight, const char * title , int nBins, double xmin, double xmax, bool print = false){
215  static pthread_rwlock_t *mapLock = InitializeMapLock();
216  TH1D * histogram;
217  pair<TH1D*, pthread_rwlock_t*> histogramPair;
218 
219  char fullNameChar[500];
220  sprintf(fullNameChar, "%s/%s/%s", plugin, directoryName, name);
221  TString fullName = TString(fullNameChar);
222 
223  try {
224  pthread_rwlock_rdlock(mapLock); // Grab the read lock
225  histogramPair = Get1DWeightedMap().at(fullName); // If the exception is caught, it bails immediately and will not release the lock
226  pthread_rwlock_unlock(mapLock);
227  }
228  catch (const std::out_of_range& oor) {
229  // Drop the read lock and grab the write lock
230  pthread_rwlock_unlock(mapLock);
231  pthread_rwlock_wrlock(mapLock);
232  // At this point, more than one thread might have made it through the try and ended up in the catch.
233  // do a single threaded (write locked) "try" again to be sure we aren't duplicating the histogram
234  try {
235  histogramPair = Get1DWeightedMap().at(fullName);
236  }
237  catch(const std::out_of_range& oor) {
238  // This now must be the first thread to get here, so we should make the histogram, fill and move on
239  if (print) std::cerr << ansi_green << plugin << " ===> Making New 1D Weighted Histogram " << fullName << ansi_normal << endl;
240  // Initialize the histogram lock
241  pthread_rwlock_t *histogramLock = new pthread_rwlock_t();
242  pthread_rwlock_init(histogramLock, NULL);
243  // Get the ROOT lock and create the histogram
244  // WARNING: Locking inside a lock is bad practice, but sometimes not easy to avoid.
245  // there would be a problem if there was another function that tried to grab the map lock
246  // inside a root lock. In this code, this will not happen.
247  japp->RootWriteLock();
248  TDirectory *homedir = gDirectory;
249  TDirectory *temp;
250  temp = gDirectory->mkdir(plugin);
251  if(temp) GetAllDirectories().push_back(temp);
252  gDirectory->cd(plugin);
253  GetAllDirectories().push_back(gDirectory->mkdir(directoryName));
254  gDirectory->cd(directoryName);
255  histogram = new TH1D( name, title, nBins, xmin, xmax);
256  histogram->Fill(value,weight);
257  homedir->cd();
258  japp->RootUnLock();
259 
260  Get1DWeightedMap()[fullName] = make_pair(histogram, histogramLock);
261  pthread_rwlock_unlock(mapLock);
262  return;
263  }
264  // If nothing is caught, the histogram must have been created by another thread
265  // while we were waiting to grab the write lock. Drop the lock and carry on...
266  pthread_rwlock_unlock(mapLock);
267  }
268 
269  histogram = histogramPair.first;
270  pthread_rwlock_t *histogramLockPtr = histogramPair.second;
271  pthread_rwlock_wrlock(histogramLockPtr);
272  histogram->Fill(value,weight);
273  pthread_rwlock_unlock(histogramLockPtr);
274 
275  return;
276 }
277 
278 void Fill2DHistogram (const char * plugin, const char * directoryName, const char * name, const double valueX , const double valueY , const char * title , int nBinsX, double xmin, double xmax, int nBinsY, double ymin, double ymax, bool print = false){
279 
280  static pthread_rwlock_t *mapLock = InitializeMapLock();
281  TH2I * histogram;
282  pair<TH2I*, pthread_rwlock_t*> histogramPair;
283 
284  char fullNameChar[500];
285  sprintf(fullNameChar, "%s/%s/%s", plugin, directoryName, name);
286  TString fullName = TString(fullNameChar);
287 
288  try {
289  pthread_rwlock_rdlock(mapLock); // Grab the read lock
290  histogramPair = Get2DMap().at(fullName);
291  pthread_rwlock_unlock(mapLock);
292  }
293  catch (const std::out_of_range& oor) {
294  // Drop the read lock and grab the write lock
295  pthread_rwlock_unlock(mapLock);
296  pthread_rwlock_wrlock(mapLock);
297  // At this point, more than one thread might have made it through the try and ended up in the catch.
298  // do a single threaded (write locked) "try" again to be sure we aren't duplicating the histogram
299  try{
300  histogramPair = Get2DMap().at(fullName);
301  }
302  catch (const std::out_of_range& oor) {
303  if (print) std::cerr << ansi_green << plugin << " ===> Making New 2D Histogram " << name << ansi_normal << endl;
304  // Initialize the histogram lock
305  pthread_rwlock_t *histogramLock = new pthread_rwlock_t();
306  pthread_rwlock_init(histogramLock, NULL);
307 
308  // Get the ROOT lock and create the histogram
309  // WARNING: Locking inside a lock is bad practice, but sometimes not easy to avoid.
310  // there would be a problem if there was another function that tried to grab the map lock
311  // inside a root lock. In this code, this will not happen.
312  japp->RootWriteLock();
313  TDirectory *homedir = gDirectory;
314  TDirectory *temp;
315  temp = gDirectory->mkdir(plugin);
316  if(temp) GetAllDirectories().push_back(temp);
317  gDirectory->cd(plugin);
318  GetAllDirectories().push_back(gDirectory->mkdir(directoryName));
319  gDirectory->cd(directoryName);
320  histogram = new TH2I( name, title, nBinsX, xmin, xmax, nBinsY, ymin, ymax);
321  histogram->Fill(valueX, valueY);
322  homedir->cd();
323  japp->RootUnLock();
324 
325  Get2DMap()[fullName] = make_pair(histogram,histogramLock);
326  pthread_rwlock_unlock(mapLock);
327  return;
328  }
329  // If nothing is caught, the histogram must have been created by another thread
330  // while we were waiting to grab the write lock. Drop the lock and carry on...
331  pthread_rwlock_unlock(mapLock);
332  }
333 
334  histogram = histogramPair.first;
335  pthread_rwlock_t *histogramLockPtr = histogramPair.second;
336  pthread_rwlock_wrlock(histogramLockPtr);
337  histogram->Fill(valueX, valueY);
338  pthread_rwlock_unlock(histogramLockPtr);
339 
340  return;
341 }
342 
343 // This overloaded function allows the creation of a 2D histogram with variable bin sizes.
344 void Fill2DHistogram (const char * plugin, const char * directoryName, const char * name, const double valueX , const double valueY , const char * title , int nBinsX, double *xbins, int nBinsY, double *ybins, bool print = false){
345 
346  static pthread_rwlock_t *mapLock = InitializeMapLock();
347  TH2I * histogram;
348  pair<TH2I*, pthread_rwlock_t*> histogramPair;
349 
350  char fullNameChar[500];
351  sprintf(fullNameChar, "%s/%s/%s", plugin, directoryName, name);
352  TString fullName = TString(fullNameChar);
353 
354  try {
355  pthread_rwlock_rdlock(mapLock); // Grab the read lock
356  histogramPair = Get2DMap().at(fullName);
357  pthread_rwlock_unlock(mapLock);
358  }
359  catch (const std::out_of_range& oor) {
360  // Drop the read lock and grab the write lock
361  pthread_rwlock_unlock(mapLock);
362  pthread_rwlock_wrlock(mapLock);
363  // At this point, more than one thread might have made it through the try and ended up in the catch.
364  // do a single threaded (write locked) "try" again to be sure we aren't duplicating the histogram
365  try{
366  histogramPair = Get2DMap().at(fullName);
367  }
368  catch (const std::out_of_range& oor) {
369  if (print) std::cerr << ansi_green << plugin << " ===> Making New 2D Histogram " << name << ansi_normal << endl;
370  // Initialize the histogram lock
371  pthread_rwlock_t *histogramLock = new pthread_rwlock_t();
372  pthread_rwlock_init(histogramLock, NULL);
373 
374  // Get the ROOT lock and create the histogram
375  // WARNING: Locking inside a lock is bad practice, but sometimes not easy to avoid.
376  // there would be a problem if there was another function that tried to grab the map lock
377  // inside a root lock. In this code, this will not happen.
378  japp->RootWriteLock();
379  TDirectory *homedir = gDirectory;
380  TDirectory *temp;
381  temp = gDirectory->mkdir(plugin);
382  if(temp) GetAllDirectories().push_back(temp);
383  gDirectory->cd(plugin);
384  GetAllDirectories().push_back(gDirectory->mkdir(directoryName));
385  gDirectory->cd(directoryName);
386  histogram = new TH2I( name, title, nBinsX, xbins, nBinsY, ybins);
387  histogram->Fill(valueX, valueY);
388  homedir->cd();
389  japp->RootUnLock();
390 
391  Get2DMap()[fullName] = make_pair(histogram,histogramLock);
392  pthread_rwlock_unlock(mapLock);
393  return;
394  }
395  // If nothing is caught, the histogram must have been created by another thread
396  // while we were waiting to grab the write lock. Drop the lock and carry on...
397  pthread_rwlock_unlock(mapLock);
398  }
399 
400  histogram = histogramPair.first;
401  pthread_rwlock_t *histogramLockPtr = histogramPair.second;
402  pthread_rwlock_wrlock(histogramLockPtr);
403  histogram->Fill(valueX, valueY);
404  pthread_rwlock_unlock(histogramLockPtr);
405 
406  return;
407 }
408 
409 void Fill2DWeightedHistogram (const char * plugin, const char * directoryName, const char * name, const double valueX , const double valueY , const double weight , const char * title , int nBinsX, double xmin, double xmax, int nBinsY, double ymin, double ymax, bool print = false){
410 
411  static pthread_rwlock_t *mapLock = InitializeMapLock();
412  TH2D * histogram;
413  pair<TH2D*, pthread_rwlock_t*> histogramPair;
414 
415  char fullNameChar[500];
416  sprintf(fullNameChar, "%s/%s/%s", plugin, directoryName, name);
417  TString fullName = TString(fullNameChar);
418 
419  try {
420  pthread_rwlock_rdlock(mapLock); // Grab the read lock
421  histogramPair = Get2DWeightedMap().at(fullName);
422  pthread_rwlock_unlock(mapLock);
423  }
424  catch (const std::out_of_range& oor) {
425  // Drop the read lock and grab the write lock
426  pthread_rwlock_unlock(mapLock);
427  pthread_rwlock_wrlock(mapLock);
428  // At this point, more than one thread might have made it through the try and ended up in the catch.
429  // do a single threaded (write locked) "try" again to be sure we aren't duplicating the histogram
430  try{
431  histogramPair = Get2DWeightedMap().at(fullName);
432  }
433  catch (const std::out_of_range& oor) {
434  if (print) std::cerr << ansi_green << plugin << " ===> Making New 2D Histogram " << name << ansi_normal << endl;
435  // Initialize the histogram lock
436  pthread_rwlock_t *histogramLock = new pthread_rwlock_t();
437  pthread_rwlock_init(histogramLock, NULL);
438 
439  // Get the ROOT lock and create the histogram
440  // WARNING: Locking inside a lock is bad practice, but sometimes not easy to avoid.
441  // there would be a problem if there was another function that tried to grab the map lock
442  // inside a root lock. In this code, this will not happen.
443  japp->RootWriteLock();
444  TDirectory *homedir = gDirectory;
445  TDirectory *temp;
446  temp = gDirectory->mkdir(plugin);
447  if(temp) GetAllDirectories().push_back(temp);
448  gDirectory->cd(plugin);
449  GetAllDirectories().push_back(gDirectory->mkdir(directoryName));
450  gDirectory->cd(directoryName);
451  histogram = new TH2D( name, title, nBinsX, xmin, xmax, nBinsY, ymin, ymax);
452  histogram->Fill(valueX, valueY, weight);
453  homedir->cd();
454  japp->RootUnLock();
455 
456  Get2DWeightedMap()[fullName] = make_pair(histogram,histogramLock);
457  pthread_rwlock_unlock(mapLock);
458  return;
459  }
460  // If nothing is caught, the histogram must have been created by another thread
461  // while we were waiting to grab the write lock. Drop the lock and carry on...
462  pthread_rwlock_unlock(mapLock);
463  }
464 
465  histogram = histogramPair.first;
466  pthread_rwlock_t *histogramLockPtr = histogramPair.second;
467  pthread_rwlock_wrlock(histogramLockPtr);
468  histogram->Fill(valueX, valueY, weight);
469  pthread_rwlock_unlock(histogramLockPtr);
470 
471  return;
472 }
473 
474 void Fill3DHistogram (const char * plugin, const char * directoryName, const char * name, const double valueX , const double valueY , const double valueZ , const char * title , int nBinsX, double xmin, double xmax, int nBinsY, double ymin, double ymax, int nBinsZ, double zmin, double zmax, bool print = false){
475 
476  static pthread_rwlock_t *mapLock = InitializeMapLock();
477  TH3I * histogram;
478  pair<TH3I*, pthread_rwlock_t*> histogramPair;
479 
480  char fullNameChar[500];
481  sprintf(fullNameChar, "%s/%s/%s", plugin, directoryName, name);
482  TString fullName = TString(fullNameChar);
483 
484  try {
485  pthread_rwlock_rdlock(mapLock); // Grab the read lock
486  histogramPair = Get3DMap().at(fullName);
487  pthread_rwlock_unlock(mapLock);
488  }
489  catch (const std::out_of_range& oor) {
490  // Drop the read lock and grab the write lock
491  pthread_rwlock_unlock(mapLock);
492  pthread_rwlock_wrlock(mapLock);
493  // At this point, more than one thread might have made it through the try and ended up in the catch.
494  // do a single threaded (write locked) "try" again to be sure we aren't duplicating the histogram
495  try{
496  histogramPair = Get3DMap().at(fullName);
497  }
498  catch (const std::out_of_range& oor) {
499  if (print) std::cerr << ansi_green << plugin << " ===> Making New 3D Histogram " << name << ansi_normal << endl;
500  // Initialize the histogram lock
501  pthread_rwlock_t *histogramLock = new pthread_rwlock_t();
502  pthread_rwlock_init(histogramLock, NULL);
503 
504  // Get the ROOT lock and create the histogram
505  // WARNING: Locking inside a lock is bad practice, but sometimes not easy to avoid.
506  // there would be a problem if there was another function that tried to grab the map lock
507  // inside a root lock. In this code, this will not happen.
508  japp->RootWriteLock();
509  TDirectory *homedir = gDirectory;
510  TDirectory *temp;
511  temp = gDirectory->mkdir(plugin);
512  if(temp) GetAllDirectories().push_back(temp);
513  gDirectory->cd(plugin);
514  GetAllDirectories().push_back(gDirectory->mkdir(directoryName));
515  gDirectory->cd(directoryName);
516  histogram = new TH3I( name, title, nBinsX, xmin, xmax, nBinsY, ymin, ymax, nBinsZ, zmin, zmax);
517  histogram->Fill(valueX, valueY, valueZ);
518  homedir->cd();
519  japp->RootUnLock();
520 
521  Get3DMap()[fullName] = make_pair(histogram,histogramLock);
522  pthread_rwlock_unlock(mapLock);
523  return;
524  }
525  // If nothing is caught, the histogram must have been created by another thread
526  // while we were waiting to grab the write lock. Drop the lock and carry on...
527  pthread_rwlock_unlock(mapLock);
528  }
529 
530  histogram = histogramPair.first;
531  pthread_rwlock_t *histogramLockPtr = histogramPair.second;
532  pthread_rwlock_wrlock(histogramLockPtr);
533  histogram->Fill(valueX, valueY, valueZ);
534  pthread_rwlock_unlock(histogramLockPtr);
535 
536  return;
537 }
538 
539 
540 
541 void Fill1DProfile (const char * plugin, const char * directoryName, const char * name, const double valueX , const double valueY , const char * title , int nBinsX, double xmin, double xmax, bool print = false){
542 
543  static pthread_rwlock_t *mapLock = InitializeMapLock();
544  TProfile * profile;
545  pair<TProfile*, pthread_rwlock_t*> profilePair;
546 
547  char fullNameChar[500];
548  sprintf(fullNameChar, "%s/%s/%s", plugin, directoryName, name);
549  TString fullName = TString(fullNameChar);
550  try {
551  pthread_rwlock_rdlock(mapLock); // Grab the read lock
552  profilePair = Get1DProfileMap().at(fullName);
553  pthread_rwlock_unlock(mapLock);
554  }
555  catch (const std::out_of_range& oor) {
556  // Drop the read lock and grab the write lock
557  pthread_rwlock_unlock(mapLock);
558  pthread_rwlock_wrlock(mapLock);
559  // At this point, more than one thread might have made it through the try and ended up in the catch.
560  // do a single threaded (write locked) "try" again to be sure we aren't duplicating the histogram
561  try{
562  profilePair = Get1DProfileMap().at(fullName);
563  }
564  catch (const std::out_of_range& oor) {
565  if (print) std::cerr << ansi_green << plugin << " ===> Making New 1D Profile " << name << ansi_normal << endl;
566  // Initialize the profile lock
567  pthread_rwlock_t *profileLock = new pthread_rwlock_t();
568  pthread_rwlock_init(profileLock, NULL);
569 
570  // Get the ROOT lock and create the histogram
571  // WARNING: Locking inside a lock is bad practice, but sometimes not easy to avoid.
572  // there would be a problem if there was another function that tried to grab the map lock
573  // inside a root lock. In this code, this will not happen.
574  japp->RootWriteLock();// Get the ROOT lock and create the histogram
575  TDirectory *homedir = gDirectory;
576  TDirectory *temp;
577  temp = gDirectory->mkdir(plugin);
578  if(temp) GetAllDirectories().push_back(temp);
579  gDirectory->cd(plugin);
580  GetAllDirectories().push_back(gDirectory->mkdir(directoryName));
581  gDirectory->cd(directoryName);
582  profile = new TProfile( name, title, nBinsX, xmin, xmax);
583  profile->Fill(valueX, valueY);
584  homedir->cd();
585  japp->RootUnLock();
586 
587  Get1DProfileMap()[fullName] = make_pair(profile,profileLock);
588  pthread_rwlock_unlock(mapLock);
589  return;
590  }
591  // If nothing is caught, the histogram must have been created by another thread
592  // while we were waiting to grab the write lock. Drop the lock and carry on...
593  pthread_rwlock_unlock(mapLock);
594  }
595 
596  profile = profilePair.first;
597  pthread_rwlock_t *profileLockPtr = profilePair.second;
598  pthread_rwlock_wrlock(profileLockPtr);
599  profile->Fill(valueX, valueY);
600  pthread_rwlock_unlock(profileLockPtr);
601 
602  return;
603 }
604 
605 void Fill2DProfile (const char * plugin, const char * directoryName, const char * name, const double valueX , const double valueY , const double valueZ, const char * title , int nBinsX, double xmin, double xmax, int nBinsY, double ymin, double ymax, bool print = false){
606  static pthread_rwlock_t *mapLock = InitializeMapLock();
607  TProfile2D * profile;
608  pair<TProfile2D*, pthread_rwlock_t*> profilePair;
609 
610  char fullNameChar[500];
611  sprintf(fullNameChar, "%s/%s/%s", plugin, directoryName, name);
612  TString fullName = TString(fullNameChar);
613  try {
614  pthread_rwlock_rdlock(mapLock); // Grab the read lock
615  profilePair = Get2DProfileMap().at(fullName);
616  pthread_rwlock_unlock(mapLock);
617  }
618  catch (const std::out_of_range& oor) {
619  // Drop the read lock and grab the write lock
620  pthread_rwlock_unlock(mapLock);
621  pthread_rwlock_wrlock(mapLock);
622  // At this point, more than one thread might have made it through the try and ended up in the catch.
623  // do a single threaded (write locked) "try" again to be sure we aren't duplicating the histogram
624  try{
625  profilePair = Get2DProfileMap().at(fullName);
626  }
627  catch (const std::out_of_range& oor) {
628  if (print) std::cerr << ansi_green << plugin << " ===> Making New 2D Profile " << name << ansi_normal << endl;
629  // Initialize the profile lock
630  pthread_rwlock_t *profileLock = new pthread_rwlock_t();
631  pthread_rwlock_init(profileLock, NULL);
632 
633  // Get the ROOT lock and create the histogram
634  // WARNING: Locking inside a lock is bad practice, but sometimes not easy to avoid.
635  // there would be a problem if there was another function that tried to grab the map lock
636  // inside a root lock. In this code, this will not happen.
637  japp->RootWriteLock();
638  TDirectory *homedir = gDirectory;
639  TDirectory *temp;
640  temp = gDirectory->mkdir(plugin);
641  if(temp) GetAllDirectories().push_back(temp);
642  gDirectory->cd(plugin);
643  GetAllDirectories().push_back(gDirectory->mkdir(directoryName));
644  gDirectory->cd(directoryName);
645  profile = new TProfile2D( name, title, nBinsX, xmin, xmax, nBinsY, ymin, ymax);
646  profile->Fill(valueX, valueY, valueZ);
647  homedir->cd();
648  japp->RootUnLock();
649 
650  Get2DProfileMap()[fullName] = make_pair(profile, profileLock);
651  pthread_rwlock_unlock(mapLock);
652  return;
653  }
654  // If nothing is caught, the histogram must have been created by another thread
655  // while we were waiting to grab the write lock. Drop the lock and carry on...
656  pthread_rwlock_unlock(mapLock);
657  }
658 
659  profile = profilePair.first;
660  pthread_rwlock_t *profileLockPtr = profilePair.second;
661  pthread_rwlock_wrlock(profileLockPtr);
662  profile->Fill(valueX, valueY, valueZ);
663  pthread_rwlock_unlock(profileLockPtr);
664 
665  return;
666 }
667 
669  japp->RootWriteLock();
670  for (unsigned int i=0; i < GetAllDirectories().size(); i++){
671  if (GetAllDirectories()[i] == 0) continue;
672  GetAllDirectories()[i]->GetList()->Sort();
673  }
674  japp->RootUnLock();
675 }
676 
677 TObject* GetHistPointer(const char * plugin, const char * directoryName, const char * name){
678 
679  // This method does not take into account thread safety and should only be called from the fini() method!!!!
680  char fullNameChar[500];
681  sprintf(fullNameChar, "%s/%s/%s", plugin, directoryName, name);
682  TString fullName = TString(fullNameChar);
683 
684  auto iter1I = Get1DMap().find(fullName);
685  if(iter1I != Get1DMap().end()) return (TObject*) (*iter1I).second.first;
686 
687  auto iter1D = Get1DWeightedMap().find(fullName);
688  if(iter1D != Get1DWeightedMap().end()) return (TObject*) (*iter1D).second.first;
689 
690  auto iter1P = Get1DProfileMap().find(fullName);
691  if(iter1P != Get1DProfileMap().end()) return (TObject*) (*iter1P).second.first;
692 
693  auto iter2I = Get2DMap().find(fullName);
694  if(iter2I != Get2DMap().end()) return (TObject*) (*iter2I).second.first;
695 
696  auto iter2D = Get2DWeightedMap().find(fullName);
697  if(iter2D != Get2DWeightedMap().end()) return (TObject*) (*iter2D).second.first;
698 
699  auto iter2P = Get2DProfileMap().find(fullName);
700  if(iter2P != Get2DProfileMap().end()) return (TObject*) (*iter2P).second.first;
701 
702  auto iter3I = Get3DMap().find(fullName);
703  if(iter3I != Get3DMap().end()) return (TObject*) (*iter3I).second.first;
704 
705  jout << "Unable to find histogram " << fullName.Data() << endl;
706  return nullptr;
707 
708 }
709 
710 #endif
void Fill1DProfile(const char *plugin, const char *directoryName, const char *name, const double valueX, const double valueY, const char *title, int nBinsX, double xmin, double xmax, bool print=false)
TObject * GetHistPointer(const char *plugin, const char *directoryName, const char *name)
map< TString, pair< TH1I *, pthread_rwlock_t * > > & Get1DMap(void)
map< TString, pair< TH3I *, pthread_rwlock_t * > > & Get3DMap(void)
sprintf(text,"Post KinFit Cut")
map< TString, pair< TH1D *, pthread_rwlock_t * > > & Get1DWeightedMap(void)
void Fill1DWeightedHistogram(const char *plugin, const char *directoryName, const char *name, const double value, const double weight, const char *title, int nBins, double xmin, double xmax, bool print=false)
double zmax
pthread_rwlock_t * InitializeMapLock()
map< TString, pair< TH2D *, pthread_rwlock_t * > > & Get2DWeightedMap(void)
JApplication * japp
void Fill2DWeightedHistogram(const char *plugin, const char *directoryName, const char *name, const double valueX, const double valueY, const double weight, const char *title, int nBinsX, double xmin, double xmax, int nBinsY, double ymin, double ymax, bool print=false)
void SortDirectories()
map< TString, pair< TProfile2D *, pthread_rwlock_t * > > & Get2DProfileMap(void)
void Fill1DHistogram(const char *plugin, const char *directoryName, const char *name, const double value, const char *title, int nBins, double xmin, double xmax, bool print=false)
void Fill2DHistogram(const char *plugin, const char *directoryName, const char *name, const double valueX, const double valueY, const char *title, int nBinsX, double xmin, double xmax, int nBinsY, double ymin, double ymax, bool print=false)
map< TString, pair< TProfile *, pthread_rwlock_t * > > & Get1DProfileMap(void)
void Fill3DHistogram(const char *plugin, const char *directoryName, const char *name, const double valueX, const double valueY, const double valueZ, const char *title, int nBinsX, double xmin, double xmax, int nBinsY, double ymin, double ymax, int nBinsZ, double zmin, double zmax, bool print=false)
map< TString, pair< TH2I *, pthread_rwlock_t * > > & Get2DMap(void)
#define ansi_green
Double_t ymin
Definition: bcal_hist_eff.C:89
Double_t ymax
Definition: bcal_hist_eff.C:91
#define ansi_normal
void Fill2DProfile(const char *plugin, const char *directoryName, const char *name, const double valueX, const double valueY, const double valueZ, const char *title, int nBinsX, double xmin, double xmax, int nBinsY, double ymin, double ymax, bool print=false)
double zmin
vector< TDirectory * > & GetAllDirectories(void)
TH2F * temp