1 ////////////////////////////////////////////////////////////////////////// 2 // // 3 // StMultiH2F allows multiple similar TH2F histograms to be // 4 // easily plotted on one graph // 5 // // 6 ////////////////////////////////////////////////////////////////////////// 7 8 #ifdef __HP_aCC 9 #include <Stiostream.h> 10 #else 11 #include "Stiostream.h" 12 #endif 13 #include "StMultiH2F.h" 14 #include "TString.h" 15 #include "TLegend.h" 16 #include "TPad.h" 17 #include "TDirectory.h" 18 19 ClassImp(StMultiH2F) 20 21 StMultiH2F::StMultiH2F() : subHists(0) {} 22 23 StMultiH2F::StMultiH2F(const char *name,const char *title,Int_t nbinsx, 24 Axis_t xlow,Axis_t xup,Int_t nbinsy,Axis_t ylow, 25 Axis_t yup,Int_t nbinsz) : 26 TH3F(name,title,nbinsx,xlow,xup,nbinsy,ylow,yup,nbinsz,-0.5,-0.5+nbinsz), 27 subHists(0) {} 28 29 StMultiH2F::~StMultiH2F() { 30 if (subHists) { 31 int zbins = TMath::Min(GetNbinsZ(),StMultiH2FMaxBins); 32 for (int zbin=0; zbin<zbins; zbin++) delete subHists[zbin]; 33 } 34 } 35 36 void StMultiH2F::Draw(Option_t *option) { 37 // Probably only the "box" and "cont" options are reasonable here 38 39 int x0 = fXaxis.GetFirst(); 40 int x1 = fXaxis.GetLast(); 41 int y0 = fYaxis.GetFirst(); 42 int y1 = fYaxis.GetLast(); 43 fXaxis.SetRange(); 44 fYaxis.SetRange(); 45 int zbins = TMath::Min(GetNbinsZ(),StMultiH2FMaxBins); 46 47 // dummy histogram pointer(s) 48 if (!subHists) { subHists = new TH2D*[zbins]; memset(subHists,0,zbins*sizeof(TH2D*)); } 49 50 if (zbins == 1) { 51 delete subHists[0]; 52 subHists[0] = XYProjection(GetName()); 53 subHists[0]->SetStats((!TestBit(kNoStats))); 54 TAxis* taxisX = subHists[0]->GetXaxis(); 55 TAxis* taxisY = subHists[0]->GetYaxis(); 56 fXaxis.Copy(*taxisX); 57 fYaxis.Copy(*taxisY); 58 taxisX->SetRange(x0,x1); 59 taxisY->SetRange(y0,y1); 60 fXaxis.SetRange(x0,x1); 61 fYaxis.SetRange(y0,y1); 62 subHists[0]->Draw(option); 63 return; 64 } 65 66 // overlay the z bins of the 3d histogram into a 2d histogram 67 // using different box colors 68 69 // make a legend 70 TLegend *legend = new TLegend(0.80,0.84,0.98,0.98,"Legend","NDC"); 71 legend->SetFillColor(0); 72 legend->SetFillStyle(0); 73 legend->SetMargin(0.25); 74 75 int zbin; 76 double maxval = -999999.; 77 int maxbin = -1; 78 79 TString n0; 80 for (zbin=0; zbin<zbins; zbin++) { 81 if ((zbin >= 10) || (names[zbin].IsNull())) n0 = GetName(); 82 else n0 = names[zbin]; 83 int slice = zbin+1; 84 delete subHists[zbin]; 85 subHists[zbin] = XYProjection(n0.Data(),slice); 86 subHists[zbin]->SetLineColor(60+40*(zbin/(zbins-1))); 87 subHists[zbin]->SetStats(kFALSE); 88 TAxis* taxisX = subHists[zbin]->GetXaxis(); 89 TAxis* taxisY = subHists[zbin]->GetYaxis(); 90 fXaxis.Copy(*taxisX); 91 fYaxis.Copy(*taxisY); 92 taxisX->SetRange(x0,x1); 93 taxisY->SetRange(y0,y1); 94 95 double binmax = subHists[zbin]->GetMaximum(); 96 if (binmax > maxval) { 97 maxval = binmax; 98 maxbin = zbin; 99 } 100 legend->AddEntry(subHists[zbin],n0.Data(),"l"); 101 } 102 103 subHists[maxbin]->SetTitle(GetTitle()); 104 subHists[maxbin]->Draw(option); 105 TString sameoption = option; sameoption += "same"; 106 for (zbin=0; zbin<zbins; zbin++) { 107 if (zbin != maxbin) subHists[zbin]->Draw(sameoption.Data()); 108 } 109 110 // Draw statistics for full set if stats are turned on 111 if (!TestBit(kNoStats)) { 112 delete subHists[0]; 113 subHists[0] = XYProjection(GetName()); 114 subHists[0]->Reset(); 115 subHists[0]->SetEntries(GetEntries()); 116 subHists[0]->SetStats(kTRUE); 117 subHists[0]->Draw(sameoption.Data()); 118 legend->SetX1(0.59); 119 legend->SetX2(0.77); 120 } 121 122 legend->Draw(); 123 124 fXaxis.SetRange(x0,x1); 125 fYaxis.SetRange(y0,y1); 126 } 127 128 TH2D* StMultiH2F::XYProjection(const char* name, Int_t zbin) { 129 static char buf[256]; 130 if (zbin<0) sprintf(buf,"%s.",name); 131 else sprintf(buf,"%s_%d_%s",GetName(),zbin,name); 132 133 TList* tgList = gDirectory->GetList(); 134 TH2D* temp = (TH2D*) tgList->FindObject(buf); 135 if (temp) tgList->Remove(temp); 136 137 if (zbin<0) fZaxis.SetRange(); 138 else fZaxis.SetRange(zbin,zbin); 139 temp = (TH2D*) Project3D("yx"); 140 temp->SetName(buf); 141 TAttLine::Copy(*temp); 142 TAttFill::Copy(*temp); 143 TAttMarker::Copy(*temp); 144 temp->GetXaxis()->SetRange(fXaxis.GetFirst(),fXaxis.GetLast()); 145 temp->GetYaxis()->SetRange(fYaxis.GetFirst(),fYaxis.GetLast()); 146 return temp; // up to the user of this function delete 147 } 148 149 void StMultiH2F::SavePrimitive(ostream& out, Option_t* option) { 150 // Save primitive as a C++ statement(s) on output stream out 151 152 bool nonEqiX = kFALSE; 153 bool nonEqiY = kFALSE; 154 int i; 155 156 // Check if the histogram has equidistant X bins or not. If not, we 157 // create an array holding the bins. 158 if (GetXaxis()->GetXbins()->fN && GetXaxis()->GetXbins()->fArray) { 159 nonEqiX = kTRUE; 160 out << " Double_t xAxis[" << GetXaxis()->GetXbins()->fN 161 << "] = {"; 162 for (i = 0; i < GetXaxis()->GetXbins()->fN; i++) { 163 if (i != 0) out << ", "; 164 out << GetXaxis()->GetXbins()->fArray[i]; 165 } 166 out << "}; " << endl; 167 } 168 169 // Check if the histogram has equidistant Y bins or not. If not, we 170 // create an array holding the bins. 171 if (GetYaxis()->GetXbins()->fN && GetYaxis()->GetXbins()->fArray) { 172 nonEqiY = kTRUE; 173 out << " Double_t yAxis[" << GetYaxis()->GetXbins()->fN 174 << "] = {"; 175 for (i = 0; i < GetYaxis()->GetXbins()->fN; i++) { 176 if (i != 0) out << ", "; 177 out << GetYaxis()->GetXbins()->fArray[i]; 178 } 179 out << "}; " << endl; 180 } 181 182 char quote = '"'; 183 out <<" "<<endl; 184 out <<" TH1 *" << GetName() << " = new " << ClassName() << "(" 185 << quote << GetName() << quote << "," << quote << GetTitle() << quote 186 << "," << GetXaxis()->GetNbins(); 187 if (nonEqiX) 188 out << ", xAxis"; 189 else 190 out << "," << GetXaxis()->GetXmin() 191 << "," << GetXaxis()->GetXmax(); 192 if (nonEqiY) 193 out << ", yAxis"; 194 else 195 out << "," << GetYaxis()->GetXmin() 196 << "," << GetYaxis()->GetXmax(); 197 out << "," << GetZaxis()->GetNbins() << ");" << endl; 198 199 // save bin contents 200 int bin; 201 for (bin=0;bin<fNcells;bin++) { 202 double bc = GetBinContent(bin); 203 if (bc) { 204 out<<" "<<GetName()<<"->SetBinContent("<<bin<<","<<bc<<");"<<endl; 205 } 206 } 207 208 // save bin errors 209 if (fSumw2.fN) { 210 for (bin=0;bin<fNcells;bin++) { 211 double be = GetBinError(bin); 212 if (be) { 213 out <<" "<<GetName()<<"->SetBinError("<<bin<<","<<be<<");"<<endl; 214 } 215 } 216 } 217 218 for (bin=0;bin<GetZaxis()->GetNbins();bin++) { 219 if (!(names[bin].IsNull())) 220 out <<" "<<GetName()<< "->Rebin(" << bin << "," 221 << quote << names[bin] << quote << ");" << endl; 222 } 223 224 TH1::SavePrimitiveHelp(out, option); 225 } 226 227 // $Id: StMultiH2F.cxx,v 1.8 2016/05/27 18:02:41 genevb Exp $ 228 // $Log: StMultiH2F.cxx,v $ 229 // Revision 1.8 2016/05/27 18:02:41 genevb 230 // Garbage collection (Coverity), remove unnecessary ROOT types 231 // 232 // Revision 1.7 2015/07/20 18:27:47 genevb 233 // fix minor bug with SavePrimitive 234 // 235 // Revision 1.6 2013/11/21 22:22:48 genevb 236 // Protect against array out-of-bounds, use inherited axis handles 237 // 238 // Revision 1.5 2008/07/10 21:26:59 genevb 239 // Allow SavePrimitive of fully drawn TPad to work properly 240 // 241 // Revision 1.4 2008/07/09 20:52:38 genevb 242 // Implement SavePrimitive functions 243 // 244 // Revision 1.3 2007/04/24 17:45:33 genevb 245 // Patched for problems with limited axis ranges 246 // 247 // Revision 1.2 2007/04/12 22:39:13 genevb 248 // Remove drawing of underflows 249 // 250 // Revision 1.1 2007/03/13 16:22:31 genevb 251 // Introduce StMultiH2F class 252 // 253 // 254