[IPython-User] Runtime selection of the default pretty display

classic Classic list List threaded Threaded
9 messages Options
Reply | Threaded
Open this post in threaded view
|

[IPython-User] Runtime selection of the default pretty display

Akim Demaille
[reresent, I guess you need to be member, but I never received
any message about this]
[resent, the message didn't show up and I received no message
from mailman about needed membership]

Hi!

I'm working on an environment for automata, and render them
as SVG inside an IPython console (typically web based).  Automata
can be really large, in which case rendering them is useless.
However the user is the one who should decide.

So I have a number of different output formats, SVG being one
of them, and I'd like to be able to select the appropriate
output format based on some metrics on the automaton.

I know I can have _repr_svg_ return None for instance if I
think the automaton is too big, in which case another format
will be chosen.  However, the user should be free to call
_repr_svg_ on such a large automaton, and get a real result,
not a None.

So what I'd like is a means to control which _repr_ IPython's
display will chose.  Is there such a feature?  What is the best
practice to do what I what?  Should I consider the user should
not be able to depend upon _repr_svg_?  Where is the piece of
documentation I missed?

I have a different question, but which is connected, so I should
probably pack my second question here too.

I would like to offer the user a means to select the display
for my automata.  So I use interact to this end:

def _automaton_display(self, mode):
    """Display automaton `self` with a local menu to propose different
    formats.
    """
    if mode == "dot" or mode == "tooltip":
        dot = _one_epsilon(self.format("dot"))
        if mode == "tooltip":
            dot = re.sub(r'label = (".*?"), shape = box, style = rounded',
                         r'tooltip = \1',
                         dot)
        svg = _dot_to_svg(dot)
        display(SVG(svg))
    elif mode == "info":
        display(self.info())
    elif mode == "type":
        display(repr(self))
    else:
        raise(ValueError("invalid display format: " + mode))

# Requires IPython 2.0.
try:
    from IPython.html.widgets import interact
    automaton.display = \
        lambda self: interact(lambda mode: _automaton_display(self, mode),
                              mode = ['dot', 'info', 'tooltip', 'type'])
except ImportError:
    pass

I have two issues:

- this requires that the user run 'myautomaton.display()' although
  I would like this to be the default output for automata, how can
  I do that?  (i.e., have something like _repr_widget_).

- when called, this piece of code displays

   Out [3]: <function vcsn.automaton.<lambda>>

  How can I get rid of this?

Thanks in advance for the answers, and in retrospect for this
brilliant piece of software!

Akim



_______________________________________________
IPython-User mailing list
[hidden email]
http://mail.scipy.org/mailman/listinfo/ipython-user
Reply | Threaded
Open this post in threaded view
|

Re: Runtime selection of the default pretty display

Matthias Bussonnier

Le 29 mai 2014 à 14:29, Akim Demaille a écrit :

> [reresent, I guess you need to be member, but I never received
> any message about this]
> [resent, the message didn't show up and I received no message
> from mailman about needed membership]

You shouldn't need to be member, but I would suggest mailing IPython-dev (and not user)
as we try to consolidate the two list in one.

>
> Hi!
>
> I'm working on an environment for automata, and render them
> as SVG inside an IPython console (typically web based).  Automata
> can be really large, in which case rendering them is useless.
> However the user is the one who should decide.
>
> So I have a number of different output formats, SVG being one
> of them, and I'd like to be able to select the appropriate
> output format based on some metrics on the automaton.
>
> I know I can have _repr_svg_ return None for instance if I
> think the automaton is too big, in which case another format
> will be chosen.  However, the user should be free to call
> _repr_svg_ on such a large automaton, and get a real result,
> not a None.
>
> So what I'd like is a means to control which _repr_ IPython's
> display will chose.  Is there such a feature?  

No, there is not.

> What is the best
> practice to do what I what?  Should I consider the user should
> not be able to depend upon _repr_svg_?  Where is the piece of
> documentation I missed?

define a public method for your object that return the svg e.g.:

def as_svg(self):
        return …

and make _repr_svg_ a simple wrapper

def _repr_svg_(self):
        if should_i_display_the_svg(self):
                return self.as_svg()
        else:
                return None

Rule of thumb, user should never have to call a methods that start with _ themselves.


>
> I have a different question, but which is connected, so I should
> probably pack my second question here too.
>
> I would like to offer the user a means to select the display
> for my automata.  So I use interact to this end:
>
>> def _automaton_display(self, mode):
>>     """Display automaton `self` with a local menu to propose different
>>     formats.
>>     """
>>     if mode == "dot" or mode == "tooltip":
>>         dot = _one_epsilon(self.format("dot"))
>>         if mode == "tooltip":
>>             dot = re.sub(r'label = (".*?"), shape = box, style = rounded',
>>                          r'tooltip = \1',
>>                          dot)
>>         svg = _dot_to_svg(dot)
>>         display(SVG(svg))
>>     elif mode == "info":
>>         display(self.info())
>>     elif mode == "type":
>>         display(repr(self))
>>     else:
>>         raise(ValueError("invalid display format: " + mode))
>>
>> # Requires IPython 2.0.
>> try:
>>     from IPython.html.widgets import interact
>>     automaton.display = \
>>         lambda self: interact(lambda mode: _automaton_display(self, mode),
>>                               mode = ['dot', 'info', 'tooltip', 'type'])
>> except ImportError:
>>     pass
>
> I have two issues:
>
> - this requires that the user run 'myautomaton.display()' although
>   I would like this to be the default output for automata, how can
>   I do that?  (i.e., have something like _repr_widget_).
>
> - when called, this piece of code displays
>
>    Out [3]: <function vcsn.automaton.<lambda>>
>
>   How can I get rid of this?

You cannot, the last syntactic block of code has a value, it will be displayed.

Il might get better if you fix your above problem of foo.display(), maybe using `_repr_mime_` in ipython
but i do not remember if you can do it with widgets.
Keep in mind that widget are still at the beginning, so missing pieces might still arise.

>
> Thanks in advance for the answers, and in retrospect for this
> brilliant piece of software!

Thanks.

--
M
_______________________________________________
IPython-User mailing list
[hidden email]
http://mail.scipy.org/mailman/listinfo/ipython-user
Reply | Threaded
Open this post in threaded view
|

Re: Runtime selection of the default pretty display

Akim Demaille
hi Matthias,

Thanks for your answer.

Le 29 mai 2014 à 14:56, Matthias Bussonnier <[hidden email]> a écrit :

>
> Le 29 mai 2014 à 14:29, Akim Demaille a écrit :
>
>> [reresent, I guess you need to be member, but I never received
>> any message about this]
>> [resent, the message didn't show up and I received no message
>> from mailman about needed membership]
>
> You shouldn't need to be member, but I would suggest mailing IPython-dev (and not user)
> as we try to consolidate the two list in one.

OK.  We'll see if my message makes it there too.

>> So what I'd like is a means to control which _repr_ IPython's
>> display will chose.  Is there such a feature?  
>
> No, there is not.

Do you think that would be useful?

> Rule of thumb, user should never have to call a methods that start with _ themselves.

OK, thanks.

>> I have a different question, but which is connected, so I should
>> probably pack my second question here too.
>>
>> I would like to offer the user a means to select the display
>> for my automata.  So I use interact to this end:
>>
>>> def _automaton_display(self, mode):
>>>    """Display automaton `self` with a local menu to propose different
>>>    formats.
>>>    """
>>>    if mode == "dot" or mode == "tooltip":
>>>        dot = _one_epsilon(self.format("dot"))
>>>        if mode == "tooltip":
>>>            dot = re.sub(r'label = (".*?"), shape = box, style = rounded',
>>>                         r'tooltip = \1',
>>>                         dot)
>>>        svg = _dot_to_svg(dot)
>>>        display(SVG(svg))
>>>    elif mode == "info":
>>>        display(self.info())
>>>    elif mode == "type":
>>>        display(repr(self))
>>>    else:
>>>        raise(ValueError("invalid display format: " + mode))
>>>
>>> # Requires IPython 2.0.
>>> try:
>>>    from IPython.html.widgets import interact
>>>    automaton.display = \
>>>        lambda self: interact(lambda mode: _automaton_display(self, mode),
>>>                              mode = ['dot', 'info', 'tooltip', 'type'])
>>> except ImportError:
>>>    pass
>>
>> I have two issues:
>>
>> - this requires that the user run 'myautomaton.display()' although
>>  I would like this to be the default output for automata, how can
>>  I do that?  (i.e., have something like _repr_widget_).
>>
>> - when called, this piece of code displays
>>
>>   Out [3]: <function vcsn.automaton.<lambda>>
>>
>>  How can I get rid of this?
>
> You cannot, the last syntactic block of code has a value, it will be displayed.

Well, I'm not really an expect Python programmer, so maybe you
thought I would have thought of another means and rejected it,
but no, I did not :)  So yes, I can have what I was asking for,
provided I avoid the outer lambda (lambdas are so sadly poor in
Python :-/):

> # Requires IPython 2.0.
> def _automaton_interact(self):
>     """Display automaton `self` with a local menu to the select
>     the display mode.  Pay attention to not displaying large
>     automata by default.
>     """
>     from IPython.html.widgets import interact
>     if 20 < self.state_number():
>         modes = ['info', 'dot']
>     else:
>         modes = ['dot', 'info']
>     modes += ['info,detailed', 'tooltip', 'type', 'dot2tex']
>     interact(lambda mode: _automaton_display(self, mode), mode = modes)
>
> automaton.display = _automaton_interact

This does exactly what I want.

> Il might get better if you fix your above problem of foo.display(), maybe using `_repr_mime_` in ipython
> but i do not remember if you can do it with widgets.

I have not found a means to use _repr_mime_ here

> Keep in mind that widget are still at the beginning, so missing pieces might still arise.

Sure.  I'd like to suggest something like _repr_widget_ or
whatever that would allow to provide an interactive widget
as representation.  That would be really awesome.

Cheers,

        Akim

_______________________________________________
IPython-User mailing list
[hidden email]
http://mail.scipy.org/mailman/listinfo/ipython-user
Reply | Threaded
Open this post in threaded view
|

Re: Runtime selection of the default pretty display

Matthias Bussonnier
Hi Akim.

>>> So what I'd like is a means to control which _repr_ IPython's
>>> display will chose.  Is there such a feature?  
>>
>> No, there is not.
>
> Do you think that would be useful?

No it is by design. If you need the functionality, you are probably misunderstanding the way it works.
As a library author you shouldn't decide for the user, if the user really want to change, he/she import
display_whatever from IPython.display and call it on your object. Any tentative to do something else,
will break things in weird ways.


>> You cannot, the last syntactic block of code has a value, it will be displayed.
>
> Well, I'm not really an expect Python programmer, so maybe you
> thought I would have thought of another means and rejected it,
> but no, I did not :)  So yes, I can have what I was asking for,
> provided I avoid the outer lambda (lambdas are so sadly poor in
> Python :-/):
>
>> # Requires IPython 2.0.
>> def _automaton_interact(self):
>>    """Display automaton `self` with a local menu to the select
>>    the display mode.  Pay attention to not displaying large
>>    automata by default.
>>    """
>>    from IPython.html.widgets import interact
>>    if 20 < self.state_number():
>>        modes = ['info', 'dot']
>>    else:
>>        modes = ['dot', 'info']
>>    modes += ['info,detailed', 'tooltip', 'type', 'dot2tex']
>>    interact(lambda mode: _automaton_display(self, mode), mode = modes)
>>
>> automaton.display = _automaton_interact
>
> This does exactly what I want.
>
>> Il might get better if you fix your above problem of foo.display(), maybe using `_repr_mime_` in ipython
>> but i do not remember if you can do it with widgets.
>
> I have not found a means to use _repr_mime_ here
>
>> Keep in mind that widget are still at the beginning, so missing pieces might still arise.
>
> Sure.  I'd like to suggest something like _repr_widget_ or
> whatever that would allow to provide an interactive widget
> as representation.  That would be really awesome.

Widget are not my area of expertise, I haven't played a lot with them, so I'll let other respond.
--
M



> Cheers,
>
> Akim
>
> _______________________________________________
> IPython-User mailing list
> [hidden email]
> http://mail.scipy.org/mailman/listinfo/ipython-user

_______________________________________________
IPython-User mailing list
[hidden email]
http://mail.scipy.org/mailman/listinfo/ipython-user
Reply | Threaded
Open this post in threaded view
|

Re: Runtime selection of the default pretty display

Akim Demaille

Le 1 juin 2014 à 22:11, Matthias Bussonnier <[hidden email]> a écrit :

> Hi Akim.

hi!

>>>> So what I'd like is a means to control which _repr_ IPython's
>>>> display will chose.  Is there such a feature?  
>>>
>>> No, there is not.
>>
>> Do you think that would be useful?
>
> No it is by design. If you need the functionality, you are probably misunderstanding the way it works.
> As a library author you shouldn't decide for the user, if the user really want to change, he/she import
> display_whatever from IPython.display and call it on your object. Any tentative to do something else,
> will break things in weird ways.

Well, I think I agree with what you are saying, but let me
reemphasize that my problem here is rendering automata.
Small automata should be rendered with _repr_svg_, bigger
ones should just display some metrics by default, such as
their size.  So I would have _repr_svg_ return None in such
a case.  And that's a means to control which _repr_ will
chose.  Except that it's decentralized: the logic of which
_repr_ is 'enabled' is spread in each one of them.  As a
library author I do not want to prevent what the user
will see, I'm trying to provide them with the best _default_
behavior possible.

_repr_widget_ would be my best bet currently, as it allows
me to select the best default behavior, and leave at the user
the choice to select other formats.

(And btw, I'm not pushing my users to call IPython.display
at all, I'm really referring to the default display of values).
_______________________________________________
IPython-User mailing list
[hidden email]
http://mail.scipy.org/mailman/listinfo/ipython-user
Reply | Threaded
Open this post in threaded view
|

Re: Runtime selection of the default pretty display

Aaron Meurer
This sort of thing has come up in the context of SymPy before as well.
SymPy can render equations using MathJax, but it can also render them
as png using LaTeX itself (if it is installed). The notebook always
prefers MathJax to png, so the only way to force png output is to not
include the mathjax output, which is what
sympy.init_printing(use_latex='png') does. But this is obviously not
ideal (if something else pulls the latex off an object, it will think
that these objects don't have that representation). So I definitely
think there should be a way to change IPython's preferred order of
printing for different frontends.

Aaron Meurer

On Sun, Jun 1, 2014 at 3:42 PM, Akim Demaille <[hidden email]> wrote:

>
> Le 1 juin 2014 à 22:11, Matthias Bussonnier <[hidden email]> a écrit :
>
>> Hi Akim.
>
> hi!
>
>>>>> So what I'd like is a means to control which _repr_ IPython's
>>>>> display will chose.  Is there such a feature?
>>>>
>>>> No, there is not.
>>>
>>> Do you think that would be useful?
>>
>> No it is by design. If you need the functionality, you are probably misunderstanding the way it works.
>> As a library author you shouldn't decide for the user, if the user really want to change, he/she import
>> display_whatever from IPython.display and call it on your object. Any tentative to do something else,
>> will break things in weird ways.
>
> Well, I think I agree with what you are saying, but let me
> reemphasize that my problem here is rendering automata.
> Small automata should be rendered with _repr_svg_, bigger
> ones should just display some metrics by default, such as
> their size.  So I would have _repr_svg_ return None in such
> a case.  And that's a means to control which _repr_ will
> chose.  Except that it's decentralized: the logic of which
> _repr_ is 'enabled' is spread in each one of them.  As a
> library author I do not want to prevent what the user
> will see, I'm trying to provide them with the best _default_
> behavior possible.
>
> _repr_widget_ would be my best bet currently, as it allows
> me to select the best default behavior, and leave at the user
> the choice to select other formats.
>
> (And btw, I'm not pushing my users to call IPython.display
> at all, I'm really referring to the default display of values).
> _______________________________________________
> IPython-User mailing list
> [hidden email]
> http://mail.scipy.org/mailman/listinfo/ipython-user
_______________________________________________
IPython-User mailing list
[hidden email]
http://mail.scipy.org/mailman/listinfo/ipython-user
Reply | Threaded
Open this post in threaded view
|

Re: [IPython-dev] Runtime selection of the default pretty display

Matthias Bussonnier

Le 2 juin 2014 à 03:30, Aaron Meurer a écrit :

> This sort of thing has come up in the context of SymPy before as well.
> SymPy can render equations using MathJax, but it can also render them
> as png using LaTeX itself (if it is installed). The notebook always
> prefers MathJax to png, so the only way to force png output is to not
> include the mathjax output, which is what
> sympy.init_printing(use_latex='png') does. But this is obviously not
> ideal (if something else pulls the latex off an object, it will think
> that these objects don't have that representation). So I definitely
> think there should be a way to change IPython's preferred order of
> printing for different front ends.

But this shouldn't come from the library side but from the specific frontend you are using.
And for having thought of this many time you always end up in an infinite number of layer where
you want to overwrite the preference in the previous layer.

Also technically in the notebook it is not super hard to implement on a user-facing drop down.

The display priority is exposed as the following in javascript.
IPython.OutputArea.display_order // ["application/javascript", "text/html", "text/markdown", "text/latex", "image/svg+xml", "image/png", "image/jpeg", "application/pdf", "text/plain"]
Just monkey-patch it, Sympy will compute all and notebook store all, but display only the first.

--
M



>
> Aaron Meurer
>
> On Sun, Jun 1, 2014 at 3:42 PM, Akim Demaille <[hidden email]> wrote:
>>
>> Le 1 juin 2014 à 22:11, Matthias Bussonnier <[hidden email]> a écrit :
>>
>>> Hi Akim.
>>
>> hi!
>>
>>>>>> So what I'd like is a means to control which _repr_ IPython's
>>>>>> display will chose.  Is there such a feature?
>>>>>
>>>>> No, there is not.
>>>>
>>>> Do you think that would be useful?
>>>
>>> No it is by design. If you need the functionality, you are probably misunderstanding the way it works.
>>> As a library author you shouldn't decide for the user, if the user really want to change, he/she import
>>> display_whatever from IPython.display and call it on your object. Any tentative to do something else,
>>> will break things in weird ways.
>>
>> Well, I think I agree with what you are saying, but let me
>> reemphasize that my problem here is rendering automata.
>> Small automata should be rendered with _repr_svg_, bigger
>> ones should just display some metrics by default, such as
>> their size.  So I would have _repr_svg_ return None in such
>> a case.  And that's a means to control which _repr_ will
>> chose.  Except that it's decentralized: the logic of which
>> _repr_ is 'enabled' is spread in each one of them.  As a
>> library author I do not want to prevent what the user
>> will see, I'm trying to provide them with the best _default_
>> behavior possible.
>>
>> _repr_widget_ would be my best bet currently, as it allows
>> me to select the best default behavior, and leave at the user
>> the choice to select other formats.
>>
>> (And btw, I'm not pushing my users to call IPython.display
>> at all, I'm really referring to the default display of values).
>> _______________________________________________
>> IPython-User mailing list
>> [hidden email]
>> http://mail.scipy.org/mailman/listinfo/ipython-user
> _______________________________________________
> IPython-dev mailing list
> [hidden email]
> http://mail.scipy.org/mailman/listinfo/ipython-dev

_______________________________________________
IPython-User mailing list
[hidden email]
http://mail.scipy.org/mailman/listinfo/ipython-user
Reply | Threaded
Open this post in threaded view
|

Re: Runtime selection of the default pretty display

Matthias Bussonnier
In reply to this post by Akim Demaille

Le 1 juin 2014 à 22:42, Akim Demaille a écrit :

> Well, I think I agree with what you are saying, but let me
> reemphasize that my problem here is rendering automata.
> Small automata should be rendered with _repr_svg_, bigger
> ones should just display some metrics by default, such as
> their size.  So I would have _repr_svg_ return None in such
> a case.  And that's a means to control which _repr_ will
> chose.  Except that it's decentralized: the logic of which
> _repr_ is 'enabled' is spread in each one of them.  As a
> library author I do not want to prevent what the user
> will see, I'm trying to provide them with the best _default_
> behavior possible.

I understand, but your default make the assumption that the user is using
it in a live notebook and is focused on interactive usage.

inherently **choosing** one repr imply that others will not be computed and
not stored in the final document. It also start adding coupling between frontend and
kernel.

Also the _default_ value make little sens as it change depending on the context.
Do you run things headless ?  Notebook app ? Emacs ? Will you convert it using nbconvert after ?

For me explicit is better than implicit, I wouldn't try to guess the best for the user.

>
> _repr_widget_ would be my best bet currently, as it allows
> me to select the best default behavior, and leave at the user
> the choice to select other formats.

For me widget are slower to use than keyboard and methods like
.png() , .svg(), text() as I have to reach the mouse.


> (And btw, I'm not pushing my users to call IPython.display
> at all, I'm really referring to the default display of values).

But they are not only displayed they are stored in _ and for later conversion.
Display is a side effect.


--
M

_______________________________________________
IPython-User mailing list
[hidden email]
http://mail.scipy.org/mailman/listinfo/ipython-user
Reply | Threaded
Open this post in threaded view
|

Re: Runtime selection of the default pretty display

Akim Demaille
Hi Matthias,

I really appreciate your taking time to make detailed answers,
thanks a lot.

Le 2 juin 2014 à 10:10, Matthias Bussonnier <[hidden email]> a écrit :

> Le 1 juin 2014 à 22:42, Akim Demaille a écrit :
>
>> Well, I think I agree with what you are saying, but let me
>> reemphasize that my problem here is rendering automata.
>> Small automata should be rendered with _repr_svg_, bigger
>> ones should just display some metrics by default, such as
>> their size.  So I would have _repr_svg_ return None in such
>> a case.  And that's a means to control which _repr_ will
>> chose.  Except that it's decentralized: the logic of which
>> _repr_ is 'enabled' is spread in each one of them.  As a
>> library author I do not want to prevent what the user
>> will see, I'm trying to provide them with the best _default_
>> behavior possible.
>
> I understand, but your default make the assumption that the user is using
> it in a live notebook and is focused on interactive usage.

That is correct.  This is indeed my main use of IPython.  Actually
my users are not even Python programmers, they just want to interact
with the system and run computations on automata and rational expressions.
They don't want to call commands to display results.  When then run
"1+2", then don't expect to have to run anything to display the result.

> inherently **choosing** one repr imply that others will not be computed and
> not stored in the final document. It also start adding coupling between frontend and
> kernel.

Hm.  I see your point.  But when I compute a very large automaton
and display simple metrics, I do hope that behind the scene IPython
is not trying to render it a SVG, as I will never use this: it's
very long to compute, large to store, and very useless to look at.

> Also the _default_ value make little sens as it change depending on the context.
> Do you run things headless ?  Notebook app ? Emacs ? Will you convert it using nbconvert after ?

I'm not sure what you mean by "default value".  I'm saying that
somewhere in IPython there is an algorithm that decides which
rendering to chose based on some inputs (format, environment,
etc.).  It would be nice if there could be another input: hints
provided by the data itself on what makes sense and what does
not.

> For me explicit is better than implicit, I wouldn't try to guess the best for the user.

I concur.  But then again, I'm talking about the default
view.  Then the user can explicitly make another choice.

>> _repr_widget_ would be my best bet currently, as it allows
>> me to select the best default behavior, and leave at the user
>> the choice to select other formats.
>
> For me widget are slower to use than keyboard and methods like
> .png() , .svg(), text() as I have to reach the mouse.

It is for me too.  It drives me mad to see people playing
with their mouse just to copy some bit of text.  But I'm
not trying to educate my users: they want to click, so let
them be able to click.

Besides, you seem to believe that there are is little gain from
interactive rendering of data, and I am very surprised by this.
I expect that people rendering data will enjoy being able to
improve their rendering with interaction.

>> (And btw, I'm not pushing my users to call IPython.display
>> at all, I'm really referring to the default display of values).
>
> But they are not only displayed they are stored in _ and for later conversion.
> Display is a side effect.

Display is the major side effect.  Really.  Some of my users are
mathematicians and they don't care about Python.  They want
some kind of an interactive environment with minimal syntactic
idiosyncrasies, and IPython is an excellent incarnation of this.

Most of them don't even know about _.

_______________________________________________
IPython-User mailing list
[hidden email]
http://mail.scipy.org/mailman/listinfo/ipython-user