-
Notifications
You must be signed in to change notification settings - Fork 438
Feature print zpk #869
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
Feature print zpk #869
Conversation
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.
This would be a very nice feature. I am not sure there are any plans to have a new object class that stores things in zpk form directly, so having convenient methods like this to access that data seems to me like the way to go.
A few suggestions/thoughts:
- might be simpler and more compact on lines 497ish to 523ish to use scipy’s tf2zpk. And maybe more robust? Unless your code does it better than how scipy does it.
- consider refactoring to have this use an intermediate method called something like
zpkdata
that serves as a direct way to access zpk numerical values. - In the nice-to-have category would be automatic latex representation when you are in a Jupyter notebook, like how tf and ss systems do it.
@sawyerbfuller Thanks for the review! The nice-to-have latex would be difficult, since Jupyter eventually calls Maybe a specific subclass for ZPK, but that would be an invasive change. Let me mull it over. Otherwise it will have to stay nice-to-have ;-) I'll have a look to see what's possible/convenient for the other suggestions/thoughts. |
@henklaak one possibility that might not break anything might be to add a field to TransferFunction, maybe ‘representation’?, that could be set to either ‘poly’ or ‘zpk’ in init. Might be automatically set to ‘zpk’ if instantiated with |
Thanks for the invaluable comments. The PR has become so much better now. |
control/xferfcn.py
Outdated
@@ -463,8 +483,7 @@ def __str__(self, var=None): | |||
|
|||
# See if this is a discrete time system with specific sampling time |
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.
# See if this is a discrete time system with specific sampling time | |
# print value of dt only if this is a discrete-time system with dt not 'True' (unspecified samplign time) |
@@ -92,6 +92,9 @@ class TransferFunction(LTI): | |||
time, positive number is discrete time with specified |
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.
I can't suggest changes above this line so I am suggsting them here:
_xferfcn_defaults = {
'xferfcn.display_format': 'poly',
}
control/xferfcn.py
Outdated
@@ -198,6 +201,14 @@ def __init__(self, *args, **kwargs): | |||
# | |||
# Process keyword arguments | |||
# | |||
if display_format is None: |
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.
if display_format is None: | |
self.display_format = kwargs.pop('display_format', | |
config.defaults['xferfcn.display_format']) |
control/xferfcn.py
Outdated
@@ -198,6 +201,14 @@ def __init__(self, *args, **kwargs): | |||
# | |||
# Process keyword arguments | |||
# | |||
if display_format is None: | |||
display_format = 'poly' |
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.
display_format = 'poly' |
control/xferfcn.py
Outdated
if display_format is None: | ||
display_format = 'poly' | ||
|
||
if display_format not in ('poly', 'zpk'): |
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.
if display_format not in ('poly', 'zpk'): | |
if self.display_format not in ('poly', 'zpk'): |
control/xferfcn.py
Outdated
|
||
if display_format not in ('poly', 'zpk'): | ||
raise ValueError("display_format must be 'poly' or 'zpk'," | ||
" got '%s'" % display_format) |
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.
" got '%s'" % display_format) | |
" got '%s'" % self.display_format) |
control/xferfcn.py
Outdated
raise ValueError("display_format must be 'poly' or 'zpk'," | ||
" got '%s'" % display_format) | ||
|
||
self.display_format = display_format |
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.
self.display_format = display_format |
control/xferfcn.py
Outdated
@@ -149,7 +152,7 @@ class TransferFunction(LTI): | |||
# Give TransferFunction._rmul_() priority for ndarray * TransferFunction | |||
__array_priority__ = 11 # override ndarray and matrix types | |||
|
|||
def __init__(self, *args, **kwargs): | |||
def __init__(self, *args, display_format=None, **kwargs): |
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.
def __init__(self, *args, display_format=None, **kwargs): | |
def __init__(self, *args, **kwargs): |
control/xferfcn.py
Outdated
@@ -92,6 +92,9 @@ class TransferFunction(LTI): | |||
time, positive number is discrete time with specified | |||
sampling time, None indicates unspecified timebase (either | |||
continuous or discrete time). | |||
display_format: None, 'poly' or 'zpk' | |||
Set the display format used in printing the TransferFunction object. | |||
Default behavior is polynomial display. |
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.
Default behavior is polynomial display. | |
Default behavior is polynomial display and can be changed by | |
changing config.defaults['xferfcn.display_format']. |
control/xferfcn.py
Outdated
@@ -1486,6 +1552,9 @@ def tf(*args, **kwargs): | |||
Polynomial coefficients of the numerator | |||
den: array_like, or list of list of array_like | |||
Polynomial coefficients of the denominator | |||
display_format: None, 'poly' or 'zpk' | |||
Set the display format used in printing the TransferFunction object. | |||
Default behavior is polynomial display. |
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.
Default behavior is polynomial display. | |
Default behavior is polynomial display and can be changed by | |
changing config.defaults['xferfcn.display_format']. |
I think we have solved this quite nicely. -edit- On the other hand, now we have defaults, we could also make the floating point format (currently '%.4g') a configurable default. -edit- Couldn't resist. Added it. |
In statesp the number format option is |
|
I considered that, but the screen space requirements that lead to the format specifiers are rather unrelated. There are actually a lot of places where one would like to customize the precision, e.g. also in plots. |
'xferfcn.floating_point_format': '.4g' | ||
} | ||
|
||
def _float2str(value): |
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.
I would suggest against doing this. It's anti-pattern for Python and also there is a simpler way to grab the default at the code level and reuse.
>>> _num_format = config.defaults.get('xferfcn.floating_point_format', ':.4g')
>>> print(f"Bla {0.232654684684654654:{_num_format}}")
Bla 0.232655
So you don't need to inject f-string machinery to the string representation.
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.
@henklaak If you can fix up this final issue, I think this PR is ready to post.
@henklaak re display format for text vs latex: makes sense I agree they have different requirements, if I understand what you’re saying. In that case we should have setttings for both latex and text. Should they then have otherwise consistent names with only “latex” vs “print” identifiers that distinguish? That would suggest making this one if you think it should have a different name then hapoy to leave that discussion to a different PR. Otherwise this looks good to me |
Down with the flu. Will continue end of the week. |
Thanks @murrayrm for taking this one. |
Fixes #64
Produces: