Fill area between two histograms

Hi,

I want to fill the area between two histograms, one of which has some negative bins. The idea is that one hist represents the lower “envelope” of systematic errors on a bin-by-bin basis, and the other represents an upper “envelope.” To make the range of syst error on each bin clear, I want to shade the area between the two histograms.

How can I do this? I tried setting the fill color for the upper envelope to something gray, and then making the lower one white, but this doesn’t quite handle cases where the lower envelope is negative; the upper histogram’s fill color doesn’t go below zero.

Maybe someone has a clever idea involving some combination of the histograms I already have,

-tm35

Do you have a small running example showing what you did up to now and which problems you encountered ?

Hi,

Check out the attached script. I found the use of “lf2” in the TH1::Draw() method changes how the fill color is applied; see the commented-out section of the script at the bottom. This basically gives me what I was hoping for, but note this draws a line between bin contents instead of sticking with the original histogram shape itself.

-tm35
env_fill.C (1.49 KB)

To keep the histogram shape (in the commented part) remove the "l " option in the Draw() access.

Hi,

I’m using Root v4.04/02. I find that with options “hist same f2” no fill color is applied. Can you confirm that your suggestion should work for me?

-tm35

yes it should. “L” means Line … and “F” filled … let me know

My observations: Option “F” fills in the upper envelope histogram only down to the y-axis. Option “F2” seems to do nothing – it looks the same as no option specified at all. Only “LF2” seems to be close (but not exactly) what I want, extending the fill color down below the y-axis, but unfortunately also applying the “L” bin-to-bin option at the same time. Give it a shot. If needed, I can attach screen shots to show you what I see.

-tm35

I think the following code does what you are looking for:

{
  c1 = new TCanvas("c1","c1",200,10,700,700);
                                                                                
  int n = 20;
  TH1F* nom = new TH1F("nom", "nom", n, 0, 1);
                                                                                
  TRandom* rand = new TRandom();
                                                                                
  for (int j = 1; j <= n; ++j) {
    nom->SetBinContent(j, rand->Rndm()-0.5);
    nom->SetBinError(j, 0.5);
  }
                                                                                
  TH1F* envHi = new TH1F("envhi", "envhi", n, 0, 1);
  TH1F* envLo = new TH1F("envhi", "envhi", n, 0, 1);
  for (int j = 1; j <= n; ++j) {
    double y = nom->GetBinContent(j);
    double ey = nom->GetBinError(j);
    envHi->SetBinContent(j, y+ey);
    envLo->SetBinContent(j, y-ey);
  }
                                                                                
  nom->SetMinimum(-2);
  nom->SetMaximum(2);
  nom->Draw("");
  envHi->SetFillColor(2);
  envHi->Draw("same");
  envLo->SetFillColor(2);
  envLo->Draw("same");
  nom->Draw("same");
}

Hi,

Yup, it sure does. I guess I completely overlooked the fact that the fill color is applied upward to the y-axis for bins with negative contents. I was trying to work around something that wasn’t broken.

Thanks for talking me through a problem that wasn’t really there!

-tm35

Hi @couet. Thanks for this (some time has elapsed…)
If the envelope were centred around a value not 0 but around a positive value like 1, such that envLo’s bin contents were positive, would there be a way to achieve the same result, with histograms only, not involving TGraphAsymmErrors objects…?
Cheers,
Roy

It depends on your code. Can you provide some script showing what you are doing ?