11

How can I plot a matrix of real values with TikZ/PGF such that it looks like plotted with imshow in MATLAB?

\addplot3 does something similar, but I'd like to have that in a color-coded 2D plot.

Torbjørn T.
  • 206,688
Christian
  • 407
  • The answer to this question is closely related to this one https://tex.stackexchange.com/questions/250762/create-a-3d-figure-surf-from-csv-file – 3244611user Jul 04 '18 at 14:11

5 Answers5

6

There's a problem with @Christian's first answer: It does not work for data matrices. In that case, the values get mapped at the corners of each squares, and the colors are some interpolation between adjacent data values, not the values themselves. I found the following solution. It's not completely satisfactory since the size of the marks does not adapt to the size of the picture, but it's a start. You can also have empty values, as shown in the example.

\begin{tikzpicture}
\begin{axis}[
  width=0.75\textwidth, height=0.75\textwidth,
  tick align=inside, unbounded coords=jump,
  xmin=-1, xmax=5, ymin=-1, ymax=5,
  point meta min=0, point meta max=8, colorbar, colormap/bluered]
  \addplot[mark=square*,only marks, scatter, scatter src=explicit,
  mark size=17]
  coordinates {
  (0,0) [0]
  (0,1) [1]
  (0,2) [2]
  (0,3) [3]
  (0,4) [4]

  (1,0) [1]
  (1,1) [2]
  (1,2) [3]
  (1,3) [4]
  (1,4) [5]

  (2,0) [2]
  (2,1) [3]
  (2,4) [6]

  (3,0) [3]
  (3,1) [4]
  (3,2) [5]
  (3,3) [6]
  (3,4) [7]

  (4,0) [4]
  (4,1) [5]
  (4,2) [6]
  (4,3) [7]
  (4,4) [8]
  };
\end{axis}
\end{tikzpicture}

solution

percusse
  • 157,807
yannick
  • 813
6

The following does the job very well:

\begin{tikzpicture}
  \begin{axis}[view={0}{90},
               xlabel=$x$,
               ylabel=$y$,
               title=View from top]
    \addplot3[surf] {x};
  \end{axis}
\end{tikzpicture}
Christian
  • 407
2

I know that this is an old question, but for future reference, I want to include that pgfplots has included an imshow like plot, at least in version 1.18. It is called matrix plot. In contrast to the solutions above, it places the patches at the correct locations, leaves no gaps in between patches and does not require manual scaling of the patches with respect to the axis system.

\documentclass{standalone}
\usepackage{pgfplots}

\begin{document} \begin{tikzpicture} \begin{axis}[ width=4cm, height=4cm, colorbar, colormap name=viridis] \addplot[matrix plot, point meta=explicit] coordinates { (0,0) [0] (1,0) [1] (2,0) [2]

        (0,1) [3] (1,1) [4] (2,1) [5]

        (0,2) [6] (1,2) [7] (2,2) [8]
    }; 
\end{axis}

\end{tikzpicture} \end{document}

Example plot result.

Note similar to imshow it places the y-axis in the top, with the positive y-direction pointing downward. Use matrix plot* for a normal axis system definition.

For more information see the documentation.

BHeijden
  • 41
  • 5
  • Good answers to old questions are always welcome, thanks for helping future readers :) in the future though, when you post answers could you make sure that they compile please? As in starting with \documentclass{...} and ending with \end{document}, helps people in the future if they can copy and paste your answer as is – JamesT Oct 12 '23 at 16:00
  • Good point, I had to look up how to do that, but the standalone works nicely. – BHeijden Oct 14 '23 at 15:22
2

I hacked a solution by my own, using a scatter plot. The key here is to adjust x and y, and the mark size to the right values.

\begin{tikzpicture}[]
    \begin{axis}[x=4mm,y=4mm,xtick=\empty,ytick=\empty]
    \addplot[scatter,scatter src=explicit, 
             only marks, mark=square*,mark size=2mm]  
             coordinates {(0,1)[0]  (1,1)[.1] (2,1)[.2]
                          (0,2)[.3] (1,2)[.4] (2,2)[.5]};
    \end{axis}
\end{tikzpicture}
Hongying
  • 569
Christian
  • 407
  • 6
    you know: http://tug.org/PSTricks/main.cgi?file=pst-plot/3D/contour ? –  Jan 05 '11 at 13:47
1

If preprocessing you data is an option, you can also use patch plots (4.6.13 in the manual). This has the advanted that you easily get the correct size for the cells and have no gaps.

For a patch plot, you have to specify coordinates of the shapes making up a surface manually. By listing a rectangle for each point you can get the desired result. For example for a matrix

2 3
4 5

you can write something like:

\begin{tikzpicture}
    \begin{axis}[
            % this prevents the borders of the
            % patches to be rendered
            shader=interp,
            % optional, add colorbar (here just
            % for showing that the values are
            % rendered correctly)
            colorbar,
        ]
        \addplot [
            % switch to patch mode
            patch,
            % The meta value determines the color.
            % "explicit" means that there is an extra
            % source for those, the default without
            % this option is to take the y value.
            point meta=explicit,
            % This tells pgfplots that the data is to
            % be interpreted as groups of four. Each
            % group represents the corners of a rectangle.
            patch type=rectangle,
        ] table [meta index=2] {
            x y meta
            -0.5 0.5 2
            -0.5 1.5 2
            0.5 1.5 2
            0.5 0.5 2
        0.5 0.5 3
        0.5 1.5 3
        1.5 1.5 3
        1.5 0.5 3

        -0.5 -0.5 4
        -0.5 0.5 4
        0.5 0.5 4
        0.5 -0.5 4

        0.5 -0.5 5
        0.5 0.5 5
        1.5 0.5 5
        1.5 -0.5 5
    };
\end{axis}

\end{tikzpicture}

We set the point meta of each corner to the same value. This way the interpolation shader results in a single color. The data input as inline table is just an example, you can just as well load it from a file or use another variation like "coordinates".

rendered tex document