33

I want to have in Mathematica the same result I have in Python: enter image description here

I have this nice effect simply by using very thin lines. But it seems in Mathematica thickness property has some limit and i just got this:

xy = RandomReal[1, {10000, 2}];
ListLinePlot[xy, PlotStyle -> Thickness@10^-5]

enter image description here

Playing with opacity doesn't help. I can't figure out how to reproduce this effect..

Alexey Popkov
  • 61,809
  • 7
  • 149
  • 368
funnyp0ny
  • 1,905
  • 14
  • 21
  • 2
    python has no built in plot. you ought to specify what module you are using – george2079 Nov 21 '14 at 12:31
  • 3
    It's matplotlib – funnyp0ny Nov 21 '14 at 12:55
  • @funnypony Under which operating system have you taken the screenshot? – Alexey Popkov Nov 21 '14 at 17:19
  • 1
    Nice pict. It can be used as wallpaper to simulate an erased blackboard. – Sigur Nov 21 '14 at 18:40
  • 2
    @AlexeyPopkov Win7 (IPython notebook from last python xy). – funnyp0ny Nov 21 '14 at 22:21
  • Can you please include the full Python code, cannot reproduce with the snippet you posted. – BioGeek Dec 15 '14 at 12:22
  • 1
    @BioGeek actually this is full code in IPython. In contrast with ordibary python.exe it automatically imports many libraries like numpy and matplotlib. If you want to do it manually - you need numpy and matplotlib. Then just add these 2 lines in the beginning: from numpy import random; from matplotlib.pyplot import plot, show and add this in the end: show(). It should work – funnyp0ny Dec 16 '14 at 12:00
  • One small thing: Thickness@10^-5 doesn't do what you think it does. It evaluates to 1/Thickness[10]^5, which isn't Thickness[10^-5] like you want. – Sjoerd Smit Dec 06 '23 at 11:56
  • @SjoerdSmit Right, thanks for the remark on precedence, I'd have never realize that – funnyp0ny Dec 23 '23 at 17:27

4 Answers4

31

Your comment raises interesting question:

I got everything simply faded and flat, while in the example - its all bright and sharp

I think the problem is related to the fact that Mathematica's graphical functions always work in linear colorspace. Starting from Pickett's solution with better resampling method, in version 10.0.1 we obtain:

$HistoryLength = 0;
xy = RandomReal[1, {10000, 2}];
img = ImageResize[
  Rasterize[
   ListLinePlot[xy, ImageSize -> 10000, 
    PlotStyle -> Directive[AbsoluteThickness[1],(*Opacity[.5],*)Blue]], "Image"], 
  300, Resampling -> {"Lanczos", 30}]

img

This image is obtained in the linear RGB colorspace while our monitors work in the sRGB colorspace. The problem is discussed in some details in this question of mine. We may apply a gamma correction as a quick-and-dirty way to fix this:

img2 = ImageApply[#^1.3 &, img]

img2

Still far from ideal. Playing with Resampling and using more correct method of converting the linear RGB into sRGB can help to produce better colors.


UPDATE: A detailed analysis

I have found that Resampling methods "Constant" and "Linear" better reproduce the Python's result. Increasing the ImageSize (i.e. decreasing the actual thickness of the lines) also helps (but the memory required for the rasterization grows as the square of ImageSize!):

$HistoryLength = 1;
xy = RandomReal[1, {10000, 2}];
img = ImageResize[
  Rasterize[
   Style[ListLinePlot[xy, ImageSize -> 15000, AspectRatio -> 224/336, 
     PlotStyle -> Directive[AbsoluteThickness[1], Blue], 
     Axes -> False, PlotRangePadding -> 0], Antialiasing -> False], 
   "Image"], 336, Resampling -> "Constant"]

img

Rescaling color intensities to run from 0 to 1 significantly improves the appearance:

img = Image[Rescale[ImageData[img]]]

img

Compare with the Python's result:

origImgCrop = 
 ImageTake[
  Import["https://i.stack.imgur.com/ycM0u.png"], {97, 310}, {42, 367}]

Python's image

The difference is still noticeable. One possible reason is insufficient ImageSize but I cannot check this directly because ImageSize larger than 15000 will kill my system with 8 Gb of physical memory. Let us crop the img too and compare the horizontal lightness distributions in the images:

imgCrop = ImageTake[img, {6, -6}, {6, -6}]

imgCrop

imgCrop // ImageDimensions
origImgCrop // ImageDimensions
{326, 214}
{326, 214}

Mean horizontal lightness distributions for Python's (blue points) and Mathematica's (orange points) outputs can be computed by taking the intensity values of the first RGB channel (the Red channel) because the first and the second channels contain identical values and actually describe the lightness:

origHorSum = 
  Total[#]/Length[#] &@
   ImageData[origImgCrop, Interleaving -> True][[;; , ;; , 1]];
horSum = Total[#]/Length[#] &@
   ImageData[imgCrop, Interleaving -> True][[;; , ;; , 1]];

ListPlot[{origHorSum, horSum}, Frame -> True, PlotRange -> {0, 1}]

plot

Let us see how this plot changes if we set ImageSize to 10000:

plot for ImageSize->10000

The same for ImageSize -> 8000:

plot for ImageSize->8000

From these comparisons I conclude that we cannot reproduce the Python's appearance just by increasing ImageSize.

And finally, let us look at the "natural" appearance of the image obtained with ImageSize->15000 by converting it into the sRGB colorspace (the function linear2srgb is implemented by Jari Paljakka and can be found in this answer):

ImageApply[linear2srgb, imgCrop]

sRGB image obtained with ImageSize->15000


UPDATE 2: simulating an erased blackboard

In the comments Sigur expressed the idea that this type of plot simulates an erased blackboard and can be used as a background for slides. In PowerPoint 2003 (which I currently use) slides by default have size 25.4x19.05 cm with AspectRatio -> 1905/2540. For obtaining a 1680 pixels wide background images the above code can be modified as follows:

$HistoryLength = 0;
xy = RandomReal[1, {10000, 2}];
img = ImageResize[
  Rasterize[
   Style[ListLinePlot[xy, ImageSize -> 15000, 
     AspectRatio -> 1905/2540, 
     PlotStyle -> Directive[AbsoluteThickness[1], Black], 
     Axes -> False, PlotRangePadding -> 0], Antialiasing -> False], 
   "Image"], 1680, Resampling -> "Constant"];
img = Image[Rescale[ImageData[img]]]
Export["erased blackboard.png", img]
img2 = ImageApply[linear2srgb, img]
Export["erased blackboard (sRGB).png", img2]

Optimized PNG files can be downloaded here: "erased blackboard.png", "erased blackboard (sRGB).png".


UPDATE 3: more about the erased blackboard

It seems that inverting the colors and blurring produces an image that feels more like true erased blackboard. With blur we need not lossless PNG anymore and can use lossy JPG compression to reduce the file size. Here is a way to do everything in Mathematica (images are clickable!):

$HistoryLength = 0;
xy = RandomReal[1, {10000, 2}];
img = ImageResize[
   Rasterize[
    Style[ListLinePlot[xy, ImageSize -> 15000, 
      AspectRatio -> 1905/2540, 
      PlotStyle -> Directive[AbsoluteThickness[1], White], 
      Axes -> False, PlotRangePadding -> 0, Background -> Black], 
     Antialiasing -> False], "Image"], 1680, Resampling -> "Constant"];
imgBlur = Blur[Image[Rescale[ImageData[img]]], 3]
Export["erased blackboard blurred.jpg", imgBlur]

erased blackboard blurred.jpg

linear2srgb = 
 Compile[{{Clinear, _Real, 1}}, 
  With[{\[Alpha] = 0.055}, 
   Table[Piecewise[{{12.92*C, 
       C <= 0.0031308}, {(1 + \[Alpha])*C^(1/2.4) - \[Alpha], 
       C > 0.0031308}}], {C, Clinear}]], 
  RuntimeAttributes -> {Listable}]; imgBlur2 = 
 ImageApply[linear2srgb, imgBlur]
Export["erased blackboard blurred (sRGB).jpg", imgBlur2]

erased blackboard blurred (sRGB).jpg

Alexey Popkov
  • 61,809
  • 7
  • 149
  • 368
  • Wow! Thanks a lot! I'd never have thought this way. This is really a nice tool for additional tweaking of graphics. – funnyp0ny Nov 20 '14 at 22:59
  • I updated the answer with an extended analysis of the situation. – Alexey Popkov Nov 21 '14 at 16:47
  • @AlexeyPopkov, I got No more memory available. I have 4gb of memory. How to execute your code above? – Sigur Nov 22 '14 at 17:11
  • @Sigur You need at least 8 Gb of physical memory for evaluating the code in my answer. Having only 4 Gb you need to use special technique (incremental rendering) for reducing memory requirements: see Section "EDIT 4" in this answer. – Alexey Popkov Nov 22 '14 at 17:17
  • @AlexeyPopkov, thanks. I tried with 1000 instead of 10000 and the program is still running. Let's see. With your code, the output would be an image with 15000 of resolution?! I'd like to produce an image with black/white colours to use as background on slides similar to a erased blackboard. – Sigur Nov 22 '14 at 17:20
  • 1
    @Sigur With my code you get a 336x224 pixels raster images. In principle you can just take an image from my answer and use ColorConvert for obtaining a grayscale version of it. Use Binarize for obtaining a black&white version. But probably 336x224 pixels size is insufficient for your purposes. – Alexey Popkov Nov 22 '14 at 17:26
  • @Sigur For your pleasure I have generated a 1500 pixels wide version and uploaded it here. The same image with "natural" colors after converting to sRGB colorspace is here. – Alexey Popkov Nov 22 '14 at 17:56
  • @AlexeyPopkov, thanks so much for the gifts. I got it. I was generating images with fewer points and saving. After some 10 images I would merge them using GIMP. Your approach was faster. Nice! – Sigur Nov 22 '14 at 18:04
  • 1
    @Sigur I added the "UPDATE 2" section in my answer dedicated to your idea. – Alexey Popkov Nov 22 '14 at 23:43
  • 2
    @AlexeyPopkov after some processing your image looks even cooler: http://i.imgur.com/1p5sEDr.jpg – funnyp0ny Nov 23 '14 at 20:04
  • 1
    @funnypony Now it is true blackboard! BTW, I notice that your image is blurred probably due to lossy conversion to JPG automatically applied by imgur.com (or you have made it intentionally?). I am not sure whether blurred version is better or worse as a background for slides. What do you think? – Alexey Popkov Nov 23 '14 at 21:30
  • @AlexeyPopkov oh no imgur.com by no means touches uploading images. It's me who simply applied several filters in photoshop. I converted it in jpg only 'cause it reduced file size 4 times. I argee blurring is unnecessary – funnyp0ny Nov 23 '14 at 21:41
  • @funnypony What was the idea? I see also a little of warm yellow added. The difference is just noticeable though. – Alexey Popkov Nov 23 '14 at 21:45
  • 1
    @AlexeyPopkov well blurring, sepia and vignette are just most common and straightforward effects one can apply to get a new feeling of an image. generally no particular idea) – funnyp0ny Nov 23 '14 at 21:53
  • @funnypony I have no experience with Photoshop filters and I find your result useful. Upon reflection I am inclined to believe that the blurred version should be better as a background for slides, because clear text in the foreground will be better emphasized. I am not sure what vignette filter does but sepia probably added a little of yellow. – Alexey Popkov Nov 23 '14 at 22:00
  • @AlexeyPopkov, thanks. I came here to write about the black colour but funnypony already did it. Nice! I guess that some blur or emboss could make the white lines look more like erased chalk. Like white clouds instead of white thin lines. Anyway, thanks and cong. for the good result. – Sigur Nov 24 '14 at 12:56
  • My bad! I guess I misread. I was talking about the lightness plots. – Öskå Nov 24 '14 at 14:11
  • @Öskå I added an explanation of the lightness plots. – Alexey Popkov Nov 24 '14 at 14:16
  • Thanks! I guess some axes label or a legend would have done it :) – Öskå Nov 24 '14 at 14:17
18

On-screen, lines are always at least 1 pixel wide in Mathematica, regardless of the thickness setting. Not sure what you tried with Opacity, as it seems to be possible to achieve the same effect:

PlotStyle -> Directive[AbsoluteThickness[1], Opacity[.05]]

Mathematica graphics

Szabolcs
  • 234,956
  • 30
  • 623
  • 1,263
10

You tried to decrease the width of the lines to below the minimum width. In order to achieve the same effect you can increase the size of the image instead.

x = RandomReal[1, 10000];
y = RandomReal[1, 10000];
Show[ImageResize[Rasterize@ListLinePlot[{Thread@{x, y}}, ImageSize -> 10000], 300], ImageSize -> 300]

example

C. E.
  • 70,533
  • 6
  • 140
  • 264
  • thx, but it has same problems as in previous answer (see comment) – funnyp0ny Nov 20 '14 at 21:21
  • 1
    @funnypony The default colors in Mathematica are not the same as the default colors in Python. For example if you set the color to Blue (PlotStyle->Blue) they look similar. – C. E. Nov 20 '14 at 21:24
  • yes, now i think its right (sorry i mark previous answer due to priority). i made some tests - it seems python draws a little denser towards center.. http://i.imgur.com/BfW29S9.png – funnyp0ny Nov 20 '14 at 22:17
  • @funnypony Out of curiosity, why do you need to reproduce matplotlib's result with such fidelity? If it's really important to have the exact same output, why not just use matplotlib? Also, I guess matplotlib's output will depend on the precise rendering method and might easily change in the future. – Szabolcs Nov 21 '14 at 16:50
  • @Szabolcs no, I don't need 'most idential plot ever') Initial idea was just to get something more or less similar to Python's plot - you can see my fail picture in the question, so solution with low opacity and pure blue color is completely fine. – funnyp0ny Nov 21 '14 at 22:15
0

The OP has probably meant:

xy = RandomReal[1, {10000, 2}];
ListLinePlot[xy, PlotStyle -> Thickness@0.00001]

or

xy = RandomReal[1, {10000, 2}];
ListLinePlot[xy, PlotStyle -> Thickness@(10^-5)]

This seems to make a major difference, at least in Mathematica 13.2. Apparently "Thickness@10^-5" is not recognized properly.

Maciej
  • 1
  • 2
  • Please include the plot to demonstarate that your approach works. – bbgodfrey Dec 06 '23 at 01:58
  • Thickness@10^-5 evaluates to 1/Thickness[10]^5. It's a syntax typo. – Sjoerd Smit Dec 06 '23 at 11:57
  • Thanks for noticing that! It did work on some previous mathematica, where I'd actually tested the script, but not anymore. @ operator has high precedence, so it evaluates first exactly as Sjoerd Smit written. – funnyp0ny Dec 23 '23 at 17:33