15
$\begingroup$

I have a rectangular matrix, which is m-by-10. Each element is either 0 or 1. I would like 0 to correspond to white elements, and 1 to red elements. This works fine if m = 100 or similar small values:

m = 100;
list = Table[Table[RandomInteger[], {j, 1, 10}], {i, 1, m}];
Tally[Flatten[list]]
MatrixPlot[list, FrameTicks -> None, ImageSize -> {300, 300}, 
 ColorRules -> {0 -> White, 1 -> Red}]

MP1

However, if I choose m = 200, the coloring becomes strange and no longer only white or red:

m = 200;
list = Table[Table[RandomInteger[], {j, 1, 10}], {i, 1, m}];
Tally[Flatten[list]]
MatrixPlot[list, FrameTicks -> None, ImageSize -> {300, 300}, 
 ColorRules -> {0 -> White, 1 -> Red}]

MP2

Why do I see orange if each element is either 0 or 1? Is there any way I can correct this so that the only colors that appear are white or red?

Setting ColorFunctionScaling -> False does not seem to correct the problem:

MP3

$\endgroup$
  • 2
    $\begingroup$ Did you try with ArrayPlot? $\endgroup$ – Dr. belisarius Jun 9 '12 at 16:59
  • 1
    $\begingroup$ Try MatrixPlot[data, Frame -> False, MaxPlotPoints -> Infinity] and MatrixPlot[data, Frame -> False, ColorFunction -> Hue, MaxPlotPoints -> Infinity]. I think, what you are seeing is the effect of downsampling combined with interpolation. $\endgroup$ – kglr Sep 12 '17 at 2:58
  • 1
    $\begingroup$ ArrayPlot seems to work as expected. (Also note that for Hue, Hue[0] === Hue[1] === Red, so the appropriate output would be all Red.) $\endgroup$ – aardvark2012 Sep 12 '17 at 3:02
  • 1
    $\begingroup$ Here's a way to confirm what kglr suggests works: MatrixPlot[RandomInteger[1, {10, 300}], Frame -> False, MaxPlotPoints -> Infinity ] // Rasterize // ImageData // Flatten[#, 1] & // DeleteDuplicates // Length. That should be two, showing that allowing it to plot all the points fixes the problem. $\endgroup$ – b3m2a1 Sep 12 '17 at 3:03
  • 1
    $\begingroup$ @aardvark2012 ArrayPlot seems to plot everything (note the much smaller cells). $\endgroup$ – b3m2a1 Sep 12 '17 at 3:04
17
$\begingroup$

Seems that the automatic setting of MaxPlotPoints is too low. You can set it to something high (or even Infinity) to get around this.

m = 200;
list = Table[Table[RandomInteger[], {j, 1, 10}], {i, 1, m}];
Tally[Flatten[list]]
MatrixPlot[list, FrameTicks -> None, ImageSize -> {300, 300}, 
 ColorRules -> {0 -> White, 1 -> Red}, MaxPlotPoints -> ∞]
$\endgroup$
  • 3
    $\begingroup$ From the docs: "With the default setting MaxPlotPoints -> Automatic, sufficiently large or sparse matrices are downsampled so that their structure is visible in the plot generated by MatrixPlot." This seems to be what's happening here, and Mathematica is suitably interpolating colors to go along with this downsampling. $\endgroup$ – J. M. will be back soon Jun 9 '12 at 17:14
  • 1
    $\begingroup$ Looks like MaxPlotPoints needs to only be Max@Dimensions@list, although no harm with using ∞... $\endgroup$ – rm -rf Jun 9 '12 at 17:47
  • 1
    $\begingroup$ Thanks. Although, from reading the documentation, it is not clear to me why downsampling by altering the colors would give a more visible structure. So I don't really understand why Mathematica does this by default. $\endgroup$ – Andrew Jun 9 '12 at 18:16
11
$\begingroup$

Update: How is the default setting for MaxPlotPoints determined?

The function Graphics`ArrayPlotDump`Private`checkMaxpoint is called to get the value of MaxPlotPoints. It takes three arguments. The first argument is the data array. The third argument is True if the calling function is MatrixPlot, False if it is ArrayPlot. The default value of MaxPlotPoints is obtained using Automatic as the second argument.

To illustrate on an example from the original answer below:

SeedRandom[1]
data = RandomInteger[1, {20, 300}];

For this data

{m, n} = Dimensions[data]

{20, 300}

and the default value of MaxPlotPoints for MatrixPlot is

maxpoint = Graphics`ArrayPlotDump`Private`checkMaxpoint[data, Automatic, True]

{200, 200}

For ArrayPlot it is always {∞, ∞} regardless of data (ArrayPlot plots everything):

Graphics`ArrayPlotDump`Private`checkMaxpoint[data, Automatic, False]

{∞, ∞}

The function Graphics`ArrayPlotDump`Private`checkMaxpoint turns the number x returned by the function Graphics`ArrayPlotDump`Private`MatrixPlotMaxPlotPoints into {x, x}.

Graphics`ArrayPlotDump`Private`MatrixPlotMaxPlotPoints[data]

200

The core of this function is just

Min[1000, Max[100, 10  Min[Dimensions[data]]]]

200

So, for MatrixPlot, {1000, 1000} is the maximum possible value for maxpoint regardless of data dimensions.

How is maxpoint used to downsample data?

The function call Graphics`ArrayPlotDump`Private`getCompressedMatrix[data, maxpoint, averaging] uses maxpoint to get the block sizes in vertical and horizontal directions:

{iblksize = Ceiling[m/Min[m, maxpoint[[1]]]], 
 jblksize = Ceiling[n/Min[n, maxpoint[[2]]]]}
{1, 2}

and calls the function Graphics`ArrayPlotDump`Private`downsampleArray with two arguments, data and {iblksize, jblksize} which, in turn, partitions data into iblksize *jblksize blocks and replaces each block with its total value and returns an array with dimensions Dimensions[data]/{iblksize, jblksize} = {20,150}. If averaging is True the calling function Graphics`ArrayPlotDump`Private`getCompressedMatrix process the matrix to replace each array entry by the mean of associated block.

downsampleddata = Graphics`ArrayPlotDump`Private`downsampleArray[data, {1, 2}];
Dimensions[downsampleddata]

{20, 150}

The array downsampleddata is, effectively, the one plotted by MatrixPlot:

ImageData[MatrixPlot[downsampleddata, Frame -> False]] === 
 ImageData[MatrixPlot[data, Frame -> False]]
True

Original answer

Documentation >> MatrixPlot:

  • With the default setting MaxPlotPoints -> Automatic, sufficiently large or sparse matrices are downsampled so that their structure is visible in the plot generated by MatrixPlot.

And Documentation >> MatrixPlot >> Options >> MaxPlotPoints:

  • By default, automatic methods are used to downsample large and/or sparse matrices

Setting the option value for MaxPlotPoints to Infinity or to Dimensions[data] prevents downsampling.

Example:

SeedRandom[1]
data = RandomInteger[1, {20, 300}];

For a small subset of data we see only two colors:

Column[{MatrixPlot[data[[All, ;; 200]], Frame -> False, ImageSize -> 600],
  MatrixPlot[data[[All, ;; 200]], Frame -> False, ColorFunction -> Hue, ImageSize -> 600]}]

matrix plots

For full data we see the effect of downsampling:

Column[{MatrixPlot[data, Frame -> False, ImageSize -> 600],
  MatrixPlot[data, Frame -> False, ColorFunction -> Hue, ImageSize -> 600]}]

matrix plots

Setting the option value for MaxPlotPoints to Infinity or to Dimensions[data] prevents downsampling:

Column[{MatrixPlot[data, Frame -> False, 
   MaxPlotPoints -> Dimensions[data], ImageSize -> 600],
  MatrixPlot[data, Frame -> False, ColorFunction -> Hue, 
   MaxPlotPoints -> Dimensions[data], ImageSize -> 600]}]

matrix plots

$\endgroup$
  • $\begingroup$ I'm curious, why with ColorFunctionScaling -> False we get 2 colors for ColorFunction -> Hue but 3 colors for the default ColorFunction? Code: Tally@Flatten[Cases[MatrixPlot[data,ColorFunction->Hue,ColorFunctionScaling -> False],_Raster,-1][[1,1]],1]. $\endgroup$ – Alexey Popkov Sep 12 '17 at 8:41
  • $\begingroup$ @Alexey, good observation. Don't know the answer off the top of my head. $\endgroup$ – kglr Sep 12 '17 at 8:59
  • $\begingroup$ I would like to merge this question into mathematica.stackexchange.com/questions/6615/… -- please let me know if you agree. $\endgroup$ – Mr.Wizard Sep 12 '17 at 14:47
  • 1
    $\begingroup$ @Mr.Wizard, sure; it is a duplicate of 6615. $\endgroup$ – kglr Sep 12 '17 at 14:51
10
$\begingroup$

As belisarius commented you can use ArrayPlot, which does not compress the range of the data.

list = RandomInteger[1, {10, 300}];

ArrayPlot[list, ColorRules -> {0 -> White, 1 -> Red}, 
 PlotRangePadding -> 0, ImageSize -> 600]

Mathematica graphics

Perhaps better in this case you can also build the image raster directly:

Image[ list /. {0 -> {1, 1, 1}, 1 -> {1, 0, 0}} ]

Mathematica graphics

$\endgroup$
  • 3
    $\begingroup$ As an aside note, I think these beasts are safer when framed. Sometimes there is a deceiving lot of white space at the borders. $\endgroup$ – Dr. belisarius Jun 10 '12 at 8:57
  • $\begingroup$ @belisarius in your opinion is throwing Framed on the second option sufficient? $\endgroup$ – Mr.Wizard Jun 10 '12 at 8:59
  • $\begingroup$ Thank you! Why is it preferable to use Image rather than ArrayPlot? $\endgroup$ – Andrew Jun 10 '12 at 14:14
  • 2
    $\begingroup$ @Andrew it may render and resize faster than the object produced by ArrayPlot, if you don't need the added features such as the frame that belisarius mentioned. It can also be quite flexible as you work with the {Red, Green, Blue} values directly (or optionally another colorspace). $\endgroup$ – Mr.Wizard Jun 10 '12 at 14:47
  • $\begingroup$ @Mr.Wizard Yes. Anything showing a hint of where the "actual" borders are would do. My comment was not about asking you to modify the code, but to warn the OP about taking care of it. +1, BTW $\endgroup$ – Dr. belisarius Jun 10 '12 at 16:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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