7

I have a 50x300 binary marix, which I want to display as a colored grid. I tried the approaches of drawing a large binary matrix as colored grid which I like, but

  • the approach using pgfplots table is too large, resizebox results in an out of memory error and I couldn't find an appropriate solution to adjust the cell size of the table in pgfplotsset. setting the fontsize as tinz as possible did not suffice, and
  • the tikz-matrix approach results in a compile timeout.

I have really no idea what to do now.. Increasing the memory assignment seems too hacky for me, isn't there a more elegant option? I also would like to stick to the pgfplots approach..

g.kov
  • 21,864
  • 1
  • 58
  • 95
Sibylse
  • 299
  • 1
    Using the solution in the top answer of the linked question, I can draw a 50x300 matrix with \drawgrid[one color=black,zero color=white,cell wd=2pt,cell ht=2pt]{\matrixfile}; however, it takes quite some time and a lot of space, of course. The thing is, that you can not have a huge chunk of data and think it will not take up space ;-) What are you trying to do exactly? – Philipp Imhof Sep 01 '15 at 14:13
  • Hm, I get a "TeX capacity exceeded, sorry [main memory size=5000000]." error.. I'd like to produce a picture of my data like the picture on the first page of this paper: (http://epubs.siam.org/doi/pdf/10.1137/1.9781611972801.15) – Sibylse Sep 01 '15 at 14:20
  • What format is desired/required for the matrix input? – Steven B. Segletes Sep 01 '15 at 14:33
  • To me, this looks more like a plot that like a drawing. – Philipp Imhof Sep 01 '15 at 15:00
  • Format doesn't matter, could convert to anything. Right now I have a csv with zeros and ones. A plot that looks like a colored binary matrix would also be fine, as long its looking good ;) – Sibylse Sep 01 '15 at 15:21
  • @Sibylse, try Imhof's with lualatex to void the memory overflow. – alfC Sep 01 '15 at 18:27
  • See this question on "pixel art" images: http://tex.stackexchange.com/questions/157080/can-tikz-create-pixel-art-images – Steven B. Segletes Apr 03 '17 at 11:30

4 Answers4

6

This is MWE using Asymptote:

enter image description here

The sample 30x500 file was generated with

// 
// "gendata.asy" :
//
int m=30, n=500;
file fout=output("binmatrix.txt");
srand(1717177);
string s;
for(int i=0;i<m;++i){
  s="";
  for(int j=0;j<n;++j){
    s+=string(round(unitrand()));
  }
  write(fout,s+'\n');
}
flush(fout);
close(fout);

And the Asymptote code for the image is

//
// "m1.asy" :
// 
settings.tex="pdflatex";
file fin=input("binmatrix.txt"); 

string[] s=fin;

int m=s.length, n=length(s[1]);

real h=1cm;
real w=h/m*n;
size(w,h);

import graph;
import palette;
real[][] v=new real[n][m];
for(int i=0; i < m; ++i){
  for(int j=0; j < n; ++j){
    v[j][i]=(real)substr(s[i],j,1);
  }
}
pen[] Palette=new pen[]{deepblue,orange};
bounds range=image(v,(0,0),(n,m),Palette);

You can also combine bits into colors, for example, like this:

settings.tex="pdflatex";
file fin=input("binmatrix.txt"); 

string[] s=fin;

int m=s.length, n=length(s[1]);

real h=1cm;
real w=h/m*n/3;
size(w,h);

import graph;
import palette;
pen[][] v=new pen[(int)(n/3)][m];
for(int i=0; i < m; ++i){
  for(int j=0; j < (int)(n/3); ++j){
    v[j][i]=rgb((real)substr(s[i],3*j,1),(real)substr(s[i],3*j+1,1),(real)substr(s[i],3*j+2,1));;
  }
}
image(v,(0,0),(n/3,m)); 

enter image description here

g.kov
  • 21,864
  • 1
  • 58
  • 95
4

If you want efficiency, primitive is generally better. Note, the Op for this question specified tikz in the solution.

\documentclass{standalone}
\usepackage{xcolor}

\newlength{\cellwidth}
\newlength{\cellheight}
\let\END=\eof

\newcommand{\colormatrix}[1]% #1 = binary matrix
{\parbox{\CMcolumns\cellwidth}{%
  \baselineskip=\cellheight
  \lineskip=0pt
  \def\one{1}%
  \def\zero{0}%
  \bgroup
    \countdef\col=1
    \col=0
    \CMParse#1\END
  \egroup
}}

\def\CMParse#1{\ifx#1\END\else
  \if#1\one\relax{\color{\onecolor}\rule{\cellwidth}{\cellheight}}\fi
  \if#1\zero\relax{\color{\zerocolor}\rule{\cellwidth}{\cellheight}}\fi
  \advance\col by 1
  \ifnum\col<\CMcolumns\relax\else
    \hfil
    \col=0
  \fi
\expandafter\CMParse\fi}% expand \fi first

\newcommand{\setcolormatrix}[6]% #1=width, #2=height, #3=number columns, #4=number rows, #5=one color, #6=zero color
{\global\cellwidth=\dimexpr #1/#3\relax
 \global\cellheight=\dimexpr #2/#4\relax
 \global\def\CMcolumns{#3}%
 \global\def\onecolor{#5}%
 \global\def\zerocolor{#6}%
}

\begin{document}
\setcolormatrix{1in}{1in}{11}{7}{blue}{yellow}%
\colormatrix{%
10110101010
10010101010
01010111010
11110010100
01100011001
11101010111
10101010111}

\end{document}

binary matrix


The file image.tex (created by the editor) consists of

10110101010
10010101010
01010111010
11110010100
01100011001
11101010111
10101010111

and the updated solution is given by

\documentclass{standalone}
\usepackage{xcolor}

\newlength{\cellwidth}
\newlength{\cellheight}
\newread\imagefile
\let\END=\eof

\newcommand{\colormatrix}[1]% #1 = filename
{\parbox{\CMcolumns\cellwidth}{%
  \baselineskip=\cellheight
  \lineskip=0pt
  \def\one{1}%
  \def\zero{0}%
  \def\empty{\par}%
  \openin\imagefile=#1
  \loop\ifeof\imagefile\else
    \read\imagefile to \buffer%
    \ifx\buffer\empty\relax\else
      \expandafter\CMParse\buffer\END
      \hfil
    \fi
  \repeat
  \closein\imagefile
}}

\long\def\CMParse#1{\ifx#1\END\else
  \if#1\one\relax{\color{\onecolor}\rule{\cellwidth}{\cellheight}}\fi
  \if#1\zero\relax{\color{\zerocolor}\rule{\cellwidth}{\cellheight}}\fi
\expandafter\CMParse\fi}% expand \fi first

\newcommand{\setcolormatrix}[6]% #1=width, #2=height, #3=number columns, #4=number rows, #5=one color, #6=zero color
{\global\cellwidth=\dimexpr #1/#3\relax
 \global\cellheight=\dimexpr #2/#4\relax
 \global\def\CMcolumns{#3}%
 \global\def\onecolor{#5}%
 \global\def\zerocolor{#6}%
}

\begin{document}
\setcolormatrix{1in}{1in}{11}{7}{blue}{yellow}%
\colormatrix{image}

\end{document}
John Kormylo
  • 79,712
  • 3
  • 50
  • 120
  • Looks promising! Unfortunately, I'm too stupid to make this work when the matrix is stored in another file. Tried filecontents and a new command.. nothing worked. Could you please tell me how to integrate this properly? – Sibylse Sep 02 '15 at 09:37
  • A revised solution using file I/O has been added. – John Kormylo Sep 02 '15 at 15:43
1

You might consider using imagemagick for this. For example, you could format your data in a plain PGM format.

File "sample.pgm"

P2
8 8
1
0 0 0 0 0 0 0 0
0 1 1 1 1 1 1 0
0 1 0 0 0 0 1 0
0 1 0 1 1 0 1 0
0 1 0 1 1 0 1 0
0 1 0 0 0 0 1 0
0 1 1 1 1 1 1 0
0 0 0 0 0 0 0 0

Converting it with imagemagick using the following command.

convert sample.pgm -scale 320x320 sample.bmp

results in the following bitmap.

enter image description here

James
  • 4,587
  • 1
  • 12
  • 27
  • Nice idea. What about: "No line should be longer than 70 characters." ? – Philipp Imhof Sep 01 '15 at 15:36
  • Good call. I didn't notice that requirement. Maybe it would be easy for the OP to list one pixel per line. Maybe there is another raw ascii image format that doesn't have the 70 char/line limit? – James Sep 01 '15 at 15:42
  • @PhilippImhof: Actually I just violated the 70 char/line requirement and imagemagick didn't mind at all. Maybe some image readers wouldn't like it, but for imagemagick it doesn't seem to be an issue. – James Sep 01 '15 at 15:47
  • I just re-read the page you linked to. It says "should", so that's not a very strict limit and I thought there might be some hope... :) – Philipp Imhof Sep 01 '15 at 15:49
1

Using \pdfliteral to produce inline image is, I believe, the most efficient way.

The drawback is that each small square is represented by two characters.

The idea comes from this question: Include PDF via \pdfliteral

\pdfcompresslevel0
\documentclass{article}
\begin{document}
\hbox to 10cm{%
    \immediate\pdfliteral{
        q
            11 0 0 7 0 0 cm            % input width = 11px;
                                       % input height = 7px
            10 0 0 3 0 0 cm            % output width = 10cm
                                       % output height = 3cm
            2.57693 0 0 2.57693 0 0 cm % magic number
            BI
                /W 11                  % input width = 11px;
                /H 7                   % input height = 7px
                /CS [
                    /Indexed /RGB
                    1                  % = using 2 colors
                                       % maximal is 255 = using 256 colors
                    <FF0000 0000FF>    % red and blue
                ]
                /BPC 8
                /F /AHx
                /I false
            ID
                01 00 01 01 00 01 00 01 00 01 00
                01 00 00 01 00 01 00 01 00 01 00
                00 01 00 01 00 01 01 01 00 01 00
                01 01 01 01 00 00 01 00 01 00 00
                00 01 01 00 00 00 01 01 00 00 01
                01 01 01 00 01 00 01 00 01 01 01
                01 00 01 00 01 00 01 00 01 01 01
                >
            EI
        Q
    }
    \hfill
}\vbox to3cm{}

\bigskip

\end{document}

Symbol 1
  • 36,855