-
Notifications
You must be signed in to change notification settings - Fork 438
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 our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
control/tests/statesp_test.py
Outdated
[], | ||
[[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\\]' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe reformat as r''
strings for better readability?
There was a problem hiding this comment.
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 coax repr
(or whatever) to spit out raw strings?
control/tests/statesp_test.py
Outdated
@@ -561,6 +561,69 @@ def test_str(self): | |||
assert str(sysdt1) == tref + "\ndt = 1.0\n" | |||
|
|||
|
|||
def test_latex_repr(self): |
There was a problem hiding this comment.
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)])
def test_latex_repr(self, g, repr_latex, p3ref, p5ref):
try:
# add "editsdefaults" fixture and remove the reset_defaults as soon as #438 is merged
reset_defaults()
if repr_latex is not None:
set_defaults('statesp', latex_repr_type=repr_latex)
assert g1._repr_latex_() == p3ref
set_defaults('statesp', latex_num_format='.5g')
assert g1._repr_latex_() == p5ref
finally:
reset_defaults()
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Except for the editsdefaults
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
Github also renders ipynb. You could add a demonstrating example to the docs. |
AFAIK Github doesn't render the LaTeX; the notebook is actually a gist at https://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! |
I wonder what's different in sympy: The output fields have latex, png and text
|
It looks like sympy's I'm not up to implementing this; if we do want it, I think we should see if we can use Sympy to achieve it.
|
Not within the scope of this PR, I guess. I was just curious. |
It looks like black recently merged a feature to wrap strings like this:
bbugyi200:182-wrap-long-strings (black PR 1132 - previous is some Github
generated name?). I'll try it this weekend.
It also occurred to me that I don't know if QtConsole for IPython uses
something else for LaTeX rendering, or does such rendering at all. If that
is 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>
.
|
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 pprint import pprint
>>> import numpy as np
>>> from control import 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 l in LTX_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 |
The results look fine in QtConsole (tested v4.7.6 from conda-forge). |
control/tests/statesp_test.py
Outdated
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() |
There was a problem hiding this comment.
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:
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() | |
def test_latex_repr(g, ref, repr_type, num_format, editsdefaults): | |
"""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 | |
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] |
There was a problem hiding this comment.
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.
@roryyorke When you get a chance, can you rebase this against the current master. |
Added StateSpace method `_repr_latex_`, which returns a MathJax-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.
e1bd131
to
91b04de
Compare
Hm, this is not quite right: I've restored a file that was removed. Will try again... |
No, I take that back. I thought |
OK, I see in c432fd5 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. |
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.
Partially addesses #278; see much discussion there on this.
Example at https://nbviewer.jupyter.org/gist/roryyorke/6879e0b20735f533410dad883eb687e5.