StRoot  1
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Groups Pages
StMultiH1F.cxx
1 // //
3 // StMultiH1F allows multiple similar TH1F histograms to be //
4 // easily plotted on one graph //
5 // //
7 
8 #ifdef __HP_aCC
9 #include <Stiostream.h>
10 #else
11 #include "Stiostream.h"
12 #endif
13 #include "StMultiH1F.h"
14 #include "TString.h"
15 #include "TLegend.h"
16 #include "TPad.h"
17 #include "TDirectory.h"
18 #include "TMath.h"
19 ClassImp(StMultiH1F)
20 
21 StMultiH1F::StMultiH1F() : fMOffset(0.), subHists(0), aHist(0) {}
22 
23 StMultiH1F::StMultiH1F(const char *name,const char *title,Int_t nbinsx,
24  Axis_t xlow,Axis_t xup ,Int_t nbinsy) :
25  TH2F(name,title,nbinsx,xlow,xup,nbinsy,-0.5,-0.5+nbinsy),
26  fMOffset(0.), subHists(0), aHist(0) {}
27 
28 StMultiH1F::StMultiH1F(const char *name,const char *title,Int_t nbinsx,
29  Double_t *xbins,Int_t nbinsy) :
30  TH2F(name,title,nbinsx,xbins,nbinsy,-0.5,-0.5+nbinsy),
31  fMOffset(0.), subHists(0), aHist(0) {}
32 
33 StMultiH1F::~StMultiH1F() {
34  if (subHists) {
35  int ybins = TMath::Min(GetNbinsY(),StMultiH1FMaxBins);
36  for (int ybin=0; ybin<ybins; ybin++) delete subHists[ybin];
37  }
38 }
39 
40 void StMultiH1F::Draw(Option_t *option) {
41 
42  int x0 = fXaxis.GetFirst();
43  int x1 = fXaxis.GetLast();
44  fXaxis.SetRange();
45  int ybins = TMath::Min(GetNbinsY(),StMultiH1FMaxBins);
46 
47  // dummy histogram pointer(s)
48  if (!subHists) { subHists = new TH1F*[ybins]; memset(subHists,0,ybins*sizeof(TH1F*)); }
49 
50  if (ybins == 1) {
51  delete subHists[0];
52  subHists[0] = XProjection(GetName());
53  subHists[0]->SetStats((!TestBit(kNoStats)));
54  TAxis* taxis = subHists[0]->GetXaxis();
55  fXaxis.Copy(*taxis);
56  taxis->SetRange(x0,x1);
57  fXaxis.SetRange(x0,x1);
58  if (fMinimum != -1111) subHists[0]->SetMinimum(fMinimum);
59  if (fMaximum != -1111) subHists[0]->SetMaximum(fMaximum);
60  subHists[0]->Draw();
61  return;
62  }
63 
64  // overlay the y bins of the 2d histogram into a 1d histogram
65  // using different line styles
66 
67  // make a legend
68  TLegend *legend = new TLegend(0.80,0.84,0.98,0.98,"Legend","NDC");
69  legend->SetFillColor(0);
70  legend->SetFillStyle(0);
71  legend->SetMargin(0.25);
72 
73  int ybin;
74  double maxval = -1e31;
75  double minval = 1e31;
76  int maxbin = -1;
77  int minbin = -1;
78  float offset = fMOffset;
79  if (fMOffset && gPad->GetLogy()) {
80  float max_offset = TMath::Power(
81  1.0e10*GetNonZeroMinimum()/GetNonZeroMaximum(),
82  1.0/(ybins-1.0));
83  if (offset > max_offset) offset = max_offset;
84  }
85 
86  TString n0;
87  for (ybin=0; ybin<ybins; ybin++) {
88  if (names[ybin].IsNull()) n0 = GetName();
89  else n0 = names[ybin];
90  int slice = ybin+1;
91  delete subHists[ybin];
92  subHists[ybin] = XProjection(n0.Data(),slice);
93  subHists[ybin]->SetLineStyle(slice);
94  subHists[ybin]->SetStats(kFALSE);
95  TAxis* taxis = subHists[ybin]->GetXaxis();
96  fXaxis.Copy(*taxis);
97  taxis->SetRange(x0,x1);
98 
99  if (fMOffset && ybin) {
100  subHists[ybin]->SetLineColor(slice);
101  if (gPad->GetLogy()) {
102  subHists[ybin]->Scale(TMath::Power(offset,ybin));
103  } else {
104  for (int xbin=0; xbin<GetNbinsX(); xbin++)
105  subHists[ybin]->AddBinContent(xbin,offset*ybin);
106  }
107  }
108 
109  double binmax = subHists[ybin]->GetMaximum();
110  double binmin = subHists[ybin]->GetMinimum();
111  if (binmax > maxval) { maxval = binmax; maxbin = ybin; }
112  if (binmin < minval) { minval = binmin; minbin = ybin; }
113  legend->AddEntry(subHists[ybin],n0.Data(),"l");
114  }
115 
116  // can't use the option argument in Draw() since this is called from
117  // StHistUtil::DrawHists(), which defaults 2D histograms to a box plot
118  if (maxbin == minbin) {
119  if (fMinimum != -1111) subHists[maxbin]->SetMinimum(fMinimum);
120  if (fMaximum != -1111) subHists[maxbin]->SetMaximum(fMaximum);
121  subHists[maxbin]->Draw();
122  } else {
123  delete aHist;
124  aHist = new TH1F(*(subHists[maxbin]));
125  aHist->SetName(Form("%s_%d",GetName(),ybins+1));
126  aHist->SetBinContent(1,maxval);
127  aHist->SetBinContent(2,minval);
128  aHist->SetMarkerStyle(1); aHist->SetMarkerColor(0);
129  if (fMinimum != -1111) aHist->SetMinimum(fMinimum);
130  if (fMaximum != -1111) aHist->SetMaximum(fMaximum);
131  aHist->Draw("p");
132  maxbin = -1;
133  }
134  for (ybin=0; ybin<ybins; ybin++) {
135  if (ybin != maxbin) subHists[ybin]->Draw("same");
136  }
137 
138  // Draw statistics for full set if stats are turned on
139  if (!TestBit(kNoStats)) {
140  subHists[0] = XProjection(GetName());
141  subHists[0]->SetEntries(GetEntries());
142  subHists[0]->SetStats(kTRUE);
143  subHists[0]->Draw("boxsames");
144  legend->SetX1(0.59);
145  legend->SetX2(0.77);
146  }
147 
148  legend->Draw();
149 
150  fXaxis.SetRange(x0,x1);
151 }
152 
153 TH1F* StMultiH1F::XProjection(const char* name, Int_t ybin) {
154  static char buf[256];
155  if (ybin<0) sprintf(buf,"%s.",name);
156  else sprintf(buf,"%s_%d_%s",GetName(),ybin,name);
157 
158  TList* tgList = gDirectory->GetList();
159  TH1F* temp = (TH1F*) tgList->FindObject(buf);
160  if (temp) tgList->Remove(temp);
161 
162  if (ybin<0) temp = (TH1F*) ProjectionX(buf);
163  else temp = (TH1F*) ProjectionX(buf,ybin,ybin);
164  TAttLine::Copy(*temp);
165  TAttFill::Copy(*temp);
166  TAttMarker::Copy(*temp);
167  return temp; // up to the user of this function to delete
168 }
169 
170 void StMultiH1F::SetBarOffset(Float_t offset) {
171  if (offset == 0.25) {
172  fMOffset = 1.2 * (GetMaximum() - GetMinimum());
173  if (!fMOffset) fMOffset = 10.0;
174  } else {
175  fMOffset = offset;
176  }
177 }
178 
179 Double_t StMultiH1F::GetNonZeroMinimum() const {
180  Double_t value, minimum = GetMinimum();
181  if (minimum) return minimum;
182  minimum = GetMaximum();
183  int bin, binx, biny, binz;
184  int xfirst = fXaxis.GetFirst();
185  int xlast = fXaxis.GetLast();
186  int yfirst = fYaxis.GetFirst();
187  int ylast = TMath::Min(fYaxis.GetLast(),StMultiH1FMaxBins);
188  int zfirst = fZaxis.GetFirst();
189  int zlast = fZaxis.GetLast();
190  for (binz=zfirst;binz<=zlast;binz++) {
191  for (biny=yfirst;biny<=ylast;biny++) {
192  for (binx=xfirst;binx<=xlast;binx++) {
193  bin = GetBin(binx,biny,binz);
194  value = GetBinContent(bin);
195  if (value && value < minimum) minimum = value;
196  }
197  }
198  }
199  if (!minimum) minimum = -1.0;
200  return minimum;
201 }
202 
203 Double_t StMultiH1F::GetNonZeroMaximum() const {
204  Double_t value, maximum = GetMaximum();
205  if (maximum) return maximum;
206  maximum = GetMinimum();
207  int bin, binx, biny, binz;
208  int xfirst = fXaxis.GetFirst();
209  int xlast = fXaxis.GetLast();
210  int yfirst = fYaxis.GetFirst();
211  int ylast = TMath::Min(fYaxis.GetLast(),StMultiH1FMaxBins);
212  int zfirst = fZaxis.GetFirst();
213  int zlast = fZaxis.GetLast();
214  for (binz=zfirst;binz<=zlast;binz++) {
215  for (biny=yfirst;biny<=ylast;biny++) {
216  for (binx=xfirst;binx<=xlast;binx++) {
217  bin = GetBin(binx,biny,binz);
218  value = GetBinContent(bin);
219  if (value && value > maximum) maximum = value;
220  }
221  }
222  }
223  if (!maximum) maximum = -1.0;
224  return maximum;
225 }
226 
227 void StMultiH1F::SavePrimitive(ostream& out, Option_t* option) {
228  // Save primitive as a C++ statement(s) on output stream out
229 
230  bool nonEqiX = kFALSE;
231  int i;
232 
233  // Check if the histogram has equidistant X bins or not. If not, we
234  // create an array holding the bins.
235  if (GetXaxis()->GetXbins()->fN && GetXaxis()->GetXbins()->fArray) {
236  nonEqiX = kTRUE;
237  out << " Double_t xAxis[" << GetXaxis()->GetXbins()->fN
238  << "] = {";
239  for (i = 0; i < GetXaxis()->GetXbins()->fN; i++) {
240  if (i != 0) out << ", ";
241  out << GetXaxis()->GetXbins()->fArray[i];
242  }
243  out << "}; " << endl;
244  }
245 
246  char quote = '"';
247  out <<" "<<endl;
248  out <<" TH1 *" << GetName() << " = new " << ClassName() << "("
249  << quote << GetName() << quote << "," << quote << GetTitle() << quote
250  << "," << GetXaxis()->GetNbins();
251  if (nonEqiX)
252  out << ", xAxis";
253  else
254  out << "," << GetXaxis()->GetXmin()
255  << "," << GetXaxis()->GetXmax();
256  out << "," << GetYaxis()->GetNbins() << ");" << endl;
257 
258  // save bin contents
259  int bin;
260  for (bin=0;bin<fNcells;bin++) {
261  double bc = GetBinContent(bin);
262  if (bc) {
263  out<<" "<<GetName()<<"->SetBinContent("<<bin<<","<<bc<<");"<<endl;
264  }
265  }
266 
267  // save bin errors
268  if (fSumw2.fN) {
269  for (bin=0;bin<fNcells;bin++) {
270  double be = GetBinError(bin);
271  if (be) {
272  out <<" "<<GetName()<<"->SetBinError("<<bin<<","<<be<<");"<<endl;
273  }
274  }
275  }
276 
277  for (bin=0;bin<GetYaxis()->GetNbins();bin++) {
278  if (!(names[bin].IsNull()))
279  out <<" "<<GetName()<< "->Rebin(" << bin << ","
280  << quote << names[bin] << quote << ");" << endl;
281  }
282  if (fMOffset != 0)
283  out <<" "<<GetName()<< "->SetBarOffset(" << fMOffset << ");" << endl;
284 
285  TH1::SavePrimitiveHelp(out, option);
286 }
287 
288 
289 Int_t StMultiH1F::Write(const char *name, Int_t option, Int_t bufsize)
290 {
291  int ybins = TMath::Min(GetNbinsY(),StMultiH1FMaxBins);
292 
293  for (int ybin=0; ybin<ybins; ybin++)
294  {
295  TString projection_name( names[ybin].IsNull() ? GetName() : names[ybin].Data() );
296  XProjection(projection_name.Data(), ybin+1)->Write();
297  }
298 
299  return TH2F::Write();
300 }
301 
302 // $Id: StMultiH1F.cxx,v 1.18 2018/05/03 16:04:58 smirnovd Exp $
303 // $Log: StMultiH1F.cxx,v $
304 // Revision 1.18 2018/05/03 16:04:58 smirnovd
305 // Override Write() to save sub histograms in StMultiH1F
306 //
307 // Revision 1.17 2016/05/27 18:02:41 genevb
308 // Garbage collection (Coverity), remove unnecessary ROOT types
309 //
310 // Revision 1.16 2015/05/26 15:40:30 genevb
311 // Handle set min/maxima
312 //
313 // Revision 1.15 2013/11/21 22:22:47 genevb
314 // Protect against array out-of-bounds, use inherited axis handles
315 //
316 // Revision 1.14 2008/07/10 21:26:59 genevb
317 // Allow SavePrimitive of fully drawn TPad to work properly
318 //
319 // Revision 1.13 2008/07/09 20:52:38 genevb
320 // Implement SavePrimitive functions
321 //
322 // Revision 1.12 2007/07/12 20:26:03 fisyak
323 // Add includes for ROOT 5.16
324 //
325 // Revision 1.11 2007/04/24 17:45:32 genevb
326 // Patched for problems with limited axis ranges
327 //
328 // Revision 1.10 2007/04/06 20:05:30 genevb
329 // Allow for lower minima
330 //
331 // Revision 1.9 2003/09/02 17:59:20 perev
332 // gcc 3.2 updates + WarnOff
333 //
334 // Revision 1.8 2003/01/21 18:33:27 genevb
335 // Better handling of temporary hists
336 //
337 // Revision 1.7 2002/04/23 01:59:16 genevb
338 // New offset abilities
339 //
340 // Revision 1.6 2000/09/15 21:23:36 fisyak
341 // HP does not have iostream
342 //
343 // Revision 1.5 2000/08/28 19:21:05 genevb
344 // Improved projection code
345 //
346 // Revision 1.4 2000/08/28 18:47:50 genevb
347 // Better handling of 1 y-bin case
348 //
349 // Revision 1.3 2000/08/25 22:03:39 genevb
350 // Fixed entries problem
351 //
352 // Revision 1.2 2000/08/25 15:46:42 genevb
353 // Added stats box, legend names
354 //
355 // Revision 1.1 2000/07/26 22:00:27 lansdell
356 // new multi-hist class for superimposing the x-projections of y-bins (of a TH2F histogram) into one TH1F histogram
357 //
358 
virtual Int_t Write(const char *name=0, Int_t option=0, Int_t bufsize=0)
Saves subhistograms (TH1F) along with this composite object.
Definition: StMultiH1F.cxx:289