Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

In my TeX document I would like to add a picture and in addition, zooming on a small part of the picture (e.g. inset in TeX or spy in TikZ).

My question, I have a histogram 2D (f(x,y) = z) date which I created from it a picture. I would like to know how could I create in TeX, something like spy or magnifying glass from a picture or raw data?

For example, I found in tikz spy library with pgfplots: opacity and grid nice example, but the person there uses \addplot and I would like to create histogram plot of my own data.

Is it possible to create 2D histogram in TikZ?

EDIT

here is an example of a 2D histogram that i would like to create: 2d histogram

share|improve this question
3  
You can use the spy library to enlarge areas of existing pictures, as is done in the answer to How to create magnified subfigures and corresponding boxes for portions of a large image. You could also recreate the histogram within your document, using PGFplots (which provides the \addplot command you noticed), as is done in tex.stackexchange.com/questions/27137/…, for example, and then zoom in the same way. –  Jake Nov 2 '11 at 12:40
    
the histogram in this example is not what i need. I need 2D Histogram. Is this possible in tikz? –  Eagle Nov 2 '11 at 14:27
    
The histogram Jake linked to is 2D, do you mean 3D, such as these? –  Torbjørn T. Nov 2 '11 at 15:43
    
@Torbjørn T., please see the example above, that i added –  Eagle Nov 2 '11 at 16:01
2  
that is a 2d contour plot with 3d data ... (tug.org/PSTricks/main.cgi?file=pst-plot/3D/contour) –  Herbert Nov 2 '11 at 16:12
show 2 more comments

2 Answers

Until someone gets around to implementing this directly in LaTeX, the easiest approach might be to use R and the brilliant hexbin library to generate the hexplot data and use pgfplots to do the actual plot:

Here's an R script for generating a hexplot of the distribution of cities with a population exceeding 40000:

# Load the data
library(maps)
data(world.cities)

# Load the hexbin package
library(hexbin)

# Generate hexbins, with the aspect ratio of the plot matching that of the data.
hbin<-hexbin(x=world.cities$long,y=world.cities$lat,xbins=100,shape=diff(range(world.cities$lat))/diff(range(world.cities$long)))

# Write the datafile. hcell2xy extracts the centroids of the hexagons
write.table(data.frame(hcell2xy(hbin),slot(hbin,"count")),row.name=F,file="testdata.csv")

This can then be plotted using pgfplots:

\documentclass[border=5mm]{article}
\usepackage{siunitx}
\usepackage{pgfplots, pgfplotstable}
\usetikzlibrary{spy}

\sisetup{round-mode=places,round-precision=0}

\pgfdeclareplotmark{hexagon}
{%
  \pgfpathmoveto{\pgfqpoint{0pt}{1.1547\pgfplotmarksize}}
  \pgfpathlineto{\pgfqpointpolar{150}{1.1547\pgfplotmarksize}}
  \pgfpathlineto{\pgfqpointpolar{210}{1.1547\pgfplotmarksize}}
  \pgfpathlineto{\pgfqpointpolar{270}{1.1547\pgfplotmarksize}}
  \pgfpathlineto{\pgfqpointpolar{330}{1.1547\pgfplotmarksize}}
  \pgfpathlineto{\pgfqpointpolar{30}{1.1547\pgfplotmarksize}}
  \pgfpathclose
\pgfusepathqfill
}

\pgfplotsset{
colormap={grayred}{color(0cm)=(black!10); color(1cm)=(red!75!black)}
}


\begin{document}
\begin{tikzpicture}[spy using outlines={circle, magnification=5, connect spies}]
\begin{axis}[
    enlargelimits=false,
    colorbar, colormap name=grayred,
           scale only axis,width=10cm,unit vector ratio*=1 1 1,
    enlarge x limits={abs=2},enlarge y limits={abs=2},
    xlabel=Longitude, ylabel=Latitude, xticklabel={\SI{\tick}{\degree}},yticklabel={\SI{\tick}{\degree}},
]
\addplot [
    scatter, scatter/use mapped color={draw=mapped color, fill=mapped color},
    scatter src=explicit,
    only marks,
    mark=hexagon,mark size=\pgfkeysvalueof{/pgfplots/width}/100/2
] table [meta index=2] {testdata.csv};
\coordinate (spynode) at (axis cs:5,45);
\begin{scope}[fill=white]
    \spy [size=5cm] on (spynode) in node [fill=white] at (3,7);
\end{scope}

\end{axis}
\end{tikzpicture}


\end{document}

If you just want to plot a series of values as a coloured matrix, this can be done directly with pgfplots, which is much faster than using arrays and looping over them "by hand":

\documentclass[border=5mm]{standalone}
\usepackage{pgfplots, pgfplotstable}

\pgfplotstableread[col sep=comma]{
5,-8,-10,-4,30,11,24,-9,13,22,5,23,-3,-8,12,-3,22,7,28,24,23,11,17,-4,24,11,19,15,-2,8,0,%
-6,26,27,-10,24,6,-6,10,12,17,29,-8,22,20,30,27,-1,0,27,8,13,4,10,8,30,-4,-6,6,26,11,0,-4,-2,17,27,17,%
-5,8,-7,-5,24,30,6,22,3,30,8,-10,8,11,28,-8,6,24,17,1,-2,26,-1,25,27,25,15,19,15,-7,2,29,14,21,25,-7,24,%
19,14,19,15,8,-6,-4,-7,28,15,7,3,6,2,-10,-9,22,18,-7,15,2,27,9,15,11,0,-7,-5,-8,24,-6,16,10,10,8,26,-4,%
6,-4,20,21,0,16,10,2,-4,3,-9,-3,21,16,-9,30,24,13,20,29,29,11,4,5,4,8,24,22,28,8,-1,1,6,30,-7,16,-6,30,%
12,-8,-4,-4,20,-4,-5,14,28,-4,28,15,14,7,7,9,14,-9,12,8,7,0,15,9,2,-10,28,22,3,-2,19,30,25,1,-9,26,12,%
25,11,15,16,-4,7,17,28,7
}\datatable
\pgfplotstabletranspose\newtable\datatable



\begin{document}
\begin{tikzpicture}
\begin{axis}[
    enlargelimits=false,
    colorbar, colormap/greenyellow,
    axis equal,
    scale only axis,
    width=6cm, height=6cm,
    xmin=-0.5,xmax=14.5
]
\addplot [
    scatter,
    scatter src=explicit,
    only marks,
    mark=square*,
    mark size=\pgfkeysvalueof{/pgfplots/width}/15/2
 ] table [x expr={mod(mod(\coordindex,15),15)}, %Use mod twice because of a bug in the fpu library
    y expr={round((\coordindex-7)/15)},
    meta=0] {\newtable};
\end{axis}
\end{tikzpicture}
\end{document}
share|improve this answer
add comment

In principle it is possible, I generated some random data in a TikZ suitable format:

\documentclass[parskip]{scrartcl}
\usepackage[margin=15mm]{geometry}
\usepackage{tikz}
\usetikzlibrary{calc}

\begin{document}

\pgfmathsetmacro{\minval}{-10}
\pgfmathsetmacro{\maxval}{30}
%\pgfmathsetmacro{\spanval}{\maxval-\minval}
\pgfmathsetmacro{\colstep}{100/(\maxval-\minval)}

\begin{tikzpicture}
\foreach \x/\y/\z in {
1/1/5,
1/2/-6,
1/3/-10,
1/4/12,
1/5/27,
1/6/17,
1/7/25,
1/8/-7,
1/9/14,
1/10/8,
1/11/21,
1/12/-6,
1/13/-4,
1/14/3,
1/15/0,
2/1/-2,
2/2/-9,
2/3/10,
2/4/7,
2/5/-6,
2/6/-4,
2/7/9,
2/8/15,
2/9/-4,
2/10/26,
2/11/5,
2/12/-3,
2/13/3,
2/14/27,
2/15/18,
3/1/4,
3/2/12,
3/3/-6,
3/4/22,
3/5/7,
3/6/23,
3/7/-8,
3/8/10,
3/9/-2,
3/10/12,
3/11/30,
3/12/30,
3/13/28,
3/14/28,
3/15/7,
4/1/13,
4/2/-2,
4/3/26,
4/4/-4,
4/5/4,
4/6/8,
4/7/-3,
4/8/-5,
4/9/22,
4/10/10,
4/11/25,
4/12/-6,
4/13/-5,
4/14/-3,
4/15/-9,
5/1/5,
5/2/10,
5/3/8,
5/4/23,
5/5/-3,
5/6/-1,
5/7/-2,
5/8/-8,
5/9/22,
5/10/8,
5/11/3,
5/12/-10,
5/13/29,
5/14/14,
5/15/-6,
6/1/28,
6/2/-2,
6/3/21,
6/4/-8,
6/5/14,
6/6/-4,
6/7/22,
6/8/25,
6/9/-9,
6/10/20,
6/11/-3,
6/12/3,
6/13/11,
6/14/18,
6/15/5,
7/1/19,
7/2/6,
7/3/-10,
7/4/-1,
7/5/10,
7/6/7,
7/7/0,
7/8/30,
7/9/-9,
7/10/25,
7/11/29,
7/12/12,
7/13/21,
7/14/-6,
7/15/13,
8/1/5,
8/2/27,
8/3/18,
8/4/-6,
8/5/5,
8/6/-8,
8/7/9,
8/8/8,
8/9/10,
8/10/24,
8/11/25,
8/12/0,
8/13/29,
8/14/15,
8/15/27,
9/1/21,
9/2/26,
9/3/14,
9/4/-8,
9/5/8,
9/6/-2,
9/7/28,
9/8/6,
9/9/22,
9/10/20,
9/11/13,
9/12/6,
9/13/18,
9/14/-1,
9/15/-3,
10/1/-3,
10/2/13,
10/3/28,
10/4/22,
10/5/30,
10/6/1,
10/7/0,
10/8/-2,
10/9/19,
10/10/-5,
10/11/11,
10/12/14,
10/13/-1,
10/14/27,
10/15/-8,
11/1/13,
11/2/-4,
11/3/20,
11/4/20,
11/5/26,
11/6/1,
11/7/11,
11/8/1,
11/9/11,
11/10/6,
11/11/14,
11/12/5,
11/13/-5,
11/14/-1,
11/15/18,
12/1/18,
12/2/27,
12/3/-9,
12/4/18,
12/5/10,
12/6/26,
12/7/-1,
12/8/-3,
12/9/25,
12/10/-8,
12/11/9,
12/12/11,
12/13/10,
12/14/16,
12/15/5,
13/1/18,
13/2/-2,
13/3/4,
13/4/-3,
13/5/21,
13/6/7,
13/7/5,
13/8/1,
13/9/21,
13/10/-8,
13/11/-4,
13/12/24,
13/13/4,
13/14/16,
13/15/20,
14/1/24,
14/2/25,
14/3/17,
14/4/0,
14/5/-9,
14/6/9,
14/7/-4,
14/8/13,
14/9/25,
14/10/23,
14/11/2,
14/12/-4,
14/13/11,
14/14/-2,
14/15/-7,
15/1/13,
15/2/25,
15/3/-6,
15/4/26,
15/5/-1,
15/6/18,
15/7/12,
15/8/-7,
15/9/9,
15/10/-3,
15/11/25,
15/12/14,
15/13/12,
15/14/12,
15/15/19}
{
\pgfmathsetmacro{\ptcol}{\colstep*(\z-\minval)}
\fill[orange!\ptcol!blue] (\x/4-0.25,\y/4-0.25) rectangle (\x/4,\y/4);
}
\end{tikzpicture}

\end{document}

Which produces:

enter image description here

The main problems would then be:

  • formatting the input data to x/y/z, shouldn't be too hard
  • multiple colors to cycle through, should be possible, at least I have an idea how to
  • hexagonal grid (if this is required); especially interesting would be the raw data format for this
  • possible TeX size restrictions; e.g. a plot with 200 x 200 points would have 40000 points, at some point capacity may be exceeded
  • the frames, ticks, scales and the "value bar" (or whatever you call it) should not be too problematic

So it would be nice if you specified your input format, and could go a lot more in detail if the hexagonal grid is requested / required.


Edit 1: Here is a little more advanced sample. You now can give your data as a comma separated list, everything except for the spy is then drawn automatically. I have to warn you though, it is really, really slow, apparently it's not a good idea looking up array indices:

\documentclass[parskip]{scrartcl}
\usepackage[margin=15mm]{geometry}
\usepackage{tikz}
\usetikzlibrary{calc,shadings,spy}

\begin{document}

\pgfmathsetmacro{\minval}{-10}
\pgfmathsetmacro{\maxval}{30}
\pgfmathsetmacro{\zlsteps}{10}
\pgfmathsetmacro{\colstep}{100/(\maxval-\minval)}
\pgfmathsetmacro{\ptsize}{0.5}
\pgfmathsetmacro{\xsize}{15}
\pgfmathsetmacro{\ysize}{15}
\pgfmathsetmacro{\xlmin}{4}
\pgfmathsetmacro{\xlmax}{8}
\pgfmathsetmacro{\ylmin}{5}
\pgfmathsetmacro{\ylmax}{11}
\pgfmathsetmacro{\xlsteps}{5}
\pgfmathsetmacro{\ylsteps}{7}
\newcommand{\zmaxcol}{orange}
\newcommand{\zmincol}{gray}
\def\valarray{{5,-8,-10,-4,30,11,24,-9,13,22,5,23,-3,-8,12,-3,22,7,28,24,23,11,17,-4,24,11,19,15,-2,8,0,%
-6,26,27,-10,24,6,-6,10,12,17,29,-8,22,20,30,27,-1,0,27,8,13,4,10,8,30,-4,-6,6,26,11,0,-4,-2,17,27,17,%
-5,8,-7,-5,24,30,6,22,3,30,8,-10,8,11,28,-8,6,24,17,1,-2,26,-1,25,27,25,15,19,15,-7,2,29,14,21,25,-7,24,%
19,14,19,15,8,-6,-4,-7,28,15,7,3,6,2,-10,-9,22,18,-7,15,2,27,9,15,11,0,-7,-5,-8,24,-6,16,10,10,8,26,-4,%
6,-4,20,21,0,16,10,2,-4,3,-9,-3,21,16,-9,30,24,13,20,29,29,11,4,5,4,8,24,22,28,8,-1,1,6,30,-7,16,-6,30,%
12,-8,-4,-4,20,-4,-5,14,28,-4,28,15,14,7,7,9,14,-9,12,8,7,0,15,9,2,-10,28,22,3,-2,19,30,25,1,-9,26,12,%
25,11,15,16,-4,7,17,28,7}}

\begin{tikzpicture}[spy using outlines={circle, magnification=4, size=4cm, connect spies}]
\pgfmathsetmacro{\xdec}{\xsize-1}
\pgfmathsetmacro{\ydec}{\ysize-1}
\foreach \x in {0,...,\xdec}
  { \foreach \y in {0,...,\ydec}
    { \pgfmathsetmacro{\ptcol}{\colstep*(\valarray[\y*\xsize+\x]-\minval)}
      \fill[\zmaxcol!\ptcol!\zmincol] (\x*\ptsize,\y*\ptsize) rectangle (\x*\ptsize+\ptsize,\y*\ptsize+\ptsize);
    }
  }
\draw (0,0) rectangle (\xsize*\ptsize,\ysize*\ptsize);
\pgfkeys{/pgf/number format/.cd,fixed zerofill,precision=2}
\foreach \x in {0,...,\xlsteps}  
{ \pgfmathsetmacro{\xlval}{(\xlmax-\xlmin)/\xlsteps*\x+\xlmin}
  \draw (\xsize/\xlsteps*\x*\ptsize,0) -- (\xsize/\xlsteps*\x*\ptsize,-0.2) node[right,rotate=-90] {\pgfmathprintnumber{\xlval}};
}
\foreach \y in {0,...,\ylsteps}  
{ \pgfmathsetmacro{\ylval}{(\ylmax-\ylmin)/\ylsteps*\y+\ylmin}
  \draw (0,\ysize/\ylsteps*\y*\ptsize) -- (-0.2,\ysize/\ylsteps*\y*\ptsize) node[left] {\pgfmathprintnumber{\ylval}};
}
\draw[top color=\zmaxcol,bottom color=\zmincol] (\xsize*\ptsize+0.5,0) rectangle (\xsize*\ptsize+1.5,\ysize*\ptsize);
\foreach \z in {0,...,\zlsteps}  
{ \pgfmathsetmacro{\zlval}{(\maxval-\minval)/\zlsteps*\z+\minval}
  \draw (\xsize*\ptsize+1.5,\ysize*\ptsize/\zlsteps*\z) -- (\xsize*\ptsize+1.7,\ysize*\ptsize/\zlsteps*\z) node[right] {\pgfmathprintnumber{\zlval}};
}
\spy [blue, size=4cm] on (3,2) in node [right] at (4,9);
\end{tikzpicture}

\end{document}

Output:

enter image description here


The same with \pgfmathsetmacro{\xsize}{25} and \pgfmathsetmacro{\ysize}{9}:

enter image description here

share|improve this answer
    
If the computation of the images takes such a long time, you may want to take a look at the pgfmanual (p. 500 Ch. 63), there is at least a possibility to externalize (and hence precompute only when it changes) the graphics. –  Ronny Jan 27 '12 at 8:25
    
Yes, I know about the externalize library, but as far as I know it doesn't redo the externalized graphichs upon change. When I tried it a while back, I had to delete the .pdf containining the externalized graphic to get it recomputed. So I think it is meant for "finished graphics you don't plan to work on anymore, or am I wrong? –  Tom Bombadil Jan 27 '12 at 9:29
    
@TomBombadil: You can force the external library to recreate an image by preceding it with \tikzset{external/remake next}, or to recreate all images starting with the next by setting \tikzset{external/force remake}. –  Jake Jan 27 '12 at 10:07
    
Very interesting, didn't know that, but it will be very helpful. Thanks a lot! –  Tom Bombadil Jan 27 '12 at 10:23
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.