rougier / scientific-visualization-book Goto Github PK
View Code? Open in Web Editor NEWAn open access book on scientific visualization using python and matplotlib
Home Page: https://www.labri.fr/perso/nrougier/
License: Other
An open access book on scientific visualization using python and matplotlib
Home Page: https://www.labri.fr/perso/nrougier/
License: Other
Hi @rougier,
Еhere is a slight inconsistency in the code from the book - there is no comma after zorder
argument, but after linestyle
argument there is a comma (technically the latter case is not an error, but usually trailing comma is used with different code formatting):
plt.plot(P[:,0], P[:,1], clip_on=False, zorder=-10
color="k", linewidth=1.0, linestyle="--", )
Perhaps the following code was meant:
plt.plot(P[:,0], P[:,1], clip_on=False, zorder=-10,
color="k", linewidth=1.0, linestyle="--")
Thank you.
Hello,
I found a typo in #23 , and next to it there are two "For example", one next to the other. I think we could reduce repetition by removing or replacing one of these two, but not sure what would be the best solution. Sorry.
Here's where it happens:
Also, maybe it would be clearer to show in the former case that GtkCairo
stands for Gtk3
interface + Cairo
renderer I think? Might be helpful to complete beginners.
Cheers
Bruno
When I run this code,
`import glm
import plot
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
if name == "main":
from matplotlib.patches import Ellipse
from matplotlib.collections import PolyCollection
fig = plt.figure(figsize=(6, 6))
ax = fig.add_axes([0, 0, 1, 1])
camera = glm.camera(25, 45, 1, "perspective")
plot.axis(ax, camera)
np.random.seed(1)
n = 1024
P = 0.2 * np.random.normal(0, 1, (n, 3))
# Bottom shadow
V = glm.transform(P * [1, 0, 1] - [0, 0.5, 0], camera)
T = np.linspace(0, 2 * np.pi, 12)
radius = 0.015
X, Y, Z = radius * np.cos(T), np.zeros(len(T)), radius * np.sin(T)
C = np.c_[X, Y, Z]
polys = []
for i in range(n):
V = glm.transform(C + [P[i, 0], -0.5, P[i, 2]], camera)[:, :2]
polys.append(V)
collection = PolyCollection(
polys, linewidths=0, alpha=0.5, zorder=+10, facecolors="0.5", edgecolor="none"
)
ax.add_collection(collection)
# Actual scatter
V = glm.transform(P, camera)
X, Y, Z = V[:, 0], V[:, 1], V[:, 2]
I = np.argsort(Z)
X, Y = X[I], Y[I]
facecolor = [
(0, 0, 0, 0),
(0, 0, 0, 0),
(0, 0, 0, 0),
mpl.colors.to_rgba("C4"),
(1, 1, 1, 0.25),
(1, 1, 1, 1),
] * len(X)
edgecolor = [
(0, 0, 0, 0.05),
(0, 0, 0, 0.10),
(0, 0, 0, 0.15),
(0, 0, 0, 1.00),
(0, 0, 0, 0.00),
(0, 0, 0, 0.00),
] * len(X)
linewidth = [6, 4, 2, 0.5, 0.0, 0.0] * len(X)
dX = (0, 0, 0, 0, -0.0035, -0.0035) * len(X)
dY = (0, 0, 0, 0, +0.0025, +0.0025) * len(Y)
size = np.array((1, 1, 1, 1, 0.25, 0.05) * len(X)) * 50
X, Y = np.repeat(X, 6), np.repeat(Y, 6)
ax.scatter(
X + dX,
Y + dY,
s=size,
linewidth=linewidth,
zorder=10,
facecolor=facecolor,
edgecolor=edgecolor,
)
plt.savefig("scatter.png", dpi=300)
plt.savefig("scatter.pdf")
plt.show()`
the output shows that module 'glm' has no attribute 'camera'
and module 'plot' has no attribute 'axis'
.
While the links are OK in the original cheat sheet https://github.com/rougier/scientific-visualization-book/blob/master/figures/cheatsheets/cheatsheets.pdf, they get corrupted in the individual sheet 1
https://github.com/rougier/scientific-visualization-book/blob/master/figures/cheatsheets/cheatsheets-1.pdf and hence in the book:
(this may or may not be linked to switch to Font Awesome for icons and brand logos).
scientific-visualization-book/rst/showcase.rst
Lines 42 to 44 in b219a8c
\nicefrac{1}{z}` in the domain :math:`[-2.5, 2.5]^2`. I used the angle
of the (complex) result for setting the color and the absolute cosine
the norm for modulating it periodically.
"the absolute cosine the norm" seem like a typo to me. It's likely the absolute cosine of the norm? As the code roughly does abs(cos(abs(N))
modulo constants.
Otherwise this looks fantastic ! I'm going to try to convince some folks to get it for their grad students bookshelves.
I'd like to start by deeply thanking you @rougier. This book is wonderful, and I thoroughly enjoyed reading it, as I enjoyed reading the NumPy book and investigating the NumPy exercises :)
To my question now: are the figures free to reuse in a commercial setting? I ask because the code of the figures seems to be (BSD) but the book is not (CC-BY-SA-NC). I ask because I'd like to include some of the book figures in some slides I have for a professional training session on matplotlib.
Thanks again for your great work and commitment to open source!
This sentence "Filled contours with dropshadows is a nice effet that allows" has effect misspelled.
Excellent book!
It may help to add "-verbose" in your example of using identify.
scientific-visualization-book/rst/anatomy.rst
Lines 82 to 83 in 00b3467
There are two "have" in:
"You can have have one to many axes per figure and each is usually surrounded by four edges (left, top, right and bottom) that are called spines. "
Congrats on the first public release and thank you for spending time on this book! ❤️
hi, thanks for your work on this awesome book! I just start reading and it helps me much on understanding matplotlib!
by the way, i found a mistake on Scales & projections
It is the code below:
>>> fig = plt.figure(figsize=(6,6))
>>> ax = plt.subplot(1, 1, 1,
aspect=1, xlim=[0,100], ylim=[0,100])
>>> P0, P1, P2, P3 = (0.1, 0.1), (1,1), (10,10), (100,100)
>>> transform = ax.transData.transform
>>> print( (transform(P1)-transform(P0))[0] )
4.185
>>> print( (transform(P2)-transform(P1))[0] )
41.85
>>> print( (transform(P1)-transform(P0))[0] )
418.5
the last one should be:
print( (transform(P3)-transform(P2))[0] )
same issues occurred both on checking "linear scale" and "log scale"
Hi @rougier,
Because Discussions are not enabled for this repository, I decided to share my alternative solution for ridgeline plot exercise as separate issue, because it is a slightly different approach, for clarity I added the comments for each step:
from matplotlib.patches import ConnectionPatch
import matplotlib.pyplot as plt
import numpy as np
# Initial function
def curve():
n = np.random.randint(1,5)
centers = np.random.normal(0.0,1.0,n)
widths = np.random.uniform(5.0,50.0,n)
widths = 10*widths/widths.sum()
scales = np.random.uniform(0.1,1.0,n)
scales /= scales.sum()
X = np.zeros(500)
x = np.linspace(-3,3,len(X))
for center, width, scale in zip(centers, widths, scales):
X = X + scale*np.exp(- (x-center)*(x-center)*width)
return X
# Set random seed and subplots number
RANDOM_STATE = 25
np.random.seed(RANDOM_STATE)
rows = 50
cols = 3
# Configure figure and overlapping axes
fig, axs = plt.subplots(rows, cols, figsize=(10, rows*0.2), subplot_kw={'yticks': []})
plt.subplots_adjust(top=0.95, bottom=0.05, hspace=-0.5, wspace=0.1)
# Label columns with titles and rows with y-axis labels
# https://stackoverflow.com/a/25814386
row_names = [f'Serie {serie}' for serie in range(rows, 0, -1)]
col_names = [f'Value {value}' for value in range(1, cols + 1)]
for ax, name in zip(axs[:, 0], row_names):
ax.set_ylabel(name, rotation=0, fontsize='small', loc='bottom', labelpad=40)
for ax, name in zip(axs[0], col_names):
ax.set_title(name, fontsize='large', fontweight='bold', loc='left', pad=20)
# Control the degree of "softness/pastelness" of the colors (if required)
# https://stackoverflow.com/a/72289062
c = 0
colors = (1. - c) * plt.get_cmap('Spectral')(np.linspace(0, 1, rows)) + c * np.ones((rows, 4))
colors = colors[::-1]
# Plot graphs from left to right, from top to bottom
for idx in range(rows * cols):
i = idx // cols
j = idx % cols
ax = axs[i][j]
ax.set_facecolor('none')
ax.spines[['left', 'top', 'right', 'bottom']].set_visible(False)
if i != rows - 1:
ax.get_xaxis().set_visible(False)
y = curve()
x = np.linspace(-3, 3, y.size)
ax.plot(x, y, color='k', linewidth=1)
ax.fill_between(x, y, color=colors[i])
ax.set_zorder(i)
# Plot vertical lines for each column of subplots
for col_idx in range(cols):
coords = axs[0][col_idx].get_position()
zero_x_coords = (coords.x1 + coords.x0) / 2
conn = ConnectionPatch(xyA=(zero_x_coords, 0.99), xyB=(0, 0),
coordsA='figure fraction', coordsB='data',
axesA=axs[0, col_idx], axesB=axs[rows-1, col_idx],
zorder=rows, linewidth=0.5, linestyle=(0, (8, 2)), color='k')
fig.add_artist(conn)
plt.show()
Output image you can find in Jupyter notebook with exercises for Chapter 1.
Thank you.
Hi, thanks for your excellent book!
It seems to me that the 50th line of coordinates/transforms‐floating‐axis.py, as well as the corresponding line of the code in rst/coordinates.rst,
ax2.set_position((xmin, ymin, xmax - xmin, ymax - xmin))
should read
ax2.set_position((xmin, ymin, xmax - xmin, ymax - ymin))
,
although the difference between ymax-xmin=0.40836979896182274 and ymax-ymin=0.38490475395717544 happens to be small and not apparent in the figure...
By the way, in the official document of Matplotlib there seems to be no description of FloatingAxesHostAxes, of which FloatingSubplot is an alias; I'd be glad if you kindly lead me to it...
Thanks,
Kazuyoshi
Hi @rougier,
If we use the code for the Figure 2.3 from the book, then the border will be inside data coordinates, not outside as expected, and with different tick labels (specifying the code from the book before resolving #63):
fig = plt.figure(figsize=(5, 5), dpi=100)
ax = fig.add_subplot(1, 1, 1, projection='polar')
FC_to_DC = ax.transData.inverted().transform
NDC_to_FC = ax.transAxes.transform
NDC_to_DC = lambda x: FC_to_DC(NDC_to_FC(x))
P = NDC_to_DC([[0,0], [1,0], [1,1], [0,1], [0,0]])
plt.plot(P[:,0], P[:,1], clip_on=False, zorder=-10
color="k", linewidth=1.0, linestyle="--", )
plt.scatter(P[:-1,0], P[:-1,1],
clip_on=False, facecolor="w", edgecolor="k")
plt.show()
But the code in Python file is correct.
I compared the code and find that for displaying the figure there are 2 additional lines in Python file:
And the first line (setting the limits for y-axis and specifying tick labels) is required to get expected figure.
Thank you.
Thank you for the excellent book.
I am getting errors in the text-polar.py from the chapter scales-projections.
ValueError Traceback (most recent call last)
Input In [804], in
57 ax.add_artist(patch)
60 # This could be made through a list but it is easier to red this way
---> 61 label("JANUARY", 0.5 * 2 * np.pi / 12, 1 - 0.5 * size)
62 label("FEBRUARY", 1.5 * 2 * np.pi / 12, 1 - 0.5 * size)
63 label("MARCH", 2.5 * 2 * np.pi / 12, 1 - 0.5 * size)
Input In [804], in label(text, angle, radius, scale)
48 xmin, xmax = V[:, 0].min(), V[:, 0].max()
49 ymin, ymax = V[:, 1].min(), V[:, 1].max()
---> 50 V -= (xmin + xmax) / 2, (ymin + ymax) / 2
51 V *= scale
52 for i in range(len(V)):
ValueError: output array is read-only
I am using numpy version 1.22.0 and matplotlib version 3.5.1
In figure 12.1 on page 149, the rightmost 3 markers are shown as white in the pdf.
When I run the script and save as .pdf the same happens, but when I save that figure as .png the markers are shades of grey (as expected).
Might just be a bug in matplotlib, since one would expect that saving as .pdf produces the same image as saving as .png. Besides the fact that one is vector based and the other is raster based.
There is no reference to Figure 1.8 in the exercises at the end of Chapter 1. Maybe it is supposed to be associated with Exercise 1 (produce a figure with an exact pixel size)? If so, some reference to the figure in that section of the text would be helpful. And if it is supposed to be an example of setting exact figure pixel size, the code for Fig 1.8 could be more specific about defining what the figure pixel size is.
As a side note, the method of generating Fig 1.8 is interesting but perhaps unnecessarily complicated for this part of the book? Is it demonstrating something discussed in Chapter 1?
I try to run code/scales-projections/projection-3d-frame.py
and then there's an error: AttributeError: 'Arrow3D' object has no attribute 'do_3d_projection'
my env: python: 3.11, matplotlib: 3.8.0
then I found a possible solution here -> matplotlib issues#21688
when I change class Arrow3D
to :
class Arrow3D(mpatches.FancyArrowPatch):
def __init__(self, xs, ys, zs, *args, **kwargs):
mpatches.FancyArrowPatch.__init__(self, (0, 0), (0, 0), *args, **kwargs)
self._verts3d = xs, ys, zs
def do_3d_projection(self, renderer=None):
xs3d, ys3d, zs3d = self._verts3d
xs, ys, zs = proj3d.proj_transform(xs3d, ys3d, zs3d, self.axes.M)
self.set_positions((xs[0],ys[0]),(xs[1],ys[1]))
return np.min(zs)
it works, so I think maybe projection-3d-frame.py
need to be updated?
Having the versions of packages used for the book in a requirements.txt
would be helpful for others reproducing things a year or so down the line.
Looking through the repo for something such as numpy
doesn't bring up anything wrt the version used, just that it's imported in several locations.
As this book was only recently finished, perhaps there's an environment on the authors computer which has all the correct package versions within it? And a file could be generated from that.
Example search for numpy with rg numpy
:
README.md:* [From Python to Numpy](https://www.labri.fr/perso/nrougier/from-python-to-numpy/) (Scientific Python Volume I)
README.md:* [100 Numpy exercices](https://github.com/rougier/numpy-100)
rst/threed.rst:specify the color of each of the triangle using a numpy array, so let's just do
rst/anatomy.rst: import numpy as np
rst/anatomy.rst: import numpy as np
rst/00-preface.rst: import numpy as np
rst/00-preface.rst: >>> import numpy; print(numpy.__version__)
code/showcases/escher-movie.py:import numpy as np
code/showcases/domain-coloring.py:import numpy as np
code/showcases/mandelbrot.py:import numpy as np
code/showcases/text-shadow.py:import numpy as np
code/showcases/windmap.py:import numpy as np
code/showcases/mosaic.py:import numpy as np
code/showcases/mosaic.py: from numpy.random.mtrand import RandomState
code/showcases/contour-dropshadow.py:import numpy as np
code/showcases/escher.py:import numpy as np
code/showcases/text-spiral.py:import numpy as np
code/showcases/recursive-voronoi.py:import numpy as np
code/showcases/recursive-voronoi.py: from numpy.random.mtrand import RandomState
code/showcases/waterfall-3d.py:import numpy as np
rst/defaults.rst: import numpy as np
code/beyond/stamp.py:import numpy as np
code/beyond/dyson-hatching.py:import numpy as np
code/beyond/tikz-dashes.py:import numpy as np
rst/coordinates.rst: import numpy as np
rst/animation.rst: import numpy as np
rst/animation.rst: import numpy as np
rst/animation.rst: import numpy as np
code/beyond/tinybot.py:import numpy as np
code/beyond/dungeon.py:import numpy as np
cover/cover-pattern.py:import numpy as np
code/beyond/interactive-loupe.py:import numpy as np
code/beyond/bluenoise.py:import numpy as np
code/beyond/bluenoise.py: from numpy.random.mtrand import RandomState
code/beyond/polygon-clipping.py:import numpy as np
code/beyond/radial-maze.py:import numpy as np
code/reference/hatch.py:import numpy as np
code/reference/colormap-sequential-1.py:import numpy as np
code/reference/colormap-uniform.py:import numpy as np
code/reference/marker.py:import numpy as np
code/reference/line.py:import numpy as np
code/ornaments/annotation-zoom.py:import numpy as np
code/scales-projections/text-polar.py:import numpy as np
code/ornaments/legend-regular.py:import numpy as np
code/ornaments/elegant-scatter.py:import numpy as np
code/reference/axes-adjustment.py:import numpy as np
code/ornaments/legend-alternatives.py:import numpy as np
code/reference/colorspec.py:import numpy as np
code/typography/typography-matters.py:import numpy as np
code/colors/color-gradients.py:import numpy as np
code/threed/bunny-6.py:import numpy as np
code/scales-projections/projection-polar-config.py:import numpy as np
code/colors/color-wheel.py:import numpy as np
code/colors/mona-lisa.py:import numpy as np
code/threed/bunny-4.py:import numpy as np
code/ornaments/title-regular.py:import numpy as np
code/typography/text-outline.py:import numpy as np
code/ornaments/bessel-functions.py:import numpy as np
code/scales-projections/projection-polar-histogram.py:import numpy as np
code/rules/rule-6.py:import numpy as np
code/colors/open-colors.py:import numpy as np
code/colors/material-colors.py:import numpy as np
code/colors/flower-polar.py:import numpy as np
code/typography/typography-legibility.py:import numpy as np
code/colors/colored-plot.py:import numpy as np
code/rules/rule-7.py:import numpy as np
code/colors/colored-hist.py:import numpy as np
code/rules/rule-3.py:import numpy as np
code/colors/alpha-vs-color.py:import numpy as np
code/colors/stacked-plots.py:import numpy as np
code/ornaments/label-alternatives.py:import numpy as np
code/typography/tick-labels-variation.py:import numpy as np
code/rules/projections.py:import numpy as np
code/typography/typography-math-stacks.py:import numpy as np
code/rules/rule-2.py:import numpy as np
code/colors/alpha-scatter.py:import numpy as np
code/typography/typography-text-path.py:import numpy as np
code/scales-projections/polar-patterns.py:import numpy as np
code/scales-projections/scales-custom.py:import numpy as np
code/rules/parameters.py:import numpy as np
code/threed/bunny-1.py:import numpy as np
code/scales-projections/geo-projections.py:import numpy as np
code/rules/rule-8.py:import numpy as np
code/threed/bunny-5.py:import numpy as np
code/ornaments/latex-text-box.py:import numpy as np
code/ornaments/annotation-direct.py:import numpy as np
code/typography/projection-3d-gaussian.py:import numpy as np
code/threed/bunny-7.py:import numpy as np
code/rules/helper.py:import numpy as np
code/rules/helper.py: """ Generate a numpy array containing a disc. """
code/typography/typography-font-stacks.py:import numpy as np
code/scales-projections/scales-log-log.py:import numpy as np
code/scales-projections/projection-3d-frame.py:import numpy as np
code/threed/bunnies.py:import numpy as np
code/threed/bunny.py:import numpy as np
code/threed/bunny-3.py:import numpy as np
code/rules/rule-9.py:import numpy as np
code/ornaments/annotate-regular.py:import numpy as np
code/threed/bunny-2.py:import numpy as np
code/reference/tick-locator.py:import numpy as np
code/threed/bunny-8.py:import numpy as np
code/reference/colormap-diverging.py:import numpy as np
code/scales-projections/scales-comparison.py:import numpy as np
code/reference/text-alignment.py:import numpy as np
code/scales-projections/scales-check.py:import numpy as np
code/reference/scale.py:import numpy as np
code/reference/colormap-qualitative.py:import numpy as np
code/reference/tick-formatter.py:import numpy as np
code/rules/graphics.py:import numpy as np
code/rules/rule-1.py:import numpy as np
code/reference/collection.py:import numpy as np
code/ornaments/annotation-side.py:import numpy as np
code/reference/colormap-sequential-2.py:import numpy as np
code/defaults/defaults-exercice-1.py:import numpy as np
code/animation/platecarree.py:import numpy as np
code/defaults/defaults-step-4.py:import numpy as np
code/layout/standard-layout-2.py:import numpy as np
code/coordinates/transforms-blend.py:import numpy as np
code/unsorted/layout-weird.py:import numpy as np
code/unsorted/advanced-linestyles.py:import numpy as np
code/coordinates/transforms-exercise-1.py:import numpy as np
code/animation/fluid-animation.py:import numpy as np
code/unsorted/alpha-gradient.py:import numpy as np
code/animation/sine-cosine.py:import numpy as np
code/optimization/line-benchmark.py:import numpy as np
code/animation/fluid.py:import numpy as np
code/optimization/transparency.py:import numpy as np
code/animation/rain.py:import numpy as np
code/optimization/scatter-benchmark.py:import numpy as np
code/optimization/self-cover.py:import numpy as np
code/animation/imgcat.py:import numpy as np
code/unsorted/hatched-bars.py:import numpy as np
code/optimization/multithread.py:import numpy as np
code/animation/earthquakes.py:import numpy as np
code/unsorted/poster-layout.py:import numpy as np
code/coordinates/transforms-letter.py:import numpy as np
code/optimization/scatters.py:import numpy as np
code/animation/sine-cosine-mp4.py:import numpy as np
code/optimization/multisample.py:import numpy as np
code/unsorted/make-hatch-linewidth.py:import numpy as np
code/animation/lissajous.py:import numpy as np
code/coordinates/transforms-polar.py:import numpy as np
code/unsorted/earthquakes.py:import numpy as np
code/unsorted/git-commits.py:import numpy as np
code/unsorted/github-activity.py:import numpy as np
code/coordinates/collage.py:import numpy as np
code/introduction/matplotlib-timeline.py:import numpy as np
code/coordinates/transforms-floating-axis.py:import numpy as np
code/coordinates/transforms-hist.py:import numpy as np
code/layout/complex-layout-bare.py:import numpy as np
code/animation/less-is-more.py:import numpy as np
code/coordinates/transforms.py:import numpy as np
code/unsorted/alpha-compositing.py:import numpy as np
code/layout/standard-layout-1.py:import numpy as np
code/layout/layout-classical.py:import numpy as np
code/unsorted/stacked-bars.py:import numpy as np
code/layout/complex-layout.py:import numpy as np
code/layout/layout-aspect.py:import numpy as np
code/unsorted/metropolis.py:import numpy as np
code/unsorted/scale-logit.py:import numpy as np
code/unsorted/dyson-hatching.py:import numpy as np
code/unsorted/dyson-hatching.py: from numpy.random.mtrand import RandomState
code/layout/layout-gridspec.py:import numpy as np
code/defaults/defaults-step-1.py:import numpy as np
code/defaults/defaults-step-2.py:import numpy as np
code/defaults/defaults-step-5.py:import numpy as np
code/defaults/defaults-step-3.py:import numpy as np
code/anatomy/bold-ticklabel.py:import numpy as np
code/unsorted/3d/contour.py:import numpy as np
code/unsorted/3d/sphere.py:import numpy as np
code/unsorted/3d/platonic-solids.py:import numpy as np
code/unsorted/3d/surf.py:import numpy as np
code/unsorted/3d/bar.py:import numpy as np
tex/cover-pattern.py:import numpy as np
code/unsorted/3d/scatter.py:import numpy as np
tex/book.bib: url = {https://www.labri.fr/perso/nrougier/from-python-to-numpy/},
code/anatomy/pixel-font.py:import numpy as np
code/anatomy/raster-vector.py:import numpy as np
code/anatomy/zorder-plots.py:import numpy as np
code/anatomy/ruler.py:import numpy as np
code/anatomy/anatomy.py:import numpy as np
code/anatomy/zorder.py:import numpy as np
code/unsorted/3d/bunny.py:import numpy as np
code/unsorted/3d/bunnies.py:import numpy as np
code/unsorted/3d/plot.py:import numpy as np
code/unsorted/3d/plot.py: camera : 4x4 numpy array
code/unsorted/3d/glm.py:import numpy as np
These seem to be the imports used in the text:
'from __future__ import absolute_import',
'from __future__ import division',
'from __future__ import print_function',
'from __future__ import unicode_literals',
'from datetime import date, datetime',
'from datetime import datetime',
'from dateutil.relativedelta import relativedelta',
'from docutils import nodes',
'from docutils.core import publish_cmdline',
'from docutils.parsers.rst import directives, Directive',
'from fluid import Fluid, inflow',
'from functools import reduce',
'from graphics import *',
'from helper import *',
'from itertools import cycle',
'from math import cos, sin, floor, sqrt, pi, ceil',
'from math import factorial',
'from math import sqrt, ceil, floor, pi, cos, sin',
'from matplotlib import colors',
'from matplotlib import ticker',
'from matplotlib.animation import FuncAnimation, writers',
'from matplotlib.artist import Artist',
'from matplotlib.backend_bases import GraphicsContextBase, RendererBase',
'from matplotlib.backends.backend_agg import FigureCanvas',
'from matplotlib.backends.backend_agg import FigureCanvasAgg',
'from matplotlib.collections import AsteriskPolygonCollection',
'from matplotlib.collections import CircleCollection',
'from matplotlib.collections import EllipseCollection',
'from matplotlib.collections import LineCollection',
'from matplotlib.collections import PatchCollection',
'from matplotlib.collections import PathCollection',
'from matplotlib.collections import PolyCollection',
'from matplotlib.collections import PolyCollection',
'from matplotlib.collections import QuadMesh',
'from matplotlib.collections import RegularPolyCollection',
'from matplotlib.collections import StarPolygonCollection',
'from matplotlib.colors import LightSource',
'from matplotlib.figure import Figure',
'from matplotlib.font_manager import FontProperties',
'from matplotlib.font_manager import findfont, FontProperties',
'from matplotlib.gridspec import GridSpec',
'from matplotlib.gridspec import GridSpec',
'from matplotlib.patches import Circle',
'from matplotlib.patches import Circle',
'from matplotlib.patches import Circle, Rectangle',
'from matplotlib.patches import ConnectionPatch',
'from matplotlib.patches import Ellipse',
'from matplotlib.patches import Ellipse',
'from matplotlib.patches import FancyBboxPatch',
'from matplotlib.patches import PathPatch',
'from matplotlib.patches import Polygon',
'from matplotlib.patches import Polygon',
'from matplotlib.patches import Polygon, Ellipse',
'from matplotlib.patches import Rectangle',
'from matplotlib.patches import Rectangle, PathPatch',
'from matplotlib.path import Path',
'from matplotlib.patheffects import Stroke, Normal',
'from matplotlib.patheffects import withStroke',
'from matplotlib.text import TextPath',
'from matplotlib.textpath import TextPath',
'from matplotlib.ticker import AutoMinorLocator, MultipleLocator, FuncFormatter',
'from matplotlib.ticker import MultipleLocator',
'from matplotlib.ticker import NullFormatter',
'from matplotlib.ticker import NullFormatter, MultipleLocator',
'from matplotlib.ticker import NullFormatter, SymmetricalLogLocator',
'from matplotlib.transforms import Affine2D',
'from matplotlib.transforms import ScaledTranslation',
'from matplotlib.transforms import blended_transform_factory, ScaledTranslation',
'from mpl_toolkits.axes_grid1 import ImageGrid',
'from mpl_toolkits.axes_grid1 import ImageGrid',
'from mpl_toolkits.axes_grid1 import make_axes_locatable',
'from mpl_toolkits.axes_grid1.inset_locator import inset_axes',
'from mpl_toolkits.axes_grid1.inset_locator import mark_inset',
'from mpl_toolkits.axes_grid1.inset_locator import mark_inset',
'from mpl_toolkits.axes_grid1.inset_locator import zoomed_inset_axes',
'from mpl_toolkits.axes_grid1.inset_locator import zoomed_inset_axes',
'from mpl_toolkits.mplot3d import Axes3D, art3d',
'from mpl_toolkits.mplot3d import Axes3D, proj3d, art3d',
'from multiprocessing import Pool',
'from numpy.random.mtrand import RandomState',
'from parameters import *',
'from pathlib import Path',
'from projections import *',
'from pylab import *',
'from scipy.ndimage import gaussian_filter',
'from scipy.ndimage import gaussian_filter1d',
'from scipy.ndimage import map_coordinates, spline_filter',
'from scipy.sparse.linalg import factorized',
'from scipy.spatial import Voronoi',
'from scipy.special import erf',
'from scipy.special import jn, jn_zeros',
'from shapely.geometry import Polygon',
'from shapely.geometry import box, Polygon',
'from skimage.color import rgb2lab, lab2rgb, rgb2xyz, xyz2rgb',
'from timeit import default_timer as timer',
'from tqdm.autonotebook import tqdm',
'import bluenoise',
'import cartopy',
'import cartopy.crs',
'import cartopy.crs as ccrs',
'import colorsys',
'import dateutil.parser',
'import git',
'import glm',
'import html.parser',
'import imageio',
'import locale',
'import math',
'import matplotlib',
'import matplotlib as mpl',
'import matplotlib.animation as animation',
'import matplotlib.animation as animation',
'import matplotlib.colors as colors',
'import matplotlib.colors as mc',
'import matplotlib.colors as mcolors',
'import matplotlib.gridspec as gridspec',
'import matplotlib.image as mpimg',
'import matplotlib.patches as mpatch',
'import matplotlib.patches as mpatches',
'import matplotlib.patches as patches',
'import matplotlib.path as mpath',
'import matplotlib.path as path',
'import matplotlib.patheffects as PathEffects',
'import matplotlib.patheffects as path_effects',
'import matplotlib.pylab as plt',
'import matplotlib.pyplot as plt',
'import matplotlib.pyplot as plt',
'import matplotlib.ticker as ticker',
'import matplotlib.transforms as transforms',
'import mpl_toolkits.axisartist.floating_axes as floating_axes',
'import mpl_toolkits.mplot3d.art3d as art3d',
'import mpmath',
'import noise',
'import numpy as np',
'import os',
'import plot',
'import re',
'import scipy',
'import scipy.sparse as sp',
'import scipy.spatial',
'import shapely.geometry',
'import sys',
'import tqdm',
'import tqdm',
'import types',
'import urllib',
'import urllib.request'
You may be interested by matplotlib/matplotlib#16171?
In the chapter "10 simple rules", around line 276 (I'd link it directly but GH doesn't seem to support line numbers properly with RST files), there's this sentence:
first one (30), while the ratio between the two values is only 3∶1. This
The character doesn't seem to be rendered properly no matter which PDF viewer I use (Evince, Okular on Linux, Adobe Reader on Win10), and looks like this:
I tried building the book on my machine but still end up with the same issue.
Hi @rougier,
Could you please tell is it possible to create recent version of the book using the repository by myself?
I started to install required system/python packages and have an errors when running make all
, for example:
Latexmk: 'xelatex': source file 'ean13.tex' doesn't exist. I'll try making it...
There are a lot of fixes in repository which are not in pdf in the book
folder, and it will be great to include these fixes in pdf version.
Thank you.
Thanks for your book! The figures are amazing.
Since I am working in 3D and have to play around with point clouds a lot, I really want to know how the 'Scatter-3D' exmaple is made.
It seems the core part is the custom marker. The marker's fading shadow rings create a beautiful effect of 3D shading.
Can you share the code for creating this example? Thanks a lot!
Thank you, and well done on the release of this fantastic and comprehensive book! I wondered whether you might consider releasing an ePUB edition of it at all? Many thanks!
Hi @rougier,
The links to the code for Figures 2.3-2.5 have the name coordinates/transform‐*.py
and URL https://github.com/rougier/scientific-visualization-book/blob/master/code/coordinates/transform-*.py, but the files have the name transforms-*.py
, so probably the following will be correct:
Name - coordinates/transforms‐*.py
URL - https://github.com/rougier/scientific-visualization-book/blob/master/code/coordinates/transforms-*.py
Also for Figure 2.5 there is the same description as for Figure 2.3 (except for file name):
Figure 2.3
Axes boundaries in polar projection using a transform from normalized data co‐
ordinates to data coordinates (coordinates/transform‐polar.py).
Figure 2.5
Axes boundaries in polar projection using a transform from normalized data co‐
ordinates to data coordinates (coordinates/transform‐blend.py).
It seems that Figure 2.5 has incorrect description.
Thank you.
I try to replicate shocase/text-spiral.py
in my laptop.
I tried to run the following code.
import mpmath
mpmath.mp.dps = 15000
text = str(mpmath.pi)
path = TextPath((0, 0), text, size=6, ) #, prop=FontProperties(family="Source Serif Pro"))
#path.vertices.setflags(write=1)
Vx, Vy = path.vertices[:, 0], path.vertices[:, 1]
X = np.interp(Vx, L, T[:, 0]) + Vy * np.interp(Vx, L, O[:, 0])
Y = np.interp(Vx, L, T[:, 1]) + Vy * np.interp(Vx, L, O[:, 1])
Vx[...] = X
Vy[...] = Y
Then I encountered ValueError: assignment destination is read-only
.
If I add the line path.vertices.setflags(write=1)
right after path
object is created,
I can reproduce the showcase.
I used matplotlib 3.6.3, which might be different behaviour for a default object editing permission (can be checked by path.vertices.flags
) .
Hope this comment will help improve reproducibility.
The code for figure 2.4 is reproduced below for convenience:
from matplotlib.transforms import ScaleTranslation
fig = plt.figure(figsize=(6, 4))
ax = fig.add_subplot(2, 1, 1)
plt.text(0.1, 0.1, "A", transform=ax.transAxes)
ax = fig.add_subplot(2, 1, 2)
dx, dy = 10/fig.dpi, 10/fig.dpi
offset = ScaledTranslation(dx, dy, fig.dpi_scale_trans)
plt.text(0, 0, "B", transform=ax.transAxes + offset)
plt.show()
I believe the scaling of dx, dy should be a division by 72, not by fig.dpi (more or less as you do in figure 2.5, in fact), as otherwise the appearance of the figure will depend on figure.dpi; e.g.
from matplotlib import pyplot as plt, transforms as tr
size = 10
for dpi in [72, 300]:
fig = plt.figure(dpi=dpi)
ax = fig.add_subplot(2, 1, 1)
dx = dy = size / fig.dpi
offset = tr.ScaledTranslation(dx, dy, fig.dpi_scale_trans)
ax.text(0, 0, "A", transform=ax.transAxes + offset, size=size)
ax = fig.add_subplot(2, 1, 2)
dx = dy = size / 72
offset = tr.ScaledTranslation(dx, dy, fig.dpi_scale_trans)
ax.text(0, 0, "A", transform=ax.transAxes + offset, size=size)
fig.savefig(f"/tmp/test{dpi}.png")
fig.savefig(f"/tmp/test{dpi}.pdf")
You can verify that here, the visual appearance of the top axis changes whereas the bottom one doesn't.
In a sense, this is redundant with figure 2.5; but perhaps division-by-72 should really be mentioned first and division-by-fig.dpi is more a side possibility?
Hi @rougier,
I found that the link under "Anti‐Grain Geometry C++ library" to https://antigrain.com is not working, and it is confirmed in the description here, referring also to another site (http://agg.sourceforge.net/antigrain.com/):
The official AGG site remains on Sourceforge, but doesn't see much activity. With www.antigrain.com recently inoperational, I thought a GitHub repo was in order, as the project demos stopped building with the site down.
Thank you.
Bottom of Page 28 in the PDF found here: https://hal.inria.fr/hal-03427242/document
The example code incorrectly displays
fig, ax = plt.subplots(figsize=(6,6), subplot_kw={"aspect"=1})
it should read:
fig, ax = plt.subplots(figsize=(6,6), subplot_kw={"aspect":1})
Hi @rougier,
There is a statement about additional figure margins for Exercise 2 solution:
scientific-visualization-book/code/anatomy/inch-cm.py
Lines 13 to 15 in a6e0607
scientific-visualization-book/code/anatomy/inch-cm.py
Lines 27 to 38 in a6e0607
margin=0.25
(not 0.125 as in the code) because we multiply this margin by 0.5 when we call plt.subplots_adjust()
.Thank you.
First of all, this looks amazing! 👏
Would you consider making the code available using another license than a creative common?
The reason is that, as with StackOverflow, CC is not compatible with licenses like MIT and BSD.
would be cool to see how you constructed them. Cheers
Can you share with me the source code of Figure 11.3 in the book?
It might be better if the images on the project page are accompanied with the code link in the git (as in the book).
The first function instruction of imshow has a problem because the length t-uple ranges between 2 and 3.
We have resolved the problem by replacing the line:
height, width = I.shape
with:
height, width = I.shape[0], I.shape[1]
bye
ps. What a great book! :-)
Hi,
Thanks for the amazing work!
I have noticed there are blank pages(which also have page numbers). Is it actually the case or Its a issue of my device?
Hi @rougier,
I found that you use global object fig
in the Ruler object:
fig
is created after function's definition.self.fig
is more appropriate in this case?
Thank you.
Hi @rougier,
The code in the book for imshow()
function which is used for collage plotting is not consistent with the output image and the Python file.
In addition to the missing lines (which is probably done intentionally), for example zorder
is used in the body but there is no argument with the same name (in Python file there is a such argument).
Could you please tell maybe it's all done that way on intentionally and it is not necessary to create issues like this and #64?
Thank you.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.