How to use TPaletteAxis for TGraph (or TGraph2D)

Dear rooters,

I am not sure if there is built-in functionality that allows users to draw markers with different colors (and/or size), and then show a Palette to indicate the scale for the color (or size).

Here is the graph for demo:
1

My method is to use TGraph object to draw a box with only two points, and
then draw many TMarker objects at the same canvas.

But I cannot figure out how to create a TPaletteAxis to illustrate the scale.

I am very appreciative if you could give some hints to me.
Thank you very much.

The following are example codes:


class myTGraph : public TGraph
{
  private: 
    
    //=======================================
    // for color palette
    Int_t* fPaletteColor; // size = fPaletteColorN
    Int_t  fPaletteColorN;
    //=======================================

    //=======================================
    // for user input data
    vector<Double_t> fXs;
    vector<Double_t> fYs;
    vector<Double_t> fCs;
    //========================================
    
    Double_t fSize1;
    Double_t fSize2;

    vector<TMarker> fMarkers;
     
  public:
    
    myTGraph() : TGraph() {};

    ~myTGraph(){};

    /*! 
        @param paletteColor, int*, each element is color index.
        @param ncolors, int, the size of palette color.
    */
    void SetPalette( Int_t ncolors, Int_t* paletteColor ) {
        fPaletteColor  = paletteColor;
        fPaletteColorN = ncolors; 
    };

    void SetMarkerSizeRange( Double_t size1, Double_t size2 ){

        if( size1>size2 ){
            fSize2 = size1;
            fSize1 = size2; }
        else{
            fSize1 = size1;
            fSize2 = size2;
        }
    }

    /*!
        @param pointN, int, for the size of the x,y,and c array.
    */
    void SetPoints( Int_t pointN, Double_t* x, Double_t* y, Double_t* c ) 
    {

       
        for( int i =0; i< pointN; i++ ){
            fXs.push_back( x[i] );
            fYs.push_back( y[i] );
            fCs.push_back( c[i] );
        }
        
        Double_t xMin, yMin, xMax, yMax;
        xMin = * min_element( fXs.begin(), fXs.end() );
        xMax = * max_element( fXs.begin(), fXs.end() );

        yMin = * min_element( fYs.begin(), fYs.end() );
        yMax = * max_element( fYs.begin(), fYs.end() );
        
        SetPoint( 0, xMin, yMin );
        SetPoint( 1, xMax, yMax );
    };

    

    void Draw2( Option_t * option = ""){

        TString opt = option;  opt.ToLower();

        bool drawSize = false;
        
        if( opt.CompareTo("c") == 0 ){ 
            
            drawSize = true; 
            
            if( fSize1 <= 0 and fSize2 <= 0 )
            {
                fSize1 = 1.;
                fSize2 = 3.;
            }
        }
               
        TGraph::Draw( "AP" ); // Draw the box

        
        Double_t cStep;

        Double_t cMin = * min_element( fCs.begin(), fCs.end() );
        Double_t cMax = * max_element( fCs.begin(), fCs.end() );
        cStep = (cMax - cMin)/ fPaletteColorN;

    
        fMarkers.clear(); 

        for( int i =0; i< fXs.size(); i++ )
        {
            Double_t x = fXs.at(i);
            Double_t y = fYs.at(i);
            
            TMarker m; 
            
            m.SetMarkerStyle(20);

            //=====================================================
            // setting colors and sizes for the markers
            
            Int_t idx = int( ( fCs.at(i) - cMin - 1E-4)/cStep )  ;
            m.SetMarkerColor( fPaletteColor[idx] );
            
            if( drawSize ) {
                Double_t mSize 
                = fSize1 + (fSize2 - fSize1) * idx  / fPaletteColorN;
                //note idx ranges from 0 to (fPaletteColor-1)
                
                m.SetMarkerSize( mSize );                
            }

            //=====================================================

            m.DrawMarker( x, y ); 
            fMarkers.push_back( m );
            m.Draw("same");
        }
    };
    
};

void  demo(){
    
    gStyle->SetOptStat( 0 );

    //================================================================
    // create colors
    // new color indices are stored in myColor_idx[]
    // with size = colorN
    
    Double_t red[9]   = { 242., 234., 237., 230., 212., 156., 99., 45., 0.};
    Double_t green[9] = { 243., 238., 238., 168., 101.,  45.,  0.,  0., 0.};
    Double_t blue[9]  = { 230.,  95.,  11.,   8.,   9.,   3.,  1.,  1., 0.};
    
    // note: total color N = subDivN * 8 
    int subDivN = 8;
    const Int_t colorN = subDivN * 8 ;    
    Int_t*  myColor_idx = new Int_t [ colorN ];
    TColor** myColor = new TColor*[ colorN ];

    int iColor = 0;
    for( int i=0; i<(9-1); i++ ){
        Double_t red1   = red[i];    Double_t red2   = red[i+1];
        Double_t green1 = green[i];  Double_t green2 = green[i+1];
        Double_t blue1  = blue[i];   Double_t blue2  = blue[i+1];
        
        if( iColor==0 ){ 
            myColor_idx[0] = TColor::GetFreeColorIndex(); 
            myColor[0] = 
            new TColor( myColor_idx[0], red[0]/255., green[0]/255., blue[0]/255.  );
            iColor += 1;
        }

        for( int j=0; j<subDivN; j++ ){
            Double_t _red   =  red1 + ( red2-red1 )* ( j+1 )/subDivN; 
            Double_t _green =  green1 + ( green2-green1 )* ( j+1 )/subDivN; 
            Double_t _blue  =  blue1 + ( blue2-blue1 )* ( j+1 )/subDivN; 

            myColor_idx[ iColor ] = TColor::GetFreeColorIndex(); 
            myColor[ iColor] = 
            new TColor( myColor_idx[iColor], 
                        _red/255., _green/255., _blue/255.  );
            iColor += 1;
        }    
    }
    //====================================================================


    if( 1 ){

        myTGraph* gr = new myTGraph();

        Double_t xs[5] = {  1,  2,  3,  4,  5 };
        Double_t ys[5] = { 10, 20, 30, 40, 50 };
        Double_t cs[5] = { 11, 22, 33, 44, 55 };

        gr->SetPalette( colorN, myColor_idx );
        gr->SetMarkerSizeRange( 0.5, 5 );
        gr->SetPoints( 5, xs, ys, cs );
        gr->Draw2( "c" );

    }


    // visualizing the color
    if( 1 )
    {
        new TCanvas();

        TH1F* histo[colorN];
        for( Int_t i = 0; i<colorN; i++ )
        { 
            
            histo[i] = 
            new TH1F( Form("histo%d",i), Form("histo%d",i), colorN, 0,colorN );
            
            for( Int_t j=0; j<5; j++ ){ histo[i]->Fill(i); }
        }

        histo[0]->Draw(); histo[0]->SetTitle("colors");
        for( Int_t i = 1; i<colorN; i++ )
        { 
            histo[i]->Draw("same");
        }    

        for( Int_t i = 0; i<colorN; i++ ){
            // histo[i]->SetLineColor( currentPalette.GetAt(i) );
            histo[i]->SetFillStyle( 1001 );
            histo[i]->SetFillColor( myColor_idx[i] );
            histo[i]->SetLineColor( myColor_idx[i] );
        }
    }


    
}


ROOT Version: 6.12
Platform: Ubuntu 14.04
Compiler: gcc


TPaletteAxis needs an histogram to be constructed.
I ran your macro and I get the following picture. Is it an attempt to draw the palette ?

Thank you for the quick reply, the original purpose of the figure you pointed out is to check the colors setting.

Ideally, I want a palette to show color-value mapping relationship.
i.e. Dark --> 100, yellow -> 50, white->0

As you mention “TPaletteAxis needs an histogram to be constructed”, and then, my idea is that to use a histogram as a private object, and plot that palette on canvas with the TGraph object. Or any other suggestions?

Thank you very much.

Yes, that might be a quick way to use TPaletteAxis.

  1. Create a dummy 2D histogram
  2. Set the maximum and minimum of this histogram to the values you need
  3. Draw the histogram with option “COL Z”

May be a constructor without histogram might be useful at some point.

The results look well. Thank you for answering my question.

1

class myTGraph : public TGraph
{
  private: 
    
    //=======================================
    // for color palette
    Int_t* fPaletteColor; // size = fPaletteColorN
    Int_t  fPaletteColorN;
    //=======================================

    //=======================================
    // for user input data
    vector<Double_t> fXs;
    vector<Double_t> fYs;
    vector<Double_t> fCs;
    //========================================
    
    Double_t fSize1;
    Double_t fSize2;

    vector<TMarker> fMarkers;

    TH2D* fHisto2d;
     
  public:
    
    myTGraph() : TGraph() {};

    ~myTGraph(){ delete fHisto2d; };

    /*! 
        @param paletteColor, int*, each element is color index.
        @param ncolors, int, the size of palette color.
    */
    void SetPalette( Int_t ncolors, Int_t* paletteColor ) {
        fPaletteColor  = paletteColor;
        fPaletteColorN = ncolors; 
    };

    void SetMarkerSizeRange( Double_t size1, Double_t size2 ){

        if( size1>size2 ){
            fSize2 = size1;
            fSize1 = size2; }
        else{
            fSize1 = size1;
            fSize2 = size2;
        }
    }

    /*!
        @param pointN, int, for the size of the x,y,and c array.
    */
    void SetPoints( Int_t pointN, Double_t* x, Double_t* y, Double_t* c ) 
    {

       
        for( int i =0; i< pointN; i++ ){
            fXs.push_back( x[i] );
            fYs.push_back( y[i] );
            fCs.push_back( c[i] );
        }
        
        Double_t xMin, yMin, xMax, yMax;
        xMin = * min_element( fXs.begin(), fXs.end() );
        xMax = * max_element( fXs.begin(), fXs.end() );

        yMin = * min_element( fYs.begin(), fYs.end() );
        yMax = * max_element( fYs.begin(), fYs.end() );
        
        SetPoint( 0, xMin, yMin );
        SetPoint( 1, xMax, yMax );
    };

    

    void Draw2( Option_t * option = ""){

        TString opt = option;  opt.ToLower();

        bool drawSize = false;
        
        if( opt.CompareTo("c") == 0 ){ 
            
            drawSize = true; 
            
            if( fSize1 <= 0 and fSize2 <= 0 )
            {
                fSize1 = 1.;
                fSize2 = 3.;
            }
        }
               
        TGraph::Draw( "AP" ); // Draw the box

        
        Double_t cStep;

        Double_t cMin = * min_element( fCs.begin(), fCs.end() );
        Double_t cMax = * max_element( fCs.begin(), fCs.end() );
        cStep = (cMax - cMin)/ fPaletteColorN;

        // for palette
        fHisto2d = new TH2D( "histo", "histo", 
                    fPaletteColorN, cMin-1, cMax+1,
                    fPaletteColorN, cMin-1, cMax+1);
    
        fMarkers.clear(); 

        for( int i =0; i< fXs.size(); i++ )
        {
            Double_t x = fXs.at(i);
            Double_t y = fYs.at(i);
            
            TMarker m; 
            
            m.SetMarkerStyle(20);

            //=====================================================
            // setting colors and sizes for the markers
            

            Int_t idx = int( ( fCs.at(i) - cMin - 1E-4)/cStep )  ;
            m.SetMarkerColor( fPaletteColor[idx] );
            
            if( drawSize ) {
                Double_t mSize 
                = fSize1 + (fSize2 - fSize1) * idx  / fPaletteColorN;
                //note idx ranges from 0 to (fPaletteColor-1)
                
                m.SetMarkerSize( mSize );                
            }

            //=====================================================

            m.DrawMarker( x, y ); 
            fMarkers.push_back( m );
            m.Draw("same");

            //======================================================
            
            fHisto2d->Fill( fCs.at(i), fCs.at(i), fCs.at(i) );
            
        }

        TCanvas* ctemp = new TCanvas();
        gStyle->SetPalette( fPaletteColorN, fPaletteColor );
        fHisto2d->Draw("colz");
        ctemp->Update();
        TPaletteAxis *palette
        = (TPaletteAxis*)fHisto2d->GetListOfFunctions()->FindObject("palette");
        ctemp->Close();

        palette->Draw("same");
        delete ctemp;
    };
    
};

void  demo(){
    
    gStyle->SetOptStat( 0 );

    //================================================================
    // create colors
    // new color indices are stored in myColor_idx[]
    // with size = colorN
    
    Double_t red[9]   = { 242., 234., 237., 230., 212., 156., 99., 45., 0.};
    Double_t green[9] = { 243., 238., 238., 168., 101.,  45.,  0.,  0., 0.};
    Double_t blue[9]  = { 230.,  95.,  11.,   8.,   9.,   3.,  1.,  1., 0.};
    
    // note: total color N = subDivN * 8 
    int subDivN = 8;
    const Int_t colorN = subDivN * 8 ;    
    Int_t*  myColor_idx = new Int_t [ colorN ];
    TColor** myColor = new TColor*[ colorN ];

    int iColor = 0;
    for( int i=0; i<(9-1); i++ ){
        Double_t red1   = red[i];    Double_t red2   = red[i+1];
        Double_t green1 = green[i];  Double_t green2 = green[i+1];
        Double_t blue1  = blue[i];   Double_t blue2  = blue[i+1];
        
        if( iColor==0 ){ 
            myColor_idx[0] = TColor::GetFreeColorIndex(); 
            myColor[0] = 
            new TColor( myColor_idx[0], red[0]/255., green[0]/255., blue[0]/255.  );
            iColor += 1;
        }

        for( int j=0; j<subDivN; j++ ){
            Double_t _red   =  red1 + ( red2-red1 )* ( j+1 )/subDivN; 
            Double_t _green =  green1 + ( green2-green1 )* ( j+1 )/subDivN; 
            Double_t _blue  =  blue1 + ( blue2-blue1 )* ( j+1 )/subDivN; 

            myColor_idx[ iColor ] = TColor::GetFreeColorIndex(); 
            myColor[ iColor] = 
            new TColor( myColor_idx[iColor], 
                        _red/255., _green/255., _blue/255.  );
            iColor += 1;
        }    
    }
    //====================================================================


    if( 1 ){

        myTGraph* gr = new myTGraph();

        Double_t xs[5] = {  1,  2,  3,  4,  5 };
        Double_t ys[5] = { 10, 20, 30, 40, 50 };
        Double_t cs[5] = { 11, 22, 33, 44, 55 };

        gr->SetPalette( colorN, myColor_idx );
        gr->SetMarkerSizeRange( 0.5, 5 );
        gr->SetPoints( 5, xs, ys, cs );
        gr->Draw2( "c" );

    }


    // visualizing the color
    if( 0 )
    {
        new TCanvas();

        TH1F* histo[colorN];
        for( Int_t i = 0; i<colorN; i++ )
        { 
            
            histo[i] = 
            new TH1F( Form("histo%d",i), Form("histo%d",i), colorN, 0,colorN );
            
            for( Int_t j=0; j<5; j++ ){ histo[i]->Fill(i); }
        }

        histo[0]->Draw(); histo[0]->SetTitle("colors");
        for( Int_t i = 1; i<colorN; i++ )
        { 
            histo[i]->Draw("same");
        }    

        for( Int_t i = 0; i<colorN; i++ ){
            histo[i]->SetFillStyle( 1001 );
            histo[i]->SetFillColor( myColor_idx[i] );
            histo[i]->SetLineColor( myColor_idx[i] );
        }
    }


    
}
1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.