Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Added IPython LaTeX representation method for StateSpace objects#450

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged

Conversation

roryyorke
Copy link
Contributor

Added StateSpace method_repr_latex_, which returns a
MathJax-centric LaTeX representation of the instance.

Added twostatesp configuration options for this representation.
One affects number formatting, and the other chooses the output type.

Partially addesses#278; see much discussion there on this.

Example athttps://nbviewer.jupyter.org/gist/roryyorke/6879e0b20735f533410dad883eb687e5.

@coveralls
Copy link

coveralls commentedAug 15, 2020
edited
Loading

Coverage Status

Coverage increased (+0.1%) to 87.083% when pulling91b04de on roryyorke:rory/ss-repr-latex intobbb2e36 on python-control:master.

@coveralls
Copy link

Coverage Status

Coverage increased (+0.1%) to 84.361% when pulling96cd45a on roryyorke:rory/ss-repr-latex intod3142ff on python-control:master.

[],
[[1.2345,-2e-200],[-1,0]])

g1_p3_p = '\\[\n\\left(\n\\begin{array}{rllrll|rll}\n3.&\\hspace{-1em}14&\\hspace{-1em}\\phantom{\\cdot}&1\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\cdot10^{100}&0\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}\\\\\n-1.&\\hspace{-1em}23&\\hspace{-1em}\\phantom{\\cdot}&5\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\cdot10^{-23}&1\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}\\\\\n\\hline\n9.&\\hspace{-1em}88&\\hspace{-1em}\\cdot10^{8}&0.&\\hspace{-1em}00123&\\hspace{-1em}\\phantom{\\cdot}&5\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}\\\\\n\\end{array}\\right)\n\\]'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

maybe reformat asr'' strings for better readability?

Copy link
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

These were generated. Can one coaxrepr (or whatever) to spit out raw strings?

@@ -561,6 +561,69 @@ def test_str(self):
assert str(sysdt1) == tref + "\ndt = 1.0\n"


def test_latex_repr(self):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

In the spirit of#438:

There are 4 identical tests with parameter variations. I suggest you use something like

@pytest.mark.parametrize("g, repr_latex, p3ref, p5ref",        [(g1,None,g1_p3_p,g1_p5_p),         (g1,"partitioned",g1_p3_p,g1_p5_p),         (g1,"separate",g1_p3_s,g1_p5_s),         (g2,"partitioned",g2_p3_p,g2_p5_p),         (g2,"separate",g2_p3_s,g2_p5_s)])deftest_latex_repr(self,g,repr_latex,p3ref,p5ref):try:# add "editsdefaults" fixture and remove the reset_defaults as soon as #438 is mergedreset_defaults()ifrepr_latexisnotNone:set_defaults('statesp',latex_repr_type=repr_latex)assertg1._repr_latex_()==p3refset_defaults('statesp',latex_num_format='.5g')assertg1._repr_latex_()==p5reffinally:reset_defaults()

Copy link
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

OK, looks good. Would this need to wait for#438, or do we already have pytest as a dependency?

Copy link
Contributor

@bnavigatorbnavigatorAug 15, 2020
edited
Loading

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Except for theeditsdefaults part, which is introduced by that PR, you should be able to do it right away. Pytest is already used and required on other tests.

See#437

@bnavigator
Copy link
Contributor

Example athttps://nbviewer.jupyter.org/gist/roryyorke/6879e0b20735f533410dad883eb687e5.

Github also renders ipynb. You could add a demonstrating example to the docs.

@roryyorke
Copy link
ContributorAuthor

Github also renders ipynb. You could add a demonstrating example to the docs.

AFAIK Githubdoesn't render the LaTeX; the notebook is actually a gist athttps://gist.github.com/roryyorke/6879e0b20735f533410dad883eb687e5, where you can see the lack of LaTeX rendering. I gather there are workarounds, but I haven't investigated.

Thanks for the review!

@bnavigator
Copy link
Contributor

I wonder what's different in sympy:
https://github.com/sympy/sympy/blob/master/examples/notebooks/Sylvester_resultant.ipynb

The output fields have latex, png and text

{   "cell_type": "code",   "execution_count": 4,   "metadata": {},   "outputs": [    {     "data": {      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAPwAAAAcBAMAAAC3wc/WAAAAMFBMVEX///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAv3aB7AAAAD3RSTlMAMkS7zRCZdiKJ71Rmq90icBAQAAAACXBIWXMAAA7EAAAOxAGVKw4bAAADWUlEQVRIDb1XTWgTQRh9+c82aRrEe+NJFKSBokdbMTe1nUOhKNQGqxFRaC5trSBdFIqC2IDY2oM0aAXpQYOiCD2YkwepoviP4B+19VRrMVSpGGd2djYzyaaki3Sgme9733vvy+zMTihgjdEdxIodBlrPEYdKaHp9q1Ot0F3BSxHWPG/gzIju+lWzpgrxGxr1KiUbOM0wV5xXIrHgkg1nTdAXjMRqF2xjVK+146FC7dJqzIeWWzVGCdfyND5q5RHjaVipo2B+LaqvQLC05NEyqbfPdbwM4un4YNQWB7SkWgiOX8qpCM+CqWZq0S8LwmVS1BWLGTttR8zfaodT7FEZPozQnzLISLug0YM2AtRZ324LNqlM79WTChBK83QHPHGlYCXujDtqJSwYyuGvDAiLV8AUEMmjkZhl157p7TITqFdTmFp39fdz4/RdYce1W2O+n7KLaH8L+BiFP47Hokof9aKI+VylvSer0qTsdrEoZUaoPnzRvp2w9oEsDlNS5+kzg+lyHV39TH8UvoG3m8d4zdQ27Bo7VEGWaGrtYMbGglG+E7gLaAZ8mfB8pFVVscxD6EW0H0/Ts7xmtu/eKx0YoZJoAjLm83PExoKW3L/pjfcD++jhJ1ohpCsqkezEZUyQBzwV7Qvw3xAEMUs0AfFZu2ZjQUuRZ/SlX8IcXT28cUvja1ugYzbKgV6dYLcRaolE22QiQUUNnxCuuJ4FjXFViykiaiULSkrRv+AKWz11TLPP8kF/vSZiwLLAzdXTfQrbvMwWTdDZfA5oyVVaAIEkrdLVG+0bzcUyRWlMAr2EbZA5zPb1WZvVSzRBZ3ORsPYVFsB9BHXQn9gXQIgMIUBkFY+TwCzuBRbRx3OzvYvufZYjpU+JVgKB6/SE61LNtIAriYDOTv4poCnXgguyyIyHEb7pXvEsBvMcENp3OJBTbxPINNlpBqFluSYsLo6PfgDCWTQRdA10njA7yFIEj70mvjd9/TMmKrRa6jmwoDwumSZ7uFM9MbkmLNqLRXoZ01uvLibTV42F1iBVeVNXNaD7nJYJ3jT8GRlYNfbpUlmT4tpDxQLd9GBnaxfLzE45cRg/obr3zrR5ZzJF9ZlmHQqynkmY7XsouZ4t5V5njeSODK1n7Pg/ov/2Jf8B6oTd7JsJTuYAAAAASUVORK5CYII=\n",      "text/latex": [       "$$\\left ( x^{2} - 5 x + 6, \\quad x^{2} - 3 x + 2\\right )$$"      ],      "text/plain": [       "⎛ 2             2          ⎞\n",       "⎝x  - 5⋅x + 6, x  - 3⋅x + 2⎠"      ]     },     "execution_count": 4,     "metadata": {},     "output_type": "execute_result"    }   ],   "source": [    "f, g"   ]  },

@roryyorke
Copy link
ContributorAuthor

It looks like sympy'sinit_printing arranges for the relevant magic; see extract from its docstring below.

I'm not up to implementing this; if wedo want it, I think we should see if we can use Sympy to achieve it.

    use_latex : string, boolean, or None, default=None        If True, use default LaTeX rendering in GUI interfaces (png and        mathjax);        if False, do not use LaTeX rendering;        if None, make a guess based on the environment;        if 'png', enable latex rendering with an external latex compiler,        falling back to matplotlib if external compilation fails;        if 'matplotlib', enable LaTeX rendering with matplotlib;        if 'mathjax', enable LaTeX text generation, for example MathJax        rendering in IPython notebook or text rendering in LaTeX documents;        if 'svg', enable LaTeX rendering with an external latex compiler,        no fallback

@bnavigator
Copy link
Contributor

Not within the scope of this PR, I guess. I was just curious.

@bnavigatorbnavigator added this to the0.9.0 milestoneAug 16, 2020
@bnavigatorbnavigator linked an issueAug 16, 2020 that may beclosed by this pull request
@roryyorke
Copy link
ContributorAuthor

roryyorke commentedAug 19, 2020 via email

It looks like black recently merged a feature to wrap strings like this:bbugyi200:182-wrap-long-strings (black PR 1132 - previous is some Githubgenerated name?). I'll try it this weekend.It also occurred to me that I don't know if QtConsole for IPython usessomething else for LaTeX rendering, or does such rendering at all. If thatis easy to install via conda I'll check that too.Are you aiming this at 0.9.0?
On Mon, 17 Aug 2020, 21:19 Ben Greiner, ***@***.***> wrote: ***@***.**** commented on this pull request. ------------------------------ In control/tests/statesp_test.py <#450 (comment)> : > +# test data for test_latex_repr, below +LTX_G1 = StateSpace([[np.pi, 1e100],[-1.23456789, 5e-23]], + [[0], [1]], + [[987654321, 0.001234]], + [[5]]) + + +LTX_G2 = StateSpace([], + [], + [], + [[1.2345,-2e-200],[-1,0]]) + + +LTX_REF = { + 'g1_p3_p' : '\\[\n\\left(\n\\begin{array}{rllrll|rll}\n3.&\\hspace{-1em}14&\\hspace{-1em}\\phantom{\\cdot}&1\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\cdot10^{100}&0\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}\\\\\n-1.&\\hspace{-1em}23&\\hspace{-1em}\\phantom{\\cdot}&5\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\cdot10^{-23}&1\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}\\\\\n\\hline\n9.&\\hspace{-1em}88&\\hspace{-1em}\\cdot10^{8}&0.&\\hspace{-1em}00123&\\hspace{-1em}\\phantom{\\cdot}&5\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}\\\\\n\\end{array}\\right)\n\\]', + + 'g1_p5_p' : '\\[\n\\left(\n\\begin{array}{rllrll|rll}\n3.&\\hspace{-1em}1416&\\hspace{-1em}\\phantom{\\cdot}&1\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\cdot10^{100}&0\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}\\\\\n-1.&\\hspace{-1em}2346&\\hspace{-1em}\\phantom{\\cdot}&5\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\cdot10^{-23}&1\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}\\\\\n\\hline\n9.&\\hspace{-1em}8765&\\hspace{-1em}\\cdot10^{8}&0.&\\hspace{-1em}001234&\\hspace{-1em}\\phantom{\\cdot}&5\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}\\\\\n\\end{array}\\right)\n\\]', + + 'g1_p3_s' : '\\[\n\\begin{array}{ll}\nA = \\left(\\begin{array}{rllrll}\n3.&\\hspace{-1em}14&\\hspace{-1em}\\phantom{\\cdot}&1\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\cdot10^{100}\\\\\n-1.&\\hspace{-1em}23&\\hspace{-1em}\\phantom{\\cdot}&5\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\cdot10^{-23}\\\\\n\\end{array}\\right)\n&\nB = \\left(\\begin{array}{rll}\n0\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}\\\\\n1\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}\\\\\n\\end{array}\\right)\n\\\\\nC = \\left(\\begin{array}{rllrll}\n9.&\\hspace{-1em}88&\\hspace{-1em}\\cdot10^{8}&0.&\\hspace{-1em}00123&\\hspace{-1em}\\phantom{\\cdot}\\\\\n\\end{array}\\right)\n&\nD = \\left(\\begin{array}{rll}\n5\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}\\\\\n\\end{array}\\right)\n\\end{array}\n\\]', + + 'g1_p5_s' : '\\[\n\\begin{array}{ll}\nA = \\left(\\begin{array}{rllrll}\n3.&\\hspace{-1em}1416&\\hspace{-1em}\\phantom{\\cdot}&1\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\cdot10^{100}\\\\\n-1.&\\hspace{-1em}2346&\\hspace{-1em}\\phantom{\\cdot}&5\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\cdot10^{-23}\\\\\n\\end{array}\\right)\n&\nB = \\left(\\begin{array}{rll}\n0\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}\\\\\n1\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}\\\\\n\\end{array}\\right)\n\\\\\nC = \\left(\\begin{array}{rllrll}\n9.&\\hspace{-1em}8765&\\hspace{-1em}\\cdot10^{8}&0.&\\hspace{-1em}001234&\\hspace{-1em}\\phantom{\\cdot}\\\\\n\\end{array}\\right)\n&\nD = \\left(\\begin{array}{rll}\n5\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}\\\\\n\\end{array}\\right)\n\\end{array}\n\\]', + + 'g2_p3_p' : '\\[\n\\left(\n\\begin{array}{rllrll}\n1.&\\hspace{-1em}23&\\hspace{-1em}\\phantom{\\cdot}&-2\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\cdot10^{-200}\\\\\n-1\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}&0\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}\\\\\n\\end{array}\\right)\n\\]', + + 'g2_p5_p' : '\\[\n\\left(\n\\begin{array}{rllrll}\n1.&\\hspace{-1em}2345&\\hspace{-1em}\\phantom{\\cdot}&-2\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\cdot10^{-200}\\\\\n-1\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}&0\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}\\\\\n\\end{array}\\right)\n\\]', + + 'g2_p3_s' : '\\[\n\\begin{array}{ll}\nD = \\left(\\begin{array}{rllrll}\n1.&\\hspace{-1em}23&\\hspace{-1em}\\phantom{\\cdot}&-2\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\cdot10^{-200}\\\\\n-1\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}&0\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}\\\\\n\\end{array}\\right)\n\\end{array}\n\\]', + + 'g2_p5_s' : '\\[\n\\begin{array}{ll}\nD = \\left(\\begin{array}{rllrll}\n1.&\\hspace{-1em}2345&\\hspace{-1em}\\phantom{\\cdot}&-2\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\cdot10^{-200}\\\\\n-1\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}&0\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}\\\\\n\\end{array}\\right)\n\\end{array}\n\\]', +} + ***@***.***( + "g, repr_type, num_format, refkey", + [ + (LTX_G1, None, None, 'g1_p3_p'), + (LTX_G1, "partitioned", ".3g", 'g1_p3_p'), + (LTX_G1, "partitioned", ".5g", 'g1_p5_p'), + (LTX_G1, "separate", ".3g", 'g1_p3_s'), + (LTX_G1, "separate", ".5g", 'g1_p5_s'), + (LTX_G2, "partitioned", ".3g", 'g2_p3_p'), + (LTX_G2, "partitioned", ".5g", 'g2_p5_p'), + (LTX_G2, "separate" , ".3g", 'g2_p3_s'), + (LTX_G2, "separate" , ".5g", 'g2_p5_s'), + ]) +def test_latex_repr(g, repr_type, num_format, refkey): + # Test '_latex_repr_' with different config values + # This is a 'gold image' test, so if you change behaviour, + # you'll need to regenerate the reference results. + # Try something like: + # control.reset_defaults() + # print(f'g1_p3_p : {g1._repr_latex_()!r}') + from control import set_defaults, reset_defaults + try: + # add "editsdefaults" fixture and remove the reset_defaults as soon as#438 is merged + reset_defaults() + if num_format is not None: + set_defaults('statesp', latex_num_format=num_format) + + if repr_type is not None: + set_defaults('statesp', latex_repr_type=repr_type) + + assert g._repr_latex_() == LTX_REF[refkey] + finally: + reset_defaults() + pass Hi, I hope you don't mind that I have yet another change suggestion for your test code. My linter is screaming a little, so I tried to tone it down: ⬇️ Suggested change -# test data for test_latex_repr, below -LTX_G1 = StateSpace([[np.pi, 1e100],[-1.23456789, 5e-23]], - [[0], [1]], - [[987654321, 0.001234]], - [[5]]) - - -LTX_G2 = StateSpace([], - [], - [], - [[1.2345,-2e-200],[-1,0]]) - - -LTX_REF = { - 'g1_p3_p' : '\\[\n\\left(\n\\begin{array}{rllrll|rll}\n3.&\\hspace{-1em}14&\\hspace{-1em}\\phantom{\\cdot}&1\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\cdot10^{100}&0\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}\\\\\n-1.&\\hspace{-1em}23&\\hspace{-1em}\\phantom{\\cdot}&5\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\cdot10^{-23}&1\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}\\\\\n\\hline\n9.&\\hspace{-1em}88&\\hspace{-1em}\\cdot10^{8}&0.&\\hspace{-1em}00123&\\hspace{-1em}\\phantom{\\cdot}&5\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}\\\\\n\\end{array}\\right)\n\\]', - - 'g1_p5_p' : '\\[\n\\left(\n\\begin{array}{rllrll|rll}\n3.&\\hspace{-1em}1416&\\hspace{-1em}\\phantom{\\cdot}&1\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\cdot10^{100}&0\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}\\\\\n-1.&\\hspace{-1em}2346&\\hspace{-1em}\\phantom{\\cdot}&5\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\cdot10^{-23}&1\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}\\\\\n\\hline\n9.&\\hspace{-1em}8765&\\hspace{-1em}\\cdot10^{8}&0.&\\hspace{-1em}001234&\\hspace{-1em}\\phantom{\\cdot}&5\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}\\\\\n\\end{array}\\right)\n\\]', - - 'g1_p3_s' : '\\[\n\\begin{array}{ll}\nA = \\left(\\begin{array}{rllrll}\n3.&\\hspace{-1em}14&\\hspace{-1em}\\phantom{\\cdot}&1\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\cdot10^{100}\\\\\n-1.&\\hspace{-1em}23&\\hspace{-1em}\\phantom{\\cdot}&5\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\cdot10^{-23}\\\\\n\\end{array}\\right)\n&\nB = \\left(\\begin{array}{rll}\n0\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}\\\\\n1\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}\\\\\n\\end{array}\\right)\n\\\\\nC = \\left(\\begin{array}{rllrll}\n9.&\\hspace{-1em}88&\\hspace{-1em}\\cdot10^{8}&0.&\\hspace{-1em}00123&\\hspace{-1em}\\phantom{\\cdot}\\\\\n\\end{array}\\right)\n&\nD = \\left(\\begin{array}{rll}\n5\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}\\\\\n\\end{array}\\right)\n\\end{array}\n\\]', - - 'g1_p5_s' : '\\[\n\\begin{array}{ll}\nA = \\left(\\begin{array}{rllrll}\n3.&\\hspace{-1em}1416&\\hspace{-1em}\\phantom{\\cdot}&1\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\cdot10^{100}\\\\\n-1.&\\hspace{-1em}2346&\\hspace{-1em}\\phantom{\\cdot}&5\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\cdot10^{-23}\\\\\n\\end{array}\\right)\n&\nB = \\left(\\begin{array}{rll}\n0\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}\\\\\n1\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}\\\\\n\\end{array}\\right)\n\\\\\nC = \\left(\\begin{array}{rllrll}\n9.&\\hspace{-1em}8765&\\hspace{-1em}\\cdot10^{8}&0.&\\hspace{-1em}001234&\\hspace{-1em}\\phantom{\\cdot}\\\\\n\\end{array}\\right)\n&\nD = \\left(\\begin{array}{rll}\n5\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}\\\\\n\\end{array}\\right)\n\\end{array}\n\\]', - - 'g2_p3_p' : '\\[\n\\left(\n\\begin{array}{rllrll}\n1.&\\hspace{-1em}23&\\hspace{-1em}\\phantom{\\cdot}&-2\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\cdot10^{-200}\\\\\n-1\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}&0\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}\\\\\n\\end{array}\\right)\n\\]', - - 'g2_p5_p' : '\\[\n\\left(\n\\begin{array}{rllrll}\n1.&\\hspace{-1em}2345&\\hspace{-1em}\\phantom{\\cdot}&-2\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\cdot10^{-200}\\\\\n-1\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}&0\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}\\\\\n\\end{array}\\right)\n\\]', - - 'g2_p3_s' : '\\[\n\\begin{array}{ll}\nD = \\left(\\begin{array}{rllrll}\n1.&\\hspace{-1em}23&\\hspace{-1em}\\phantom{\\cdot}&-2\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\cdot10^{-200}\\\\\n-1\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}&0\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}\\\\\n\\end{array}\\right)\n\\end{array}\n\\]', - - 'g2_p5_s' : '\\[\n\\begin{array}{ll}\nD = \\left(\\begin{array}{rllrll}\n1.&\\hspace{-1em}2345&\\hspace{-1em}\\phantom{\\cdot}&-2\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\cdot10^{-200}\\\\\n-1\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}&0\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}\\\\\n\\end{array}\\right)\n\\end{array}\n\\]', -} - ***@***.***( - "g, repr_type, num_format, refkey", - [ - (LTX_G1, None, None, 'g1_p3_p'), - (LTX_G1, "partitioned", ".3g", 'g1_p3_p'), - (LTX_G1, "partitioned", ".5g", 'g1_p5_p'), - (LTX_G1, "separate", ".3g", 'g1_p3_s'), - (LTX_G1, "separate", ".5g", 'g1_p5_s'), - (LTX_G2, "partitioned", ".3g", 'g2_p3_p'), - (LTX_G2, "partitioned", ".5g", 'g2_p5_p'), - (LTX_G2, "separate" , ".3g", 'g2_p3_s'), - (LTX_G2, "separate" , ".5g", 'g2_p5_s'), - ]) -def test_latex_repr(g, repr_type, num_format, refkey): - # Test '_latex_repr_' with different config values - # This is a 'gold image' test, so if you change behaviour, - # you'll need to regenerate the reference results. - # Try something like: - # control.reset_defaults() - # print(f'g1_p3_p : {g1._repr_latex_()!r}') - from control import set_defaults, reset_defaults - try: - # add "editsdefaults" fixture and remove the reset_defaults as soon as#438 is merged - reset_defaults() - if num_format is not None: - set_defaults('statesp', latex_num_format=num_format) - - if repr_type is not None: - set_defaults('statesp', latex_repr_type=repr_type) - - assert g._repr_latex_() == LTX_REF[refkey] - finally: - reset_defaults() - pass + +# test data for test_latex_repr below +LTX_G1 = StateSpace([[np.pi, 1e100], [-1.23456789, 5e-23]], + [[0], [1]], + [[987654321, 0.001234]], + [[5]]) + +LTX_G2 = StateSpace([], + [], + [], + [[1.2345, -2e-200], [-1, 0]]) + +LTX_G1_REF = { + 'p3_p' : '\\[\n\\left(\n\\begin{array}{rllrll|rll}\n3.&\\hspace{-1em}14&\\hspace{-1em}\\phantom{\\cdot}&1\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\cdot10^{100}&0\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}\\\\\n-1.&\\hspace{-1em}23&\\hspace{-1em}\\phantom{\\cdot}&5\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\cdot10^{-23}&1\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}\\\\\n\\hline\n9.&\\hspace{-1em}88&\\hspace{-1em}\\cdot10^{8}&0.&\\hspace{-1em}00123&\\hspace{-1em}\\phantom{\\cdot}&5\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}\\\\\n\\end{array}\\right)\n\\]', + + 'p5_p' : '\\[\n\\left(\n\\begin{array}{rllrll|rll}\n3.&\\hspace{-1em}1416&\\hspace{-1em}\\phantom{\\cdot}&1\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\cdot10^{100}&0\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}\\\\\n-1.&\\hspace{-1em}2346&\\hspace{-1em}\\phantom{\\cdot}&5\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\cdot10^{-23}&1\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}\\\\\n\\hline\n9.&\\hspace{-1em}8765&\\hspace{-1em}\\cdot10^{8}&0.&\\hspace{-1em}001234&\\hspace{-1em}\\phantom{\\cdot}&5\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}\\\\\n\\end{array}\\right)\n\\]', + + 'p3_s' : '\\[\n\\begin{array}{ll}\nA = \\left(\\begin{array}{rllrll}\n3.&\\hspace{-1em}14&\\hspace{-1em}\\phantom{\\cdot}&1\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\cdot10^{100}\\\\\n-1.&\\hspace{-1em}23&\\hspace{-1em}\\phantom{\\cdot}&5\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\cdot10^{-23}\\\\\n\\end{array}\\right)\n&\nB = \\left(\\begin{array}{rll}\n0\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}\\\\\n1\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}\\\\\n\\end{array}\\right)\n\\\\\nC = \\left(\\begin{array}{rllrll}\n9.&\\hspace{-1em}88&\\hspace{-1em}\\cdot10^{8}&0.&\\hspace{-1em}00123&\\hspace{-1em}\\phantom{\\cdot}\\\\\n\\end{array}\\right)\n&\nD = \\left(\\begin{array}{rll}\n5\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}\\\\\n\\end{array}\\right)\n\\end{array}\n\\]', + + 'p5_s' : '\\[\n\\begin{array}{ll}\nA = \\left(\\begin{array}{rllrll}\n3.&\\hspace{-1em}1416&\\hspace{-1em}\\phantom{\\cdot}&1\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\cdot10^{100}\\\\\n-1.&\\hspace{-1em}2346&\\hspace{-1em}\\phantom{\\cdot}&5\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\cdot10^{-23}\\\\\n\\end{array}\\right)\n&\nB = \\left(\\begin{array}{rll}\n0\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}\\\\\n1\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}\\\\\n\\end{array}\\right)\n\\\\\nC = \\left(\\begin{array}{rllrll}\n9.&\\hspace{-1em}8765&\\hspace{-1em}\\cdot10^{8}&0.&\\hspace{-1em}001234&\\hspace{-1em}\\phantom{\\cdot}\\\\\n\\end{array}\\right)\n&\nD = \\left(\\begin{array}{rll}\n5\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}\\\\\n\\end{array}\\right)\n\\end{array}\n\\]', +} + +LTX_G2_REF = { + 'p3_p' : '\\[\n\\left(\n\\begin{array}{rllrll}\n1.&\\hspace{-1em}23&\\hspace{-1em}\\phantom{\\cdot}&-2\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\cdot10^{-200}\\\\\n-1\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}&0\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}\\\\\n\\end{array}\\right)\n\\]', + + 'p5_p' : '\\[\n\\left(\n\\begin{array}{rllrll}\n1.&\\hspace{-1em}2345&\\hspace{-1em}\\phantom{\\cdot}&-2\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\cdot10^{-200}\\\\\n-1\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}&0\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}\\\\\n\\end{array}\\right)\n\\]', + + 'p3_s' : '\\[\n\\begin{array}{ll}\nD = \\left(\\begin{array}{rllrll}\n1.&\\hspace{-1em}23&\\hspace{-1em}\\phantom{\\cdot}&-2\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\cdot10^{-200}\\\\\n-1\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}&0\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}\\\\\n\\end{array}\\right)\n\\end{array}\n\\]', + + 'p5_s' : '\\[\n\\begin{array}{ll}\nD = \\left(\\begin{array}{rllrll}\n1.&\\hspace{-1em}2345&\\hspace{-1em}\\phantom{\\cdot}&-2\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\cdot10^{-200}\\\\\n-1\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}&0\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}\\\\\n\\end{array}\\right)\n\\end{array}\n\\]', +} + +refkey_n = {None: 'p3', '.3g': 'p3', '.5g': 'p5'} +refkey_r = {None: 'p', 'partitioned': 'p', 'separate': 's'} + + ***@***.***(" g, ref", + [(LTX_G1, LTX_G1_REF), + (LTX_G2, LTX_G2_REF)]) ***@***.***("repr_type", [None, "partitioned", "separate"]) ***@***.***("num_format", [None, ".3g", ".5g"]) +def test_latex_repr(g, ref, repr_type, num_format): + """Test `._latex_repr_` with different config values + + This is a 'gold image' test, so if you change behaviour, + you'll need to regenerate the reference results. + Try something like: + control.reset_defaults() + print(f'p3_p : {g1._repr_latex_()!r}') + """ + from control import set_defaults, reset_defaults + try: + # add "editsdefaults" fixture and remove the reset_defaults as soon as + #gh-438 is merged + reset_defaults() + if num_format is not None: + set_defaults('statesp', latex_num_format=num_format) + + if repr_type is not None: + set_defaults('statesp', latex_repr_type=repr_type) + + refkey = "{}_{}".format(refkey_n[num_format], refkey_r[repr_type]) + assert g._repr_latex_() == ref[refkey] + finally: + reset_defaults() Of course the very long reference lines will always produce a warning, even if we would introduce line breaks at the \n, but that is okay in my mind. — You are receiving this because you authored the thread. Reply to this email directly, view it on GitHub <#450 (review)>, or unsubscribe <https://github.com/notifications/unsubscribe-auth/AAA3C7Q5DUQ3Y5ZNLAHRYQTSBF7FXANCNFSM4QAEZJXA> .

@bnavigator
Copy link
Contributor

bnavigator commentedAug 19, 2020
edited
Loading

psf/black#1132 won't help here. The reference strings do not contain enough whitespace to wrap before the line length limit.

There is always pprint, but even the results from that are too long:

>>>from pprintimport pprint>>>import numpyas np>>>from controlimport StateSpace>>>LTX_G1= StateSpace([[np.pi,1e100],...                      [-1.23456789,5e-23]],...                     [[0], [1]],...                     [[987654321,0.001234]],...                     [[5]])>>> pprint(LTX_G1._repr_latex_())('\\[\n' '\\left(\n' '\\begin{array}{rllrll|rll}\n' '3.&\\hspace{-1em}14&\\hspace{-1em}\\phantom{\\cdot}&1\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\cdot10^{100}&0\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}\\\\\n' '-1.&\\hspace{-1em}23&\\hspace{-1em}\\phantom{\\cdot}&5\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\cdot10^{-23}&1\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}\\\\\n' '\\hline\n' '9.&\\hspace{-1em}88&\\hspace{-1em}\\cdot10^{8}&0.&\\hspace{-1em}00123&\\hspace{-1em}\\phantom{\\cdot}&5\\phantom{.}&\\hspace{-1em}&\\hspace{-1em}\\phantom{\\cdot}\\\\\n' '\\end{array}\\right)\n' '\\]')

Here is a manual implementation with breaking at the column separators and using rstrings. But is it really worth the complexity?

>>>print("(r'{}')".format("''\\n'\n r'".join(["&'\n r'".join(l.split("&"))...for linLTX_G1._repr_latex_()...                                                           .splitlines()])))(r'\[''\n' r'\left(''\n' r'\begin{array}{rllrll|rll}''\n' r'3.&' r'\hspace{-1em}14&' r'\hspace{-1em}\phantom{\cdot}&' r'1\phantom{.}&' r'\hspace{-1em}&' r'\hspace{-1em}\cdot10^{100}&' r'0\phantom{.}&' r'\hspace{-1em}&' r'\hspace{-1em}\phantom{\cdot}\\''\n' r'-1.&' r'\hspace{-1em}23&' r'\hspace{-1em}\phantom{\cdot}&' r'5\phantom{.}&' r'\hspace{-1em}&' r'\hspace{-1em}\cdot10^{-23}&' r'1\phantom{.}&' r'\hspace{-1em}&' r'\hspace{-1em}\phantom{\cdot}\\''\n' r'\hline''\n' r'9.&' r'\hspace{-1em}88&' r'\hspace{-1em}\cdot10^{8}&' r'0.&' r'\hspace{-1em}00123&' r'\hspace{-1em}\phantom{\cdot}&' r'5\phantom{.}&' r'\hspace{-1em}&' r'\hspace{-1em}\phantom{\cdot}\\''\n' r'\end{array}\right)''\n' r'\]')

You could also avoid the manual break at '&' and put some strategically placed spaces into_repr_latex_ itself.

@roryyorke
Copy link
ContributorAuthor

The results look fine in QtConsole (tested v4.7.6 from conda-forge).

Comment on lines 719 to 742
def test_latex_repr(g, ref, repr_type, num_format):
"""Test `._latex_repr_` with different config values

This is a 'gold image' test, so if you change behaviour,
you'll need to regenerate the reference results.
Try something like:
control.reset_defaults()
print(f'p3_p : {g1._repr_latex_()!r}')
"""
from control import set_defaults, reset_defaults
try:
# add "editsdefaults" fixture and remove the reset_defaults as soon as
# gh-438 is merged
reset_defaults()
if num_format is not None:
set_defaults('statesp', latex_num_format=num_format)

if repr_type is not None:
set_defaults('statesp', latex_repr_type=repr_type)

refkey = "{}_{}".format(refkey_n[num_format], refkey_r[repr_type])
assert g._repr_latex_() == ref[refkey]
finally:
reset_defaults()
Copy link
Contributor

@bnavigatorbnavigatorAug 21, 2020
edited
Loading

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

With#456 introducing the editsdefaults fixture, you can now use it directly:

Suggested change
deftest_latex_repr(g,ref,repr_type,num_format):
"""Test`._latex_repr_`withdifferentconfigvalues
Thisisa'gold image'test,soifyouchangebehaviour,
you'llneedtoregeneratethereferenceresults.
Trysomethinglike:
control.reset_defaults()
print(f'p3_p :{g1._repr_latex_()!r}')
"""
fromcontrolimportset_defaults,reset_defaults
try:
# add "editsdefaults" fixture and remove the reset_defaults as soon as
# gh-438 is merged
reset_defaults()
ifnum_formatisnotNone:
set_defaults('statesp',latex_num_format=num_format)
ifrepr_typeisnotNone:
set_defaults('statesp',latex_repr_type=repr_type)
refkey="{}_{}".format(refkey_n[num_format],refkey_r[repr_type])
assertg._repr_latex_()==ref[refkey]
finally:
reset_defaults()
deftest_latex_repr(g,ref,repr_type,num_format,editsdefaults):
"""Test`._latex_repr_`withdifferentconfigvalues
Thisisa'gold image'test,soifyouchangebehaviour,
you'llneedtoregeneratethereferenceresults.
Trysomethinglike:
control.reset_defaults()
print(f'p3_p :{g1._repr_latex_()!r}')
"""
fromcontrolimportset_defaults
ifnum_formatisnotNone:
set_defaults('statesp',latex_num_format=num_format)
ifrepr_typeisnotNone:
set_defaults('statesp',latex_repr_type=repr_type)
refkey="{}_{}".format(refkey_n[num_format],refkey_r[repr_type])
assertg._repr_latex_()==ref[refkey]

Copy link
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Thanks, that is tidier. Have merged from master and changed to use the new fixture.

@murrayrm
Copy link
Member

@roryyorke When you get a chance, can you rebase this against the current master.

Added StateSpace method `_repr_latex_`, which returns aMathJax-centric LaTeX representation of the instance.Added two `statesp` configuration options for this representation.One affects number formatting, and the other chooses the output type.
@roryyorke
Copy link
ContributorAuthor

Hm, this is not quite right: I've restored a file that was removed. Will try again...

@roryyorke
Copy link
ContributorAuthor

No, I take that back. I thoughtcontrol/tests/statesp_test.py had been removed, and that I had re-added it, but I see it was still there. I think a test has gone missing (test_sample_system_prewarping), experimenting withgit bisect to find where it went missing.

@roryyorke
Copy link
ContributorAuthor

OK, I see inc432fd5 the two prewarp tests for xferfcn and ss were merged into one parameterized test.

Sorry for all the noise. I think this PR is rebased and ready.

@murrayrmmurrayrm merged commit6ed3f74 intopython-control:masterDec 31, 2020
Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment
Reviewers

@bnavigatorbnavigatorbnavigator approved these changes

Assignees
No one assigned
Labels
None yet
Projects
None yet
Milestone
0.9.0
Development

Successfully merging this pull request may close these issues.

4 participants
@roryyorke@coveralls@bnavigator@murrayrm

[8]ページ先頭

©2009-2025 Movatter.jp