如何用matplotlib绘制热图?

时间:2016-05-12 19:53:32

标签: python matplotlib plot

如何使用python和matplotlib绘制如下图片? 我知道如何绘制2D热图,但是通过绘制热图顶部的条形图以及颜色条和热图之间的条形图,它让我感到很沮丧。 如何在图片上添加这两个条,并在x轴或y轴上显示数字属于哪个组?

非常感谢所有回复。

enter image description here

1 个答案:

答案 0 :(得分:6)

系统而直接的方法虽然在开始时有点麻烦,但却使用matplotlib.gridspec.GridSpec

首先设置网格:

#ifndef TWODCONTOUR_H
#define TWODCONTOUR_H


#include <vector>
using std::vector;
#include <opencv2/core.hpp>
using namespace cv;

class Contour
{
protected:
    vector<Vec2f> points;   
    virtual void process(){} // virtual function interface for after-creation/edit processing (eg. refinement/validation)
public:
    inline Vec2f at(int index){return points[index];}
    inline void clear(){points.clear();}
    inline void addPoint(Vec2f p){points.push_back(p);}
    inline void finish(){process();}
    inline void randomize(int num)
    {
        num--;
        points.clear();
        int cycles=6;//rand()%6+1;
        float offset=(float)rand()/(float)RAND_MAX*2.0f*3.141592654f;
        float noisemag=(float)rand()/(float)RAND_MAX;
        for(int i=0;i<num;i++)
        {
            float a=(float)i/(float)num;
            addPoint(
                    Vec2f(sin(a*2.0f*3.141592654f),cos(a*2.0f*3.141592654f))+
                    noisemag*Vec2f(sin(cycles*a*2.0f*3.141592654f+offset),cos(cycles*a*2.0f*3.141592654f+offset)));
        }
        addPoint(points.front());
        process();
    }
    void writeToFile(String fname);
    virtual Mat draw(Mat canvas, bool center=false, Scalar colour=Scalar(255,255,255), int thickness=1);
    inline int numPoints(){return points.size();}
    inline Vec2f getPoint(int i){return points[i];}
};



#endif

这给我们一个2行3列的网格,其中左下轴为10x10,其他轴的相对大小为10x1或1x10。这些比例可以根据自己的喜好进行调整。请注意,顶部中心/右轴将为空。

#include <opencv2/highgui.hpp>
#include <opencv2/imgproc.hpp>
#include <iostream>
#include <fstream>
#include "2DContour.h"

using namespace std;
using namespace cv;

//error occurs here
void Contour::writeToFile(string fname)
{
    ofstream out;
    out.open(fname.c_str());
    for(unsigned int i=0;i<points.size();i++)
        out << points[i][0]<<" "<<points[i][1]<<endl;
    out.close();
    std::cout<<"Wrote: "<<fname<<std::endl;
}

//draw() function does not experience the same error however
Mat Contour::draw(Mat canvas, bool center, Scalar colour, int thickness)
{
    Mat r=canvas.clone();
    cv::Point c(center?r.cols/2:0,center?r.rows/2:0);

     for( unsigned int j = 0; j < points.size(); j++ )
         {
             line(r,c+ cv::Point(points[j]*50),c+ cv::Point(points[(j+1)%points.size()]*50),colour,thickness, 8 );
         }
     return r;
}

我将使用通过谷歌找到的通用基因组图片获得顶部和右侧图片:enter image description here

将生成随机热图。我使用import matplotlib.pyplot as plt from matplotlib.gridspec import GridSpec fig = plt.figure() gs = GridSpec(2, 3, width_ratios=[10, 1, 1], height_ratios=[1, 10]) ,以便图像对象和热图占据各自轴的整个空间(否则它们将覆盖由gridspec设置的高度/宽度比率)。

big_ax = fig.add_subplot(gs[1,0]) # bottom left
top_ax = fig.add_subplot(gs[0,0]) # top left
right_ax = fig.add_subplot(gs[1,1]) # bottom center
cbar_ax = fig.add_subplot(gs[1,2]) # bottom right

enter image description here

它不是超级迷人的(特别是使用默认的喷射色彩图),但你可以轻松地使用它来重现你的OP图。

编辑:因此,如果你想在顶部和右边生成类似基因组的情节,你可以尝试这样的顶部栏:

imshow(aspect='auto')

对于正确的轴,您可以执行相同的操作,但使用im = plt.imread('/path/to/image.png') # Plot your heatmap on big_ax and colorbar on cbar_ax heatmap = big_ax.imshow(np.random.rand(10, 10), aspect='auto', origin='lower') cbar = fig.colorbar(heatmap, cax=cbar_ax) # Show your images on top_ax and right_ax top_ax.imshow(im, aspect='auto') # need to rotate my image. # you may not have to if you have two different images from scipy import ndimage right_ax.imshow(ndimage.rotate(im, 90), aspect='auto') # Clean up the image axes (remove ticks, etc.) right_ax.set_axis_off() top_ax.set_axis_off() # remove spacing between axes fig.subplots_adjust(wspace=0.05, hspace=0.05) 并将x-coords换成y-coords。

from matplotlib.patches import Rectangle
from matplotlib.collections import PatchCollection

# draw the black line
top_ax.axhline(0, color='k', zorder=-1)

# box x-coords and text labels
boxes = zip(np.arange(0.1, 1, 0.2), np.arange(0.2, 1, 0.2))
box_text = ('A1', 'B1', 'B2', 'A2')
# color indicators for boxes
colors = (0, 1, 1, 0)
# construct Rects
patches = [Rectangle(xy=(x0, -1), width=(x1-x0), height=2) for x0,x1 in boxes]
p = PatchCollection(patches, cmap='jet')
# this maps the colors in [0,1] to the cmap above
p.set_array(np.array(colors))
top_ax.add_collection(p)

# add text
[top_ax.text((x0+x1)/2., 1.2, text, ha='center') 
    for (x0,x1), text in zip(boxes, box_text)]

# adjust ylims
top_ax.set_ylim(-2, 2)

这些修改导致类似:

enter image description here