ASKSAGE: Sage Q&A Forum - RSS feedhttps://ask.sagemath.org/questions/Q&A Forum for SageenCopyright Sage, 2010. Some rights reserved under creative commons license.Sun, 18 Nov 2018 19:10:50 +0100Using colormaps for several curves in a single plot (lists)https://ask.sagemath.org/question/44308/using-colormaps-for-several-curves-in-a-single-plot-lists/I would like to plot in a simgle fingure several curves, with the colors changing according to a colormap. More precisely, I want to plot some partial sums of a power series, and would like to use the "Blues" colormap to do this. I am using lists to produce the figures / functions. I can actually do something reasonable with color =(?,?,?), but want to be able to use the colormaps. Here is what I got :
Terms = [x^(2+j)*(2+(-1)^(j+1)) for j in range(10)]
Sums = [sum(Terms[0:n]) for n in range(10)]
Figures = [plot(Sums[j], (x,-1.2,1.2), ymin=-3, ymax = 3, color= (0,1-j/10,j/10)) for j in range(10)]
show(sum(Figures))Fri, 16 Nov 2018 17:54:22 +0100https://ask.sagemath.org/question/44308/using-colormaps-for-several-curves-in-a-single-plot-lists/Answer by slelievre for <p>I would like to plot in a simgle fingure several curves, with the colors changing according to a colormap. More precisely, I want to plot some partial sums of a power series, and would like to use the "Blues" colormap to do this. I am using lists to produce the figures / functions. I can actually do something reasonable with color =(?,?,?), but want to be able to use the colormaps. Here is what I got :</p>
<pre><code>Terms = [x^(2+j)*(2+(-1)^(j+1)) for j in range(10)]
Sums = [sum(Terms[0:n]) for n in range(10)]
Figures = [plot(Sums[j], (x,-1.2,1.2), ymin=-3, ymax = 3, color= (0,1-j/10,j/10)) for j in range(10)]
show(sum(Figures))
</code></pre>
https://ask.sagemath.org/question/44308/using-colormaps-for-several-curves-in-a-single-plot-lists/?answer=44309#post-id-44309Here is one way to use a colormap with your plots.
In this example, we set the number of curves, and run through the colormap in that many steps.
sage: cm = colormaps.Blues
sage: nmax = 20
sage: color = lambda j: cm(floor(j*255/nmax))[:3]
sage: Terms = [x^(2+j)*(2+(-1)^(j+1)) for j in range(nmax)]
sage: Sums = [sum(Terms[0:n]) for n in range(nmax)]
sage: Figures = [plot(Sums[j], (x, -1.2, 1.2), ymin=-3, ymax=3, color=color(j)) for j in range(nmax)]
sage: f = sum(Figures)
sage: f.show()
**Edit.** (To answer follow-up question in the comment.)
Colormaps have 256 levels numbered 0 to 255,
so `color` above maps [0 .. nmax - 1] into [0 .. 255].
To leave out the first half of the colormap, use instead:
sage: color = lambda j: cm(floor(128 + j*127/nmax))[:3]
or if you want to go nonlinearly using some function `h`
from [0 .. nmax-1] to the interval [0, 1], just use
sage: color = lambda j: cm(floor(255*h(j))[:3]
(That looks better indeed.)
The reason for `[:3]` is that a colormap returns four values,
corresponding to R, G, B and opacity (also known as alpha),
but typically opacity is 1.0 throughout (since most colormaps
do not play with transparency).
To further refine the above and make the transition through
colors more continuous, instead of using `cm(floor(...))` one
could use the fractional part of `255*h(j)` to move gradually
between the colors at `floor(255*h(j))` and `ceil(255*h(j))`
in the colormap... (Not clear one could perceive the effect
of that though!)
To do that, given a function `h` as above, you could do
def color(j):
h = RR(255*h(j))
r0, g0, b0 = cm(h.floor())[:3] # rgb at floor
r1, g1, b1 = cm(h.ceil())[:3] # rgb at ceiling
f = h.frac() # fractional part
r = (1-f) * r0 + f * r1
g = (1-f) * g0 + f * g1
b = (1-f) * b0 + f * b1
return r, g, bFri, 16 Nov 2018 19:24:00 +0100https://ask.sagemath.org/question/44308/using-colormaps-for-several-curves-in-a-single-plot-lists/?answer=44309#post-id-44309Comment by JC for <p>Here is one way to use a colormap with your plots.</p>
<p>In this example, we set the number of curves, and run through the colormap in that many steps.</p>
<pre><code>sage: cm = colormaps.Blues
sage: nmax = 20
sage: color = lambda j: cm(floor(j*255/nmax))[:3]
sage: Terms = [x^(2+j)*(2+(-1)^(j+1)) for j in range(nmax)]
sage: Sums = [sum(Terms[0:n]) for n in range(nmax)]
sage: Figures = [plot(Sums[j], (x, -1.2, 1.2), ymin=-3, ymax=3, color=color(j)) for j in range(nmax)]
sage: f = sum(Figures)
sage: f.show()
</code></pre>
<p><strong>Edit.</strong> (To answer follow-up question in the comment.)</p>
<p>Colormaps have 256 levels numbered 0 to 255,
so <code>color</code> above maps [0 .. nmax - 1] into [0 .. 255].</p>
<p>To leave out the first half of the colormap, use instead:</p>
<pre><code>sage: color = lambda j: cm(floor(128 + j*127/nmax))[:3]
</code></pre>
<p>or if you want to go nonlinearly using some function <code>h</code>
from [0 .. nmax-1] to the interval [0, 1], just use</p>
<pre><code>sage: color = lambda j: cm(floor(255*h(j))[:3]
</code></pre>
<p>(That looks better indeed.)</p>
<p>The reason for <code>[:3]</code> is that a colormap returns four values,
corresponding to R, G, B and opacity (also known as alpha),
but typically opacity is 1.0 throughout (since most colormaps
do not play with transparency).</p>
<p>To further refine the above and make the transition through
colors more continuous, instead of using <code>cm(floor(...))</code> one
could use the fractional part of <code>255*h(j)</code> to move gradually
between the colors at <code>floor(255*h(j))</code> and <code>ceil(255*h(j))</code>
in the colormap... (Not clear one could perceive the effect
of that though!)</p>
<p>To do that, given a function <code>h</code> as above, you could do</p>
<pre><code>def color(j):
h = RR(255*h(j))
r0, g0, b0 = cm(h.floor())[:3] # rgb at floor
r1, g1, b1 = cm(h.ceil())[:3] # rgb at ceiling
f = h.frac() # fractional part
r = (1-f) * r0 + f * r1
g = (1-f) * g0 + f * g1
b = (1-f) * b0 + f * b1
return r, g, b
</code></pre>
https://ask.sagemath.org/question/44308/using-colormaps-for-several-curves-in-a-single-plot-lists/?comment=44310#post-id-44310Great, that is exactly what I was looking for. Next tweak : make the color function to beheave non linearly, or for instance start at 0.5 in order to avoid too light curves.Fri, 16 Nov 2018 19:51:49 +0100https://ask.sagemath.org/question/44308/using-colormaps-for-several-curves-in-a-single-plot-lists/?comment=44310#post-id-44310Comment by slelievre for <p>Here is one way to use a colormap with your plots.</p>
<p>In this example, we set the number of curves, and run through the colormap in that many steps.</p>
<pre><code>sage: cm = colormaps.Blues
sage: nmax = 20
sage: color = lambda j: cm(floor(j*255/nmax))[:3]
sage: Terms = [x^(2+j)*(2+(-1)^(j+1)) for j in range(nmax)]
sage: Sums = [sum(Terms[0:n]) for n in range(nmax)]
sage: Figures = [plot(Sums[j], (x, -1.2, 1.2), ymin=-3, ymax=3, color=color(j)) for j in range(nmax)]
sage: f = sum(Figures)
sage: f.show()
</code></pre>
<p><strong>Edit.</strong> (To answer follow-up question in the comment.)</p>
<p>Colormaps have 256 levels numbered 0 to 255,
so <code>color</code> above maps [0 .. nmax - 1] into [0 .. 255].</p>
<p>To leave out the first half of the colormap, use instead:</p>
<pre><code>sage: color = lambda j: cm(floor(128 + j*127/nmax))[:3]
</code></pre>
<p>or if you want to go nonlinearly using some function <code>h</code>
from [0 .. nmax-1] to the interval [0, 1], just use</p>
<pre><code>sage: color = lambda j: cm(floor(255*h(j))[:3]
</code></pre>
<p>(That looks better indeed.)</p>
<p>The reason for <code>[:3]</code> is that a colormap returns four values,
corresponding to R, G, B and opacity (also known as alpha),
but typically opacity is 1.0 throughout (since most colormaps
do not play with transparency).</p>
<p>To further refine the above and make the transition through
colors more continuous, instead of using <code>cm(floor(...))</code> one
could use the fractional part of <code>255*h(j)</code> to move gradually
between the colors at <code>floor(255*h(j))</code> and <code>ceil(255*h(j))</code>
in the colormap... (Not clear one could perceive the effect
of that though!)</p>
<p>To do that, given a function <code>h</code> as above, you could do</p>
<pre><code>def color(j):
h = RR(255*h(j))
r0, g0, b0 = cm(h.floor())[:3] # rgb at floor
r1, g1, b1 = cm(h.ceil())[:3] # rgb at ceiling
f = h.frac() # fractional part
r = (1-f) * r0 + f * r1
g = (1-f) * g0 + f * g1
b = (1-f) * b0 + f * b1
return r, g, b
</code></pre>
https://ask.sagemath.org/question/44308/using-colormaps-for-several-curves-in-a-single-plot-lists/?comment=44329#post-id-44329Edited answer to address this follow-up question.Sun, 18 Nov 2018 19:10:50 +0100https://ask.sagemath.org/question/44308/using-colormaps-for-several-curves-in-a-single-plot-lists/?comment=44329#post-id-44329