Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

IPython `display` to string

I am trying to use the IPython.display module to convert objects to Markdown. However, there does not seem to be a good way to export this Markdown as a string.

Behaviour:

>>> from IPython.display import *
>>> from numpy import *
>>> display_markdown(eye(3))
[[1. 0. 0.]
 [0. 1. 0.]
 [0. 0. 1.]]

Wanted behaviour:

>>> display_markdown_string(eye(3))
"$$\left( ... \right)$$"

Is there a good way to achieve this? It seems to me that this functionality has to present somewhere in IPython, since it can be done in the Notebooks.

like image 424
Synthetica Avatar asked Dec 19 '19 11:12

Synthetica


People also ask

What does Display () do in Python?

show command displays the form within the window that is running the Python script.

What is IPython display in Python?

IPython (Interactive Python) is a command shell for interactive computing in multiple programming languages, originally developed for the Python programming language, that offers introspection, rich media, shell syntax, tab completion, and history.

What is from IPython display import Clear_output?

You can use IPython. display. clear_output to clear the output of a cell.


1 Answers

You have misunderstood what display_markdown() does. It is not a function to convert representation formats. IPython doesn’t use Markdown to display the array, it just outputs plain text in this specific case.

The IPython display system expects the objects to provide the formatted output themselves, and markdown is just one of the different formats supported. Because objects could support multiple formats, you sometimes want to explicitly select one specific format. display_markdown() lets you select the markdown representation and ignore others. But if an object doesn't have a specific markdown representation, its standard repr() string is used instead, as a fall-back. See the Rich Display section of the integration documentation.

Numpy arrays do not have a markdown representation, so display_markdown() has nothing to work with. What you see printed is just the string produced by repr(eye(3)). So you could just use repr(eye(3)), and to use it in markdown, wrap it in backticks:

A = np.eye(3)
markdown_repr = f"```\n{A!r}\n```"

The !r syntax tells Python to take the output of repr(). The above produces the string:

"```\narray([[1., 0., 0.],\n       [0., 1., 0.],\n       [0., 0., 1.]])\n```

If you want to have representation of an array in LaTeX, then there are projects that do produce such representations of numpy arrays you could use; provided you wrap their result in $$ lines, you can then treat those as markdown output as Jupyter supports embedded Mathjax expressions (a subset of LaTeX).

For example, using array-to-latex:

from array_to_latex import to_ltx
to_markdown = lambda m: f"$$\n{to_ltx(m, print_out=False)}\n$$"
print(to_markdown(A))

produces

$$
\begin{bmatrix}
  1.00 &  0.00 &  0.00\\
  0.00 &  1.00 &  0.00\\
  0.00 &  0.00 &  1.00
\end{bmatrix}
$$

You don’t have to use a library (you can write your own text manipulation code to do something similar), but you can’t use IPython to do this.

Of course, once you have such a function, you could not only use it directly, but you can also teach IPython to use it for any numpy array. You can register it as a formatter for text/markdown with IPython, as a third-party formatter function:

md_formatter = get_ipython().display_formatter.formatters["text/markdown"]
md_formatter.for_type(np.ndarray, to_markdown)

Because the library I used outputs LaTeX you could just use to_ltx() directly (with print_out=False) to produce LaTeX output, which will also result in Mathjax output whenever you echo an array:

latex_formatter = get_ipython().display_formatter.formatters["text/latex"]
latex_formatter.for_type(np.ndarray, lambda m: to_ltx(m, print_out=False))

Either way, now you'll see a MathJax rendering of the array:

notebook demo with LaTeX representation of a numpy matrix

Now, if you wanted to access the different formats objects make available to IPython, then you want to use the IPython.core.formatters.format_display_data() function; this gives you two dictionaries, the first is a dictionary with the various representation mime types as keys. If there is a markdown conversion available for the object, then you'll find it under the "text/markdown" key:

from IPython.core.formatters import format_display_data
formatted, metadata = format_display_data(A)
formatted["text/markdown"]

Because I already registered a markdown formatter for numpy arrays, the above produces the output of to_markdown() for us:

'$$\n\\begin{bmatrix}\n  1.00 &  0.00 &  0.00\\\\\n  0.00 &  1.00 &  0.00\\\\\n  0.00 &  0.00 &  1.00\n\\end{bmatrix}\n$$'

but without additional rich display registrations, all you'd get is a "text/plain" entry.

like image 125
Martijn Pieters Avatar answered Sep 28 '22 14:09

Martijn Pieters