11

I have data from infrared measurements in a file with 194 rows and 194 columns, each value representing the temperature at a certain pixel.

As the image from the camera does not look nice, I would like to plot it with pgfplots in a similar way. This means for each value in my data matrix, a certain color should be plotted.

The data matrix looks like this:

22.93   22.97   23.07   23.11   23.11
23.1    23.05   23.1    23.12   23.12
23.11   23.3    23.3    23.17   23.18
23.08   23.11   23.3    23.17   23.18
23.12   23.1    23.18   23.22   23.14

My most promising try was the following code:

\begin{tikzpicture}
\begin{axis}

\pgfplotstableread{pictures/test.txt} \datatable
\addplot3[surf, shader=interp, mesh/rows=5]table from \datatable;

\end{axis}
\end{tikzpicture}

That's the outcome. enter image description here

I wish to obtain a density plot as shown in the following picture (the colorbar on the right is not a problem, I found the solution with groupplot...):

enter image description here

5

3 Answers 3

8

Something like this? The drawback is, you have to adopt the data format.

\documentclass[tikz]{standalone}

\usepackage{pgfplots, filecontents}

\begin{filecontents*}{temp.dat}
0 0 22.93
1 0 22.97
2 0 23.07
3 0 23.11
4 0 23.11

0 1 23.1
1 1 23.05
2 1 23.1 
3 1 23.12 
4 1 23.12

0 2 23.11
1 2 23.3
2 2 23.3
3 2 23.17
4 2 23.18

0 3 23.08
1 3 23.11
2 3 23.3
3 3 23.17
4 3 23.18

0 4 23.12
1 4 23.1
2 4 23.18
3 4 23.22
4 4 23.14
\end{filecontents*}


\begin{document}

\begin{tikzpicture}
  \begin{axis}[view={0}{90},
               xlabel=$x$,
               ylabel=$y$,
               colorbar,
               colorbar style={
                    title=$^\circ C$,
                    yticklabel style={
                        /pgf/number format/.cd,
                            fixed,
                            fixed zerofill
                    }
               },
               title=data from infrared measurements]
    \addplot3[surf] file {temp.dat};
  \end{axis}
\end{tikzpicture}

\end{document}

enter image description here

3
  • That solution looks pretty good!! Many thanks! I had to make some adjustments (the yicklabel style didnt't work for some reason). I was able to get it running with just a couple of data. Whith 194x194 however the latex-memory gets a problem (of course). Do you know a solution how to increase the memory size? Error says "TeX capacity exceeded, sorry [main memory size=3000000]
    – nmy2015
    Jul 16, 2015 at 3:19
  • I managed to somewhat get it compiled when using lualatex instead of pdflatex. The picture shows in the main document but is not externalized as a pdf file. I receive the following error message: Package tikz Error: Sorry, the system call 'pdflatex -halt-on-error -interact
    – nmy2015
    Jul 16, 2015 at 6:42
  • How do you change the colormap for this? Adding colormap name = spring gives a missing number treated as zero error ...
    – fbence
    Jul 26, 2019 at 12:21
11

Using the matrix plot* feature of PGFPlots v1.13 should exactly do what you want (see section 4.6.12 on page 164 of the manual). I assume you want to show the values of the pixels as given in your data points.

If so, using surf (only) doesn't do what you want, because then the a cell is build from "surrounding" coordinates showing the mean value of these surrounding coordinates. That means that mean coordinate for the lower left cell is (0.5,0.5) and has a temperature of around 23.0°C. And because of this behavior you just get a 4x4 matrix although your input is a 5x5 matrix.

It gets a bit better when using surf,shader=flat corner where you also (just) get a 4x4 matrix, but the cell temperature is taken from the lower left coordinate of the cell, e.g. (0,0) for the lower left cell. As you can see now, the temperature is much lower (in color: more blue) then compared to the upper variant.

Only with matrix plot* you will get the 5x5 matrix where the center of the cell is the specified coordinate also showing the corresponding temperature.

\documentclass[tikz]{standalone}
\usepackage{filecontents}
\usepackage{pgfplots}
    \begin{filecontents*}{temp.dat}
        0 0 22.93
        1 0 22.97
        2 0 23.07
        3 0 23.11
        4 0 23.11

        0 1 23.1
        1 1 23.05
        2 1 23.1
        3 1 23.12
        4 1 23.12

        0 2 23.11
        1 2 23.3
        2 2 23.3
        3 2 23.17
        4 2 23.18

        0 3 23.08
        1 3 23.11
        2 3 23.3
        3 3 23.17
        4 3 23.18

        0 4 23.12
        1 4 23.1
        2 4 23.18
        3 4 23.22
        4 4 23.14
    \end{filecontents*}
\begin{document}
    \begin{tikzpicture}
        \begin{axis}[
            view={0}{90},   % not needed for `matrix plot*' variant
            xlabel=$x$,
            ylabel=$y$,
            colorbar,
            colorbar style={
                title=$^\circ \mathrm{C}$,
                yticklabel style={
                    /pgf/number format/.cd,
                    fixed,
                    precision=1,
                    fixed zerofill,
                },
            },
            title=data from infrared measurements,
            %
            % added these key-values
            enlargelimits=false,
            axis on top,
            point meta min=22.9,
            point meta max=23.3,
            %
            % uncomment me to show, that there are really no cells plotted
            % when using the second variant (`surf, shader=flat corner')
            %xmax=5,
            %ymax=5,
        ]
            %% gives the mean temperature of the neighbouring cells (4x4 matrix)
            %\addplot3 [surf] file {temp.dat};

            %% gives the temperature of each point where the reference point
            %% is the lower left corner of the cell (also a 4x4 matrix)
            %% (I already asked the package author if this is intended or a bug)
            %\addplot3 [surf,shader=flat corner] file {temp.dat};

            % this should give the desired output (5x5 matrix)
            \addplot [matrix plot*,point meta=explicit] file [meta=index 2] {temp.dat};
        \end{axis}
    \end{tikzpicture}
\end{document}

image showing the result of above code

3
  • I've been looking for this for such a long time! Unfortunately searching for "pgfplots heatmap" doesn't directly yield this answer, and heatmap doesn't appear in the docs. Thank you!
    – kmundnic
    Apr 29, 2021 at 23:46
  • @kmundnic, you are welcome. If you think it would help also others to find these question/answer, you could make an edit to the title of the question. There you could add "heatmap". To increase chances that the edit will be accepted state a good "Edit Summary". Apr 30, 2021 at 5:04
  • 1
    @kmundnic, in addition you could mark other questions with "heatmap" as duplicates, if you think these answers here are applicable to that other question as well. This would of course also increase visibility of this answer. Apr 30, 2021 at 5:07
5

Many thanks sergej, for your very valuable answer.

I managed to get it running now with all the big data I'm using.

Here's the code I applied:

\tikzsetnextfilename{temp1C50DOD}
\begin{tikzpicture}
\begin{axis}
[view={0}{90},
xlabel=$x$,
ylabel=$y$,
colorbar,
colorbar style={
title=$^\circ C$,
yticklabel style={/pgf/number format/.cd, fixed zerofill, precision=1}
},
title= 
]

\addplot3[surf, shader=interp, mesh/rows=194]file {pictures/test2.txt};


\end{axis}
\end{tikzpicture}

My test2.txt looks like you suggested. (with an excel macro it was easy to sort the data accordingly). The Macro looks like this:

Sub Columns2Column()
'
' Columns2Column Macro
'

'
Dim i As Integer
Dim j As Integer
Dim lngZeile As Long
With ActiveSheet
   For i = 2 To .Cells(1, .Columns.Count).End(xlToLeft).Column
   lngZeile = lngZeile + 194
      For j = 1 To 194
         .Cells(lngZeile + j, 1).Value = Cells(j, i).Value
      Next j
   Next i
End With
End Sub

Additionally, as the big data were too much I changed to lualatex instead of pdflatex by just replacing the exe file in the command configuration of my editior.

As tikz externalize still didn't work with this, I had to add the following lines into my header file:

\tikzset{external/system call={lualatex
        \tikzexternalcheckshellescape -halt-on-error -interaction=batchmode
        -jobname "\image" "\texsource"}}

I hope this solution helps others as well :)

And here is the beautiful outcome:

enter image description here

7
  • 1
    The outcome is really beautiful! Thanks for sharing.
    – sergej
    Jul 16, 2015 at 8:13
  • 1
    You can add yticklabel style={/pgf/number format/.cd, fixed zerofill, precision=1} to the colorbar style to get a decimal point and a trailing zero after the 23.
    – sergej
    Jul 16, 2015 at 8:21
  • Thanks sergej, I did that and added it to above code. Nice thing! I only now have the problem, if I want to create a second such picture with different data, it does run in errors whose origin I can't really figure out at the moment. It seems, lualatex and externalize still have their problems with each other. It says: Syntax error: couldn't find trailer dictionary Syntax error: Couldn't read xref table. Anyone any idea what this means?
    – nmy2015
    Jul 16, 2015 at 10:25
  • 1
    I found out, how this problem can be solved: \tikzexternalize needs to get the option optimize=false so it works. I just have one more question: As I have multiple plots, I'd like to adjust the colorbar to a certain range that is applicable for all plots. Is there any option to set the range of the colorbar?
    – nmy2015
    Jul 20, 2015 at 10:17
  • 1
    It seems optimize=false was not the proper solution. What finally really helped to compile the document without problems with all the tikz-pictures was to update ALL packages and to remove inputenc, which does not work together with lualatex. (see thread here: tex.stackexchange.com/questions/256081/…)
    – nmy2015
    Jul 30, 2015 at 2:46

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .