Partial coloring of text in matplotlib

Is there a way in matplotlib to partially specify the color of a string?

Example:

plt.ylabel(“Today is cloudy.”)

How can I show “today” as red, “is” as green and “cloudy.” as blue?

Thanks.

PS: Asked also on http://stackoverflow.com/questions/9169052/partial-coloring-of-text-in-matplotlib

···


Gökhan

Nope. But it’s something I’ve wanted to add for a while. Can you
file an Issue in the github tracker?

Mike
···

http://p.sf.net/sfu/learndevnow-d2dMatplotlib-users@lists.sourceforge.nethttps://lists.sourceforge.net/lists/listinfo/matplotlib-users

Posted at https://github.com/matplotlib/matplotlib/issues/697

I think a syntax like:

plt.ylabel(“Sun is shining.”, color=‘rgb’)

would be a good start. (Assuming len of string == len of colors)

···

On Tue, Feb 7, 2012 at 11:18 AM, Michael Droettboom <mdroe@…86…> wrote:

Nope.  But it's something I've wanted to add for a while.  Can you

file an Issue in the github tracker?

Mike




On 02/07/2012 11:40 AM, Gökhan Sever wrote:
    Is there a way in matplotlib to partially specify the color

of a string?

Example:

plt.ylabel(“Today is cloudy.”)

    How can I show "today" as red, "is" as green and "cloudy." as

blue?

Thanks.

PS: Asked also on http://stackoverflow.com/questions/9169052/partial-coloring-of-text-in-matplotlib

  Gökhan
------------------------------------------------------------------------------
Keep Your Developer Skills Current with LearnDevNow!
The most comprehensive online learning library for Microsoft developers
is just $99.99! Visual Studio, SharePoint, SQL - plus HTML5, CSS3, MVC3,
Metro Style Apps, more. Free future releases when you subscribe now!
[http://p.sf.net/sfu/learndevnow-d2d](http://p.sf.net/sfu/learndevnow-d2d)
_______________________________________________
Matplotlib-users mailing list
Matplotlib-users@lists.sourceforge.net
[https://lists.sourceforge.net/lists/listinfo/matplotlib-users](https://lists.sourceforge.net/lists/listinfo/matplotlib-users)

Keep Your Developer Skills Current with LearnDevNow!

The most comprehensive online learning library for Microsoft developers

is just $99.99! Visual Studio, SharePoint, SQL - plus HTML5, CSS3, MVC3,

Metro Style Apps, more. Free future releases when you subscribe now!

http://p.sf.net/sfu/learndevnow-d2d


Matplotlib-users mailing list

Matplotlib-users@lists.sourceforge.net

https://lists.sourceforge.net/lists/listinfo/matplotlib-users


Gökhan

Don’t know if I like that. It becomes even more difficult to convert the color spec into rgb. How about this?

plt.ylabel(['Sun", “is”, “shining”], color=[‘r’, ‘g’, ‘b’])

By having the input label be an array, that would force ylabel to recognize that the color sequence should also be treated similarly.

Ben Root

···

On Tue, Feb 7, 2012 at 12:38 PM, Gökhan Sever <gokhansever@…287…> wrote:

Posted at https://github.com/matplotlib/matplotlib/issues/697

I think a syntax like:

plt.ylabel(“Sun is shining.”, color=‘rgb’)

would be a good start. (Assuming len of string == len of colors)

This works as well, as long as it functions :slight_smile:

My idea requires little less typing. But forgot previously, text string should be whitespace split.

···

On Tue, Feb 7, 2012 at 11:43 AM, Benjamin Root <ben.root@…1304…> wrote:

On Tue, Feb 7, 2012 at 12:38 PM, Gökhan Sever <gokhansever@…287…> wrote:

Posted at https://github.com/matplotlib/matplotlib/issues/697

I think a syntax like:

plt.ylabel(“Sun is shining.”, color=‘rgb’)

would be a good start. (Assuming len of string == len of colors)

Don’t know if I like that. It becomes even more difficult to convert the color spec into rgb. How about this?

plt.ylabel(['Sun", “is”, “shining”], color=[‘r’, ‘g’, ‘b’])

By having the input label be an array, that would force ylabel to recognize that the color sequence should also be treated similarly.

Ben Root


Gökhan

Right, but we shouldn't guess. If we automatically split on
whitespace, this becomes harder:

plt.ylabel(["The sun is", "yellow"], ['k', 'y'])

Ryan

···

On Tue, Feb 7, 2012 at 12:49 PM, Gökhan Sever <gokhansever@...287...> wrote:

This works as well, as long as it functions :slight_smile:

My idea requires little less typing. But forgot previously, text string
should be whitespace split.

--
Ryan May
Graduate Research Assistant
School of Meteorology
University of Oklahoma

I was basing my whitespace split idea on single string assumption --eg. no list passing.

I do not have a strong preference on the final argument passing, as long as it works instead of manually placing the texts on figure or axis :slight_smile:

···

On Tue, Feb 7, 2012 at 11:52 AM, Ryan May <rmay31@…287…> wrote:

On Tue, Feb 7, 2012 at 12:49 PM, Gökhan Sever <gokhansever@…287…> wrote:

This works as well, as long as it functions :slight_smile:

My idea requires little less typing. But forgot previously, text string

should be whitespace split.

Right, but we shouldn’t guess. If we automatically split on

whitespace, this becomes harder:

plt.ylabel([“The sun is”, “yellow”], [‘k’, ‘y’])

Ryan

Ryan May

Graduate Research Assistant

School of Meteorology

University of Oklahoma


Gökhan

I think the python mantra of “explicit over implicit” should be followed here. I don’t think we currently allow list of strings, so there is no risk of breaking existing scripts, I think. We probably should confirm that just in case.

Also, how deep should this rabbit hole go? I could imagine one could want this for title() and figtitle(). Maybe it would be best to implement this at the Text() constructor level?

Ben Root

···

On Tue, Feb 7, 2012 at 1:15 PM, Gökhan Sever <gokhansever@…287…> wrote:

I was basing my whitespace split idea on single string assumption --eg. no list passing.

I do not have a strong preference on the final argument passing, as long as it works instead of manually placing the texts on figure or axis :slight_smile:

On Tue, Feb 7, 2012 at 11:52 AM, Ryan May <rmay31@…287…> wrote:

On Tue, Feb 7, 2012 at 12:49 PM, Gökhan Sever <gokhansever@…287…> wrote:

This works as well, as long as it functions :slight_smile:

My idea requires little less typing. But forgot previously, text string

should be whitespace split.

Right, but we shouldn’t guess. If we automatically split on

whitespace, this becomes harder:

plt.ylabel([“The sun is”, “yellow”], [‘k’, ‘y’])

Ryan

I was basing my whitespace split idea on single string assumption --eg. no list passing.

I do not have a strong preference on the final argument passing, as long as it works instead of manually placing the texts on figure or axis :slight_smile:

This works as well, as long as it functions :slight_smile:

My idea requires little less typing. But forgot previously, text string

should be whitespace split.

Right, but we shouldn’t guess. If we automatically split on

whitespace, this becomes harder:

plt.ylabel([“The sun is”, “yellow”], [‘k’, ‘y’])

Ryan

I think the python mantra of “explicit over implicit” should be followed here. I don’t think we currently allow list of strings, so there is no risk of breaking existing scripts, I think. We probably should confirm that just in case.

Fair enough.

Also, how deep should this rabbit hole go? I could imagine one could want this for title() and figtitle(). Maybe it would be best to implement this at the Text() constructor level?

ylabel text coloring works for me for the time being. However, a general implementation would possibly fulfill other incoming requests.

···

On Tue, Feb 7, 2012 at 12:46 PM, Benjamin Root <ben.root@…1304…> wrote:

On Tue, Feb 7, 2012 at 1:15 PM, Gökhan Sever <gokhansever@…287…> wrote:

On Tue, Feb 7, 2012 at 11:52 AM, Ryan May <rmay31@…287…> wrote:

On Tue, Feb 7, 2012 at 12:49 PM, Gökhan Sever <gokhansever@…287…> wrote:

Ben Root


Gökhan

In the past, I’ve thought having some sort of “HTML-lite” subset
would be the most powerful here. So one could do:

   title("This is <b>bold</b>")

Strictly speaking, for colors, one would do:

   title("This is <font color='red'>red</font>")

but that's awfully verbose.  I wouldn't have a problem fudging the

spec and supporting:

   title("This is <red>red</red>")

since this would never be full-fledged HTML anyway [1].

The advantage of this approach over any of the list-based ones is

that different properties can be nested, and I think most people
understand the basics of HTML/XML tags.

And I agree with Benjamin, that this should be at the Text()

constructor level so it works everywhere. I envision it being a
sort of peer text parser just as the mathtext parser is now – in
fact a lot of the mathtext machinery would be reused.

[1] Of course, I've also considered using something like

PythonWebKit to render text for us – the advantage being we’d also
get proper bidi and other internationalization features. But (a)
WebKit is another honking dependency and (b) I’m not sure the Python
bindings are ready for prime time.

Mike
···

http://p.sf.net/sfu/learndevnow-d2dMatplotlib-users@lists.sourceforge.nethttps://lists.sourceforge.net/lists/listinfo/matplotlib-users

Famous last words, right?

I'm curious: for the SVG backend, or a possible html5 canvas backend, can we already include html? I don't know, but I'm curious.

Jason

···

On 2/7/12 2:47 PM, Michael Droettboom wrote:

since this would never be full-fledged HTML anyway [1].

Benjamin Root, on 2012-02-07 13:46, wrote:

Also, how deep should this rabbit hole go? I could imagine one could want
this for title() and figtitle(). Maybe it would be best to implement this
at the Text() constructor level?

For this reason, I would discourage even implementing such
functionality in the core of matplotlib. This functionality doesn't strike me
as something that ought to be available everywhere by default - if someone
needs it, they can implement it as follows:

···

-----
import matplotlib.pyplot as plt
from matplotlib import transforms

def rainbow_text(x,y,ls,lc,**kw):
    """
    Take a list of strings ``ls`` and colors ``lc`` and place them next to each
    other, with text ls[i] being shown in color lc[i].

    This example shows how to do both vertical and horizontal text, and will
    pass all keyword arguments to plt.text, so you can set the font size,
    family, etc.
    """
    t = plt.gca().transData
    fig = plt.gcf()
    plt.show()

    #horizontal version
    for s,c in zip(ls,lc):
        text = plt.text(x,y," "+s+" ",color=c, transform=t, **kw)
        text.draw(fig.canvas.get_renderer())
        ex = text.get_window_extent()
        t = transforms.offset_copy(text._transform, x=ex.width, units='dots')

    #vertical version
    for s,c in zip(ls,lc):
        text = plt.text(x,y," "+s+" ",color=c, transform=t,
                rotation=90,va='bottom',ha='center',**kw)
        text.draw(fig.canvas.get_renderer())
        ex = text.get_window_extent()
        t = transforms.offset_copy(text._transform, y=ex.height, units='dots')

plt.figure()
rainbow_text(0.5,0.5,"all unicorns poop rainbows ! ! !".split(),
        ['red', 'orange', 'brown', 'green', 'blue', 'purple', 'black'],
        size=40)

best,
--
Paul Ivanov
314 address only used for lists, off-list direct email at:
http://pirsquared.org | GPG/PGP key id: 0x0F3E28F7

Along the lines of Mike’s suggestion, I thought this could be done using Latex.

I posted an answer on SO with an example of doing this, but it seems only to work with postscript backend. Other backends override the color with the mpl text color setting.

Is there a way to prevent this override? For example don’t try to use ‘PS’ backend, and look at hte figure interactively. It defaults to black.

http://stackoverflow.com/a/9185143/717357

-Yann

···

On Tue, Feb 7, 2012 at 4:46 PM, Paul Ivanov <pivanov314@…287…> wrote:

Benjamin Root, on 2012-02-07 13:46, wrote:

Also, how deep should this rabbit hole go? I could imagine one could want

this for title() and figtitle(). Maybe it would be best to implement this

at the Text() constructor level?

For this reason, I would discourage even implementing such

functionality in the core of matplotlib. This functionality doesn’t strike me

as something that ought to be available everywhere by default - if someone

needs it, they can implement it as follows:


import matplotlib.pyplot as plt

from matplotlib import transforms

def rainbow_text(x,y,ls,lc,**kw):

"""

Take a list of strings ``ls`` and colors ``lc`` and place them next to each

other, with text ls[i] being shown in color lc[i].



This example shows how to do both vertical and horizontal text, and will

pass all keyword arguments to plt.text, so you can set the font size,

family, etc.

"""

t = plt.gca().transData

fig = plt.gcf()

plt.show()



#horizontal version

for s,c in zip(ls,lc):

    text = plt.text(x,y," "+s+" ",color=c, transform=t, **kw)

    text.draw(fig.canvas.get_renderer())

    ex = text.get_window_extent()

    t = transforms.offset_copy(text._transform, x=ex.width, units='dots')



#vertical version

for s,c in zip(ls,lc):

    text = plt.text(x,y," "+s+" ",color=c, transform=t,

            rotation=90,va='bottom',ha='center',**kw)

    text.draw(fig.canvas.get_renderer())

    ex = text.get_window_extent()

    t = transforms.offset_copy(text._transform, y=ex.height, units='dots')

plt.figure()

rainbow_text(0.5,0.5,“all unicorns poop rainbows ! ! !”.split(),

    ['red', 'orange', 'brown', 'green', 'blue', 'purple', 'black'],

    size=40)

best,

Paul Ivanov

314 address only used for lists, off-list direct email at:

http://pirsquared.org | GPG/PGP key id: 0x0F3E28F7


Keep Your Developer Skills Current with LearnDevNow!

The most comprehensive online learning library for Microsoft developers

is just $99.99! Visual Studio, SharePoint, SQL - plus HTML5, CSS3, MVC3,

Metro Style Apps, more. Free future releases when you subscribe now!

http://p.sf.net/sfu/learndevnow-d2d


Matplotlib-users mailing list

Matplotlib-users@lists.sourceforge.net

https://lists.sourceforge.net/lists/listinfo/matplotlib-users

What can be done with the current Matplotlib is to use the offset boxes.
Here is a modified version of a code snippet from

http://abitofpythonabitofastronomy.blogspot.com/2009/05/mpl-multicolor-text.html

Regards,

-JJ

from matplotlib.offsetbox import HPacker, TextArea, AnnotationBbox

f = figure(1)
ax = f.add_subplot(111)

txt1 = TextArea("A$^3$", textprops=dict(color="r", size=150))
txt2 = TextArea("gb", textprops=dict(color="k", size=150))

txt = HPacker(children=[txt1, txt2],
            align="baseline",
            pad=0, sep=0)

bbox = AnnotationBbox(txt, xy=(0.5, 0.5),
                       xycoords='data',
                       frameon=False,
                       box_alignment=(0.5, 0.5), # alignment center, center
                       )

ax.add_artist(bbox)

show()

···

On Wed, Feb 8, 2012 at 7:44 AM, Yann Tambouret <yannpaul@...728...> wrote:

Along the lines of Mike's suggestion, I thought this could be done using
Latex.

I posted an answer on SO with an example of doing this, but it seems only to
work with postscript backend. Other backends override the color with the mpl
text color setting.

Is there a way to prevent this override? For example don't try to use 'PS'
backend, and look at hte figure interactively. It defaults to black.

http://stackoverflow.com/a/9185143/717357

-Yann

On Tue, Feb 7, 2012 at 4:46 PM, Paul Ivanov <pivanov314@...287...> wrote:

Benjamin Root, on 2012-02-07 13:46, wrote:
> Also, how deep should this rabbit hole go? I could imagine one could
> want
> this for title() and figtitle(). Maybe it would be best to implement
> this
> at the Text() constructor level?

For this reason, I would discourage even implementing such
functionality in the core of matplotlib. This functionality doesn't strike
me
as something that ought to be available everywhere by default - if someone
needs it, they can implement it as follows:

-----
import matplotlib.pyplot as plt
from matplotlib import transforms

def rainbow_text(x,y,ls,lc,**kw):
"""
Take a list of strings ``ls`` and colors ``lc`` and place them next to
each
other, with text ls[i] being shown in color lc[i].

This example shows how to do both vertical and horizontal text, and
will
pass all keyword arguments to plt.text, so you can set the font size,
family, etc.
"""
t = plt.gca().transData
fig = plt.gcf()
plt.show()

#horizontal version
for s,c in zip(ls,lc):
text = plt.text(x,y," "+s+" ",color=c, transform=t, **kw)
text.draw(fig.canvas.get_renderer())
ex = text.get_window_extent()
t = transforms.offset_copy(text._transform, x=ex.width,
units='dots')

#vertical version
for s,c in zip(ls,lc):
text = plt.text(x,y," "+s+" ",color=c, transform=t,
rotation=90,va='bottom',ha='center',**kw)
text.draw(fig.canvas.get_renderer())
ex = text.get_window_extent()
t = transforms.offset_copy(text._transform, y=ex.height,
units='dots')

plt.figure()
rainbow_text(0.5,0.5,"all unicorns poop rainbows ! ! !".split(),
['red', 'orange', 'brown', 'green', 'blue', 'purple', 'black'],
size=40)

best,
--
Paul Ivanov
314 address only used for lists, off-list direct email at:
http://pirsquared.org | GPG/PGP key id: 0x0F3E28F7

------------------------------------------------------------------------------
Keep Your Developer Skills Current with LearnDevNow!
The most comprehensive online learning library for Microsoft developers
is just $99.99! Visual Studio, SharePoint, SQL - plus HTML5, CSS3, MVC3,
Metro Style Apps, more. Free future releases when you subscribe now!
http://p.sf.net/sfu/learndevnow-d2d
_______________________________________________
Matplotlib-users mailing list
Matplotlib-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-users

------------------------------------------------------------------------------
Keep Your Developer Skills Current with LearnDevNow!
The most comprehensive online learning library for Microsoft developers
is just $99.99! Visual Studio, SharePoint, SQL - plus HTML5, CSS3, MVC3,
Metro Style Apps, more. Free future releases when you subscribe now!
http://p.sf.net/sfu/learndevnow-d2d
_______________________________________________
Matplotlib-users mailing list
Matplotlib-users@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/matplotlib-users

This is the solution which requires the least modification to the original text inserting functions. The only drawback is like you said, it only works with ps backend.

Any idea if this could be generalized for other backends?

···

On Tue, Feb 7, 2012 at 3:44 PM, Yann Tambouret <yannpaul@…83…728…> wrote:

Along the lines of Mike’s suggestion, I thought this could be done using Latex.

I posted an answer on SO with an example of doing this, but it seems only to work with postscript backend. Other backends override the color with the mpl text color setting.

Is there a way to prevent this override? For example don’t try to use ‘PS’ backend, and look at hte figure interactively. It defaults to black.

http://stackoverflow.com/a/9185143/717357

-Yann

On Tue, Feb 7, 2012 at 4:46 PM, Paul Ivanov <pivanov314@…287…> wrote:

Benjamin Root, on 2012-02-07 13:46, wrote:

Also, how deep should this rabbit hole go? I could imagine one could want

this for title() and figtitle(). Maybe it would be best to implement this

at the Text() constructor level?

For this reason, I would discourage even implementing such

functionality in the core of matplotlib. This functionality doesn’t strike me

as something that ought to be available everywhere by default - if someone

needs it, they can implement it as follows:


import matplotlib.pyplot as plt

from matplotlib import transforms

def rainbow_text(x,y,ls,lc,**kw):

"""

Take a list of strings ``ls`` and colors ``lc`` and place them next to each

other, with text ls[i] being shown in color lc[i].



This example shows how to do both vertical and horizontal text, and will

pass all keyword arguments to plt.text, so you can set the font size,

family, etc.

"""

t = plt.gca().transData

fig = plt.gcf()

plt.show()



#horizontal version

for s,c in zip(ls,lc):

    text = plt.text(x,y," "+s+" ",color=c, transform=t, **kw)

    text.draw(fig.canvas.get_renderer())

    ex = text.get_window_extent()

    t = transforms.offset_copy(text._transform, x=ex.width, units='dots')



#vertical version

for s,c in zip(ls,lc):

    text = plt.text(x,y," "+s+" ",color=c, transform=t,

            rotation=90,va='bottom',ha='center',**kw)

    text.draw(fig.canvas.get_renderer())

    ex = text.get_window_extent()

    t = transforms.offset_copy(text._transform, y=ex.height, units='dots')

plt.figure()

rainbow_text(0.5,0.5,“all unicorns poop rainbows ! ! !”.split(),

    ['red', 'orange', 'brown', 'green', 'blue', 'purple', 'black'],

    size=40)

best,

Paul Ivanov

314 address only used for lists, off-list direct email at:

http://pirsquared.org | GPG/PGP key id: 0x0F3E28F7


Keep Your Developer Skills Current with LearnDevNow!

The most comprehensive online learning library for Microsoft developers

is just $99.99! Visual Studio, SharePoint, SQL - plus HTML5, CSS3, MVC3,

Metro Style Apps, more. Free future releases when you subscribe now!

http://p.sf.net/sfu/learndevnow-d2d


Matplotlib-users mailing list

Matplotlib-users@lists.sourceforge.net

https://lists.sourceforge.net/lists/listinfo/matplotlib-users


Keep Your Developer Skills Current with LearnDevNow!

The most comprehensive online learning library for Microsoft developers

is just $99.99! Visual Studio, SharePoint, SQL - plus HTML5, CSS3, MVC3,

Metro Style Apps, more. Free future releases when you subscribe now!

http://p.sf.net/sfu/learndevnow-d2d


Matplotlib-users mailing list

Matplotlib-users@lists.sourceforge.net

https://lists.sourceforge.net/lists/listinfo/matplotlib-users


Gökhan