
    \h                        S SK JrJr  S SKJrJr  S SKJr  S SKJ	r	  S SK
Jr  S SKJrJr  S SKJr  S SKJr  S S	KJr  S S
KJr  S SKJrJr  S SKJr  S SKJr  S SKJr  / SQr \" SSS/0\!4S9r"\"(       a  \"RF                  r$S r%S r&S r'   S(S jr(  S)S jr)  S*S jr*  S)S jr+  S*S jr,  S+S jr-  S,S jr.S-S jr/  S.S jr0S/S  jr1  S0S! jr2  S1S" jr3S# r4S$ r5  S2S% jr6S2S& jr7g')3    )Ipi)explog)apart)Dummy)import_module)argAbs)_fast_inverse_laplace)SISOLinearTimeInvariant)LineOver1DRangeSeries)plot_parametric)ZZQQ)Poly)latex)deg)pole_zero_numerical_datapole_zero_plotstep_response_numerical_datastep_response_plotimpulse_response_numerical_dataimpulse_response_plotramp_response_numerical_dataramp_response_plotbode_magnitude_numerical_databode_phase_numerical_databode_magnitude_plotbode_phase_plot	bode_plotnyquist_plot_exprnyquist_plotnichols_plot_exprnichols_plot
matplotlibfromlistpyplot)import_kwargscatchc                     [        U [        5      (       d  [        S5      eU R                  5       n[	        UR
                  5      nUS:  a  [        S5      eUR                  [        5      (       a  [        S5      eg)zUFunction to check whether the dynamical system passed for plots is
compatible or not.z.Only SISO LTI systems are currently supported.   zExtra degree of freedom found. Make sure that there are no free symbols in the dynamical system other than the variable of Laplace transform.z#Time delay terms are not supported.N)	
isinstancer   NotImplementedErrorto_exprlenfree_symbols
ValueErrorhasr   )systemsyslen_free_symbolss      [/var/www/auris/envauris/lib/python3.13/site-packages/sympy/physics/control/control_plots.py_check_systemr8   "   sw     f566!"RSS
..
C3++,! 7 8 	8 wws|| ""GHH     c                     S nU R                   [        [        4;   a  U" U R                  5       5      $ U" U R	                  5       5      $ )z*Function to get the roots of a polynomial.c                 z    U  Vs/ s H)  oR                   (       a  [        U5      O
[        U5      PM+     sn$ s  snf )N)is_realfloatcomplex)lis     r7   _eval_poly_roots.<locals>._eval5   s+    ?@Aq!IIa71:5qAAAs   08)domainr   r   	all_rootsnroots)polyrA   s     r7   _poly_rootsrG   3   s=    B{{r2hT^^%&& r9   c                     [        U 5        U R                  5       n [        U R                  U R                  5      n[        U R
                  U R                  5      n[        U5      [        U5      4$ )a  
Returns the numerical data of poles and zeros of the system.
It is internally used by ``pole_zero_plot`` to get the data
for plotting poles and zeros. Users can use this data to further
analyse the dynamics of the system or plot using a different
backend/plotting-module.

Parameters
==========

system : SISOLinearTimeInvariant
    The system for which the pole-zero data is to be computed.

Returns
=======

tuple : (zeros, poles)
    zeros = Zeros of the system as a list of Python float/complex.
    poles = Poles of the system as a list of Python float/complex.

Raises
======

NotImplementedError
    When a SISO LTI system is not passed.

    When time delay terms are present in the system.

ValueError
    When more than one free symbol is present in the system.
    The only variable in the transfer function should be
    the variable of the Laplace transform.

Examples
========

>>> from sympy.abc import s
>>> from sympy.physics.control.lti import TransferFunction
>>> from sympy.physics.control.control_plots import pole_zero_numerical_data
>>> tf1 = TransferFunction(s**2 + 1, s**4 + 4*s**3 + 6*s**2 + 5*s + 2, s)
>>> pole_zero_numerical_data(tf1)
([-1j, 1j], [-2.0, -1.0, (-0.5-0.8660254037844386j), (-0.5+0.8660254037844386j)])

See Also
========

pole_zero_plot

)r8   doitr   numvardenrG   )r4   num_polyden_polys      r7   r   r   >   sU    d &[[]FFJJ

+HFJJ

+Hx +h"777r9   c           	         [        U 5      u  pU	 Vs/ s H  oR                  PM     nnU	 Vs/ s H  oR                  PM     nnU
 Vs/ s H  oR                  PM     nnU
 Vs/ s H  oR                  PM     nn[        R	                  XSSX!S9  [        R	                  XSUUS9  [        R                  S5        [        R                  S5        [        R                  S[        U 5       S	3S
S9  U(       a  [        R                  5         U(       a(  [        R                  SSS9  [        R                  SSS9  U(       a  [        R                  5         g[        $ s  snf s  snf s  snf s  snf )a  
Returns the Pole-Zero plot (also known as PZ Plot or PZ Map) of a system.

A Pole-Zero plot is a graphical representation of a system's poles and
zeros. It is plotted on a complex plane, with circular markers representing
the system's zeros and 'x' shaped markers representing the system's poles.

Parameters
==========

system : SISOLinearTimeInvariant type systems
    The system for which the pole-zero plot is to be computed.
pole_color : str, tuple, optional
    The color of the pole points on the plot. Default color
    is blue. The color can be provided as a matplotlib color string,
    or a 3-tuple of floats each in the 0-1 range.
pole_markersize : Number, optional
    The size of the markers used to mark the poles in the plot.
    Default pole markersize is 10.
zero_color : str, tuple, optional
    The color of the zero points on the plot. Default color
    is orange. The color can be provided as a matplotlib color string,
    or a 3-tuple of floats each in the 0-1 range.
zero_markersize : Number, optional
    The size of the markers used to mark the zeros in the plot.
    Default zero markersize is 7.
grid : boolean, optional
    If ``True``, the plot will have a grid. Defaults to True.
show_axes : boolean, optional
    If ``True``, the coordinate axes will be shown. Defaults to False.
show : boolean, optional
    If ``True``, the plot will be displayed otherwise
    the equivalent matplotlib ``plot`` object will be returned.
    Defaults to True.

Examples
========

.. plot::
    :context: close-figs
    :format: doctest
    :include-source: True

    >>> from sympy.abc import s
    >>> from sympy.physics.control.lti import TransferFunction
    >>> from sympy.physics.control.control_plots import pole_zero_plot
    >>> tf1 = TransferFunction(s**2 + 1, s**4 + 4*s**3 + 6*s**2 + 5*s + 2, s)
    >>> pole_zero_plot(tf1)   # doctest: +SKIP

See Also
========

pole_zero_numerical_data

References
==========

.. [1] https://en.wikipedia.org/wiki/Pole%E2%80%93zero_plot

xnone)mfc
markersizecoloro)rS   rT   	Real AxisImaginary AxiszPoles and Zeros of $$   padr   blackrT   N)r   realimagpltplotxlabelylabeltitler   gridaxhlineaxvlineshow)r4   
pole_colorpole_markersize
zero_colorzero_markersizere   	show_axesrh   kwargszerospolesr@   	zero_real	zero_imag	pole_real	pole_imags                   r7   r   r   y   s%   ~ ,F3LE!&'AI'!&'AI'!&'AI'!&'AI'HHY3F"  6HHY3?  JJ{JJ II$U6]O152I>
AW%AW%
J/ ('''s   EE"E'#E,c                 4   US:  a  [        S5      e[        U 5        [        S5      nU R                  5       U R                  -  n[        X`R                  SS9n[        X`R                  U5      R                  U5      n[        XuX#440 UD6R                  5       $ )a  
Returns the numerical values of the points in the step response plot
of a SISO continuous-time system. By default, adaptive sampling
is used. If the user wants to instead get an uniformly
sampled response, then ``adaptive`` kwarg should be passed ``False``
and ``n`` must be passed as additional kwargs.
Refer to the parameters of class :class:`sympy.plotting.series.LineOver1DRangeSeries`
for more details.

Parameters
==========

system : SISOLinearTimeInvariant
    The system for which the unit step response data is to be computed.
prec : int, optional
    The decimal point precision for the point coordinate values.
    Defaults to 8.
lower_limit : Number, optional
    The lower limit of the plot range. Defaults to 0.
upper_limit : Number, optional
    The upper limit of the plot range. Defaults to 10.
kwargs :
    Additional keyword arguments are passed to the underlying
    :class:`sympy.plotting.series.LineOver1DRangeSeries` class.

Returns
=======

tuple : (x, y)
    x = Time-axis values of the points in the step response. NumPy array.
    y = Amplitude-axis values of the points in the step response. NumPy array.

Raises
======

NotImplementedError
    When a SISO LTI system is not passed.

    When time delay terms are present in the system.

ValueError
    When more than one free symbol is present in the system.
    The only variable in the transfer function should be
    the variable of the Laplace transform.

    When ``lower_limit`` parameter is less than 0.

Examples
========

>>> from sympy.abc import s
>>> from sympy.physics.control.lti import TransferFunction
>>> from sympy.physics.control.control_plots import step_response_numerical_data
>>> tf1 = TransferFunction(s, s**2 + 5*s + 8, s)
>>> step_response_numerical_data(tf1)   # doctest: +SKIP
([0.0, 0.025413462339411542, 0.0484508722725343, ... , 9.670250533855183, 9.844291913708725, 10.0],
[0.0, 0.023844582399907256, 0.042894276802320226, ..., 6.828770759094287e-12, 6.456457160755703e-12])

See Also
========

step_response_plot

r   :Lower limit of time must be greater than or equal to zero.rP   Tfull
r2   r8   r   r/   rK   r   r   evalfr   
get_pointsr4   preclower_limitupper_limitrn   _xexpr_ys           r7   r   r      s    D Q % & 	&&	sB>>VZZ(Dzz-D	tZZ	4	:	:4	@B +%C 
*,r9   c                    [        U 4UX4S.UD6u  p[        R                  XUS9  [        R                  S5        [        R	                  S5        [        R                  S[        U 5       S3SS9  U(       a  [        R                  5         U(       a(  [        R                  S	S
S9  [        R                  S	S
S9  U(       a  [        R                  5         g[        $ )a  
Returns the unit step response of a continuous-time system. It is
the response of the system when the input signal is a step function.

Parameters
==========

system : SISOLinearTimeInvariant type
    The LTI SISO system for which the Step Response is to be computed.
color : str, tuple, optional
    The color of the line. Default is Blue.
show : boolean, optional
    If ``True``, the plot will be displayed otherwise
    the equivalent matplotlib ``plot`` object will be returned.
    Defaults to True.
lower_limit : Number, optional
    The lower limit of the plot range. Defaults to 0.
upper_limit : Number, optional
    The upper limit of the plot range. Defaults to 10.
prec : int, optional
    The decimal point precision for the point coordinate values.
    Defaults to 8.
show_axes : boolean, optional
    If ``True``, the coordinate axes will be shown. Defaults to False.
grid : boolean, optional
    If ``True``, the plot will have a grid. Defaults to True.

Examples
========

.. plot::
    :context: close-figs
    :format: doctest
    :include-source: True

    >>> from sympy.abc import s
    >>> from sympy.physics.control.lti import TransferFunction
    >>> from sympy.physics.control.control_plots import step_response_plot
    >>> tf1 = TransferFunction(8*s**2 + 18*s + 32, s**3 + 6*s**2 + 14*s + 24, s)
    >>> step_response_plot(tf1)   # doctest: +SKIP

See Also
========

impulse_response_plot, ramp_response_plot

References
==========

.. [1] https://www.mathworks.com/help/control/ref/lti.step.html

r}   r~   r   r]   Time (s)	AmplitudezUnit Step Response of $rX   rY   rZ   r   r\   N)r   r`   ra   rb   rc   rd   r   re   rf   rg   rh   r4   rT   r}   r~   r   rm   re   rh   rn   rP   ys              r7   r   r   "  s    l ( DTD<BDDAHHQHJJzJJ{II'fa8bIA
AW%AW%
Jr9   c                    US:  a  [        S5      e[        U 5        [        S5      nU R                  5       n[	        X`R
                  SS9n[        X`R
                  U5      R                  U5      n[        XuX#440 UD6R                  5       $ )a  
Returns the numerical values of the points in the impulse response plot
of a SISO continuous-time system. By default, adaptive sampling
is used. If the user wants to instead get an uniformly
sampled response, then ``adaptive`` kwarg should be passed ``False``
and ``n`` must be passed as additional kwargs.
Refer to the parameters of class :class:`sympy.plotting.series.LineOver1DRangeSeries`
for more details.

Parameters
==========

system : SISOLinearTimeInvariant
    The system for which the impulse response data is to be computed.
prec : int, optional
    The decimal point precision for the point coordinate values.
    Defaults to 8.
lower_limit : Number, optional
    The lower limit of the plot range. Defaults to 0.
upper_limit : Number, optional
    The upper limit of the plot range. Defaults to 10.
kwargs :
    Additional keyword arguments are passed to the underlying
    :class:`sympy.plotting.series.LineOver1DRangeSeries` class.

Returns
=======

tuple : (x, y)
    x = Time-axis values of the points in the impulse response. NumPy array.
    y = Amplitude-axis values of the points in the impulse response. NumPy array.

Raises
======

NotImplementedError
    When a SISO LTI system is not passed.

    When time delay terms are present in the system.

ValueError
    When more than one free symbol is present in the system.
    The only variable in the transfer function should be
    the variable of the Laplace transform.

    When ``lower_limit`` parameter is less than 0.

Examples
========

>>> from sympy.abc import s
>>> from sympy.physics.control.lti import TransferFunction
>>> from sympy.physics.control.control_plots import impulse_response_numerical_data
>>> tf1 = TransferFunction(s, s**2 + 5*s + 8, s)
>>> impulse_response_numerical_data(tf1)   # doctest: +SKIP
([0.0, 0.06616480200395854,... , 9.854500743565858, 10.0],
[0.9999999799999999, 0.7042848373025861,...,7.170748906965121e-13, -5.1901263495547205e-12])

See Also
========

impulse_response_plot

r   rv   rP   Trw   )
r2   r8   r   r/   r   rK   r   rz   r   r{   r|   s           r7   r   r   k  s    D Q % & 	&&	sB>>Dzz-D	tZZ	4	:	:4	@B +%C 
*,r9   c                    [        U 4UX4S.UD6u  p[        R                  XUS9  [        R                  S5        [        R	                  S5        [        R                  S[        U 5       S3SS9  U(       a  [        R                  5         U(       a(  [        R                  S	S
S9  [        R                  S	S
S9  U(       a  [        R                  5         g[        $ )a  
Returns the unit impulse response (Input is the Dirac-Delta Function) of a
continuous-time system.

Parameters
==========

system : SISOLinearTimeInvariant type
    The LTI SISO system for which the Impulse Response is to be computed.
color : str, tuple, optional
    The color of the line. Default is Blue.
show : boolean, optional
    If ``True``, the plot will be displayed otherwise
    the equivalent matplotlib ``plot`` object will be returned.
    Defaults to True.
lower_limit : Number, optional
    The lower limit of the plot range. Defaults to 0.
upper_limit : Number, optional
    The upper limit of the plot range. Defaults to 10.
prec : int, optional
    The decimal point precision for the point coordinate values.
    Defaults to 8.
show_axes : boolean, optional
    If ``True``, the coordinate axes will be shown. Defaults to False.
grid : boolean, optional
    If ``True``, the plot will have a grid. Defaults to True.

Examples
========

.. plot::
    :context: close-figs
    :format: doctest
    :include-source: True

    >>> from sympy.abc import s
    >>> from sympy.physics.control.lti import TransferFunction
    >>> from sympy.physics.control.control_plots import impulse_response_plot
    >>> tf1 = TransferFunction(8*s**2 + 18*s + 32, s**3 + 6*s**2 + 14*s + 24, s)
    >>> impulse_response_plot(tf1)   # doctest: +SKIP

See Also
========

step_response_plot, ramp_response_plot

References
==========

.. [1] https://www.mathworks.com/help/control/ref/dynamicsystem.impulse.html

r   r]   r   r   zImpulse Response of $rX   rY   rZ   r   r\   N)r   r`   ra   rb   rc   rd   r   re   rf   rg   rh   r   s              r7   r   r     s    l +6 DD<BDDAHHQHJJzJJ{II%eFm_A6BI?
AW%AW%
Jr9   c                 `   US:  a  [        S5      eUS:  a  [        S5      e[        U 5        [        S5      nXR                  5       -  U R                  S-  -  n[        XpR                  SS9n[        XpR                  U5      R                  U5      n[        XX4440 UD6R                  5       $ )a4  
Returns the numerical values of the points in the ramp response plot
of a SISO continuous-time system. By default, adaptive sampling
is used. If the user wants to instead get an uniformly
sampled response, then ``adaptive`` kwarg should be passed ``False``
and ``n`` must be passed as additional kwargs.
Refer to the parameters of class :class:`sympy.plotting.series.LineOver1DRangeSeries`
for more details.

Parameters
==========

system : SISOLinearTimeInvariant
    The system for which the ramp response data is to be computed.
slope : Number, optional
    The slope of the input ramp function. Defaults to 1.
prec : int, optional
    The decimal point precision for the point coordinate values.
    Defaults to 8.
lower_limit : Number, optional
    The lower limit of the plot range. Defaults to 0.
upper_limit : Number, optional
    The upper limit of the plot range. Defaults to 10.
kwargs :
    Additional keyword arguments are passed to the underlying
    :class:`sympy.plotting.series.LineOver1DRangeSeries` class.

Returns
=======

tuple : (x, y)
    x = Time-axis values of the points in the ramp response plot. NumPy array.
    y = Amplitude-axis values of the points in the ramp response plot. NumPy array.

Raises
======

NotImplementedError
    When a SISO LTI system is not passed.

    When time delay terms are present in the system.

ValueError
    When more than one free symbol is present in the system.
    The only variable in the transfer function should be
    the variable of the Laplace transform.

    When ``lower_limit`` parameter is less than 0.

    When ``slope`` is negative.

Examples
========

>>> from sympy.abc import s
>>> from sympy.physics.control.lti import TransferFunction
>>> from sympy.physics.control.control_plots import ramp_response_numerical_data
>>> tf1 = TransferFunction(s, s**2 + 5*s + 8, s)
>>> ramp_response_numerical_data(tf1)   # doctest: +SKIP
(([0.0, 0.12166980856813935,..., 9.861246379582118, 10.0],
[1.4504508011325967e-09, 0.006046440489058766,..., 0.12499999999568202, 0.12499999999661349]))

See Also
========

ramp_response_plot

r   z,Slope must be greater than or equal to zero.rv   rP      Trw   ry   )	r4   sloper}   r~   r   rn   r   r   r   s	            r7   r   r     s    L qy   	Q % & 	&&	sB..""fjj1_5Dzz-D	tZZ	4	:	:4	@B +%C 
*,r9   c	                    [        U 4XXES.U	D6u  p[        R                  XUS9  [        R                  S5        [        R	                  S5        [        R                  S[        U 5       SU S3SS	9  U(       a  [        R                  5         U(       a(  [        R                  S
SS9  [        R                  S
SS9  U(       a  [        R                  5         g[        $ )a  
Returns the ramp response of a continuous-time system.

Ramp function is defined as the straight line
passing through origin ($f(x) = mx$). The slope of
the ramp function can be varied by the user and
the default value is 1.

Parameters
==========

system : SISOLinearTimeInvariant type
    The LTI SISO system for which the Ramp Response is to be computed.
slope : Number, optional
    The slope of the input ramp function. Defaults to 1.
color : str, tuple, optional
    The color of the line. Default is Blue.
show : boolean, optional
    If ``True``, the plot will be displayed otherwise
    the equivalent matplotlib ``plot`` object will be returned.
    Defaults to True.
lower_limit : Number, optional
    The lower limit of the plot range. Defaults to 0.
upper_limit : Number, optional
    The upper limit of the plot range. Defaults to 10.
prec : int, optional
    The decimal point precision for the point coordinate values.
    Defaults to 8.
show_axes : boolean, optional
    If ``True``, the coordinate axes will be shown. Defaults to False.
grid : boolean, optional
    If ``True``, the plot will have a grid. Defaults to True.

Examples
========

.. plot::
    :context: close-figs
    :format: doctest
    :include-source: True

    >>> from sympy.abc import s
    >>> from sympy.physics.control.lti import TransferFunction
    >>> from sympy.physics.control.control_plots import ramp_response_plot
    >>> tf1 = TransferFunction(s, (s+4)*(s+8), s)
    >>> ramp_response_plot(tf1, upper_limit=2)   # doctest: +SKIP

See Also
========

step_response_plot, impulse_response_plot

References
==========

.. [1] https://en.wikipedia.org/wiki/Ramp_function

)r   r}   r~   r   r]   r   r   zRamp Response of $z$ [Slope = ]rY   rZ   r   r\   N)r   r`   ra   rb   rc   rd   r   re   rf   rg   rh   )r4   r   rT   r}   r~   r   rm   re   rh   rn   rP   r   s               r7   r   r   W  s    x ( DeD<BDDAHHQHJJzJJ{II"5=/UG1E2IN
AW%AW%
Jr9   c                 v   [        U 5        U R                  5       nSnX6;  a  [        S5      e[        SSS9nUS:X  a  [        U-  S-  [
        -  nO	[        U-  nUR                  U R                  U05      n	S[        [        U	5      S	5      -  n
[        U
US	U-  S	U-  44S
S0UD6R                  5       u  pX4$ )a  
Returns the numerical data of the Bode magnitude plot of the system.
It is internally used by ``bode_magnitude_plot`` to get the data
for plotting Bode magnitude plot. Users can use this data to further
analyse the dynamics of the system or plot using a different
backend/plotting-module.

Parameters
==========

system : SISOLinearTimeInvariant
    The system for which the data is to be computed.
initial_exp : Number, optional
    The initial exponent of 10 of the semilog plot. Defaults to -5.
final_exp : Number, optional
    The final exponent of 10 of the semilog plot. Defaults to 5.
freq_unit : string, optional
    User can choose between ``'rad/sec'`` (radians/second) and ``'Hz'`` (Hertz) as frequency units.

Returns
=======

tuple : (x, y)
    x = x-axis values of the Bode magnitude plot.
    y = y-axis values of the Bode magnitude plot.

Raises
======

NotImplementedError
    When a SISO LTI system is not passed.

    When time delay terms are present in the system.

ValueError
    When more than one free symbol is present in the system.
    The only variable in the transfer function should be
    the variable of the Laplace transform.

    When incorrect frequency units are given as input.

Examples
========

>>> from sympy.abc import s
>>> from sympy.physics.control.lti import TransferFunction
>>> from sympy.physics.control.control_plots import bode_magnitude_numerical_data
>>> tf1 = TransferFunction(s**2 + 1, s**4 + 4*s**3 + 6*s**2 + 5*s + 2, s)
>>> bode_magnitude_numerical_data(tf1)   # doctest: +SKIP
([1e-05, 1.5148378120533502e-05,..., 68437.36188804005, 100000.0],
[-6.020599914256786, -6.0205999155219505,..., -193.4117304087953, -200.00000000260573])

See Also
========

bode_magnitude_plot, bode_phase_numerical_data

rad/secHz5Only "rad/sec" and "Hz" are accepted frequency units.wTr^   r   r   rY   
   xscaler   )r8   r/   r2   r   r   r   subsrK   r   r   r   r{   )r4   initial_exp	final_exp	freq_unitrn   r   
freq_units_wreplw_exprmagrP   r   s                r7   r   r     s    v &>>D"J"PQQ	s	BDtAvbytYY

D)*F
SVb!
!C 	R_b)m,F5:F>DFFPjl 	A 4Kr9   c                    [        XX'S9u  p[        R                  " X4SU0UD6  [        R                  S5        [        R	                  SU-  5        [        R                  S5        [        R                  S[        U 5       S3SS	9  U(       a  [        R                  S
5        U(       a(  [        R                  SSS9  [        R                  SSS9  U(       a  [        R                  5         g[        $ )zi
Returns the Bode magnitude plot of a continuous-time system.

See ``bode_plot`` for all the parameters.
)r   r   r   rT   r   Frequency (%s) [Log Scale]zMagnitude (dB)zBode Plot (Magnitude) of $rX   rY   rZ   Tr   r\   r]   N)r   r`   ra   r   rb   rc   rd   r   re   rf   rg   rh   )r4   r   r   rT   rm   re   rh   r   rn   rP   r   s              r7   r   r     s     )2DAHHQ))&)JJu JJ+i78JJ II*5=/;IDAW%AW%
Jr9   c                    [        U 5        U R                  5       nSnSn	X8;  a  [        S5      eXI;  a  [        S5      e[        SSS9n
US:X  a  [        U
-  S	-  [
        -  nO	[        U
-  nUR                  U R                  U05      nUS
:X  a  [        U5      S-  [
        -  nO[        U5      n[        UU
SU-  SU-  44SS0UD6R                  5       u  pSnU(       a  US:X  a  [
        nOUS
:X  a  SnU(       aV  S	U-  n[        S[        U5      5       H8  nUU   UUS-
     -
  nUU:  a  UU   U-
  UU'   M$  UU* :  d  M-  UU   U-   UU'   M:     X4$ )a  
Returns the numerical data of the Bode phase plot of the system.
It is internally used by ``bode_phase_plot`` to get the data
for plotting Bode phase plot. Users can use this data to further
analyse the dynamics of the system or plot using a different
backend/plotting-module.

Parameters
==========

system : SISOLinearTimeInvariant
    The system for which the Bode phase plot data is to be computed.
initial_exp : Number, optional
    The initial exponent of 10 of the semilog plot. Defaults to -5.
final_exp : Number, optional
    The final exponent of 10 of the semilog plot. Defaults to 5.
freq_unit : string, optional
    User can choose between ``'rad/sec'`` (radians/second) and '``'Hz'`` (Hertz) as frequency units.
phase_unit : string, optional
    User can choose between ``'rad'`` (radians) and ``'deg'`` (degree) as phase units.
phase_unwrap : bool, optional
    Set to ``True`` by default.

Returns
=======

tuple : (x, y)
    x = x-axis values of the Bode phase plot.
    y = y-axis values of the Bode phase plot.

Raises
======

NotImplementedError
    When a SISO LTI system is not passed.

    When time delay terms are present in the system.

ValueError
    When more than one free symbol is present in the system.
    The only variable in the transfer function should be
    the variable of the Laplace transform.

    When incorrect frequency or phase units are given as input.

Examples
========

>>> from sympy.abc import s
>>> from sympy.physics.control.lti import TransferFunction
>>> from sympy.physics.control.control_plots import bode_phase_numerical_data
>>> tf1 = TransferFunction(s**2 + 1, s**4 + 4*s**3 + 6*s**2 + 5*s + 2, s)
>>> bode_phase_numerical_data(tf1)   # doctest: +SKIP
([1e-05, 1.4472354033813751e-05, 2.035581932165858e-05,..., 47577.3248186011, 67884.09326036123, 100000.0],
[-2.5000000000291665e-05, -3.6180885085e-05, -5.08895483066e-05,...,-3.1415085799262523, -3.14155265358979])

See Also
========

bode_magnitude_plot, bode_phase_numerical_data

r   )radr   r   z.Only "rad" and "deg" are accepted phase units.r   Tr   r   r   r      r   r   r   Nr   r,   )r8   r/   r2   r   r   r   r   rK   r
   r   r{   ranger0   )r4   r   r   r   
phase_unitphase_unwraprn   r   r   phase_unitsr   r   r   phaserP   r   halfunitr@   diffs                       r7   r   r     s   ~ &>>D"J K"PQQ$IJJ	s	BDtAvbytYY

D)*FUFC"F 	R_b)m,F5:F>DFFPjl 	A DD5 Dvq#a&!AQ4!AE(?Dd{!t!!t! " 4Kr9   c
           	         [        XX'XS9u  p[        R                  " X4SU0U
D6  [        R                  S5        [        R	                  SU-  5        [        R                  SU-  5        [        R                  S[        U 5       S3SS	9  U(       a  [        R                  S
5        U(       a(  [        R                  SSS9  [        R                  SSS9  U(       a  [        R                  5         g[        $ )ze
Returns the Bode phase plot of a continuous-time system.

See ``bode_plot`` for all the parameters.
)r   r   r   r   r   rT   r   r   z
Phase (%s)zBode Plot (Phase) of $rX   rY   rZ   Tr   r\   r]   N)r   r`   ra   r   rb   rc   rd   r   re   rf   rg   rh   )r4   r   r   rT   rm   re   rh   r   r   r   rn   rP   r   s                r7   r    r    |  s     %VZdDAHHQ))&)JJuJJ+i78JJ|j()II&uV}oQ7RI@AW%AW%
Jr9   c	                 Z   [         R                  S5        [        U 4XSX4US.U	D6n
U
R                  S[	        U 5       S3SS9  U
R                  S5        [         R                  S	5        [        U 4XSX4XgUS
.U	D6R                  S5        U(       a  [         R                  5         g[         $ )a,  
Returns the Bode phase and magnitude plots of a continuous-time system.

Parameters
==========

system : SISOLinearTimeInvariant type
    The LTI SISO system for which the Bode Plot is to be computed.
initial_exp : Number, optional
    The initial exponent of 10 of the semilog plot. Defaults to -5.
final_exp : Number, optional
    The final exponent of 10 of the semilog plot. Defaults to 5.
show : boolean, optional
    If ``True``, the plot will be displayed otherwise
    the equivalent matplotlib ``plot`` object will be returned.
    Defaults to True.
prec : int, optional
    The decimal point precision for the point coordinate values.
    Defaults to 8.
grid : boolean, optional
    If ``True``, the plot will have a grid. Defaults to True.
show_axes : boolean, optional
    If ``True``, the coordinate axes will be shown. Defaults to False.
freq_unit : string, optional
    User can choose between ``'rad/sec'`` (radians/second) and ``'Hz'`` (Hertz) as frequency units.
phase_unit : string, optional
    User can choose between ``'rad'`` (radians) and ``'deg'`` (degree) as phase units.

Examples
========

.. plot::
    :context: close-figs
    :format: doctest
    :include-source: True

    >>> from sympy.abc import s
    >>> from sympy.physics.control.lti import TransferFunction
    >>> from sympy.physics.control.control_plots import bode_plot
    >>> tf1 = TransferFunction(1*s**2 + 0.1*s + 7.5, 1*s**4 + 0.12*s**3 + 9*s**2, s)
    >>> bode_plot(tf1, initial_exp=0.2, final_exp=0.7)   # doctest: +SKIP

See Also
========

bode_magnitude_plot, bode_phase_plot

   F)r   r   rh   re   rm   r   zBode Plot of $rX   rY   rZ   N   )r   r   rh   re   rm   r   r   r   )r`   subplotr   rd   r   rb   r    rh   )r4   r   r   re   rm   rh   r   r   r   rn   r   s              r7   r!   r!     s    d KK
f '+'%'C IIuV}oQ/RI8JJtKKF EimyE ~DE FK  FK  LP  FQ
Jr9   c                     U R                   n[        SSS9n[        U-  nU R                  5       nUR	                  X05      nUR                  5       nUS   nUS   nXgU4$ )z0Function to get the expression for Nyquist plot.r   Tr   r   r,   )rK   r   r   r/   r   as_real_imag)r4   sr   r   r   r   	real_expr	imag_exprs           r7   r"   r"     sg    

AcAq5D>>DYYy!F  "Fq	Iq	I""r9   c                     U R                   n[        SSS9nU R                  5       nUR                  U[        U-  5      n[        U5      nS[        US5      -  n[        U5      n[        U5      nXhU4$ )z0Function to get the expression for Nichols plot.r   Tr   rY   r   )	rK   r   r/   r   r   r   r   r
   r   )	r4   r   r   sys_exprH_jwmag_exprmag_dB_expr
phase_exprphase_deg_exprs	            r7   r$   r$     sn    

AcA~~H==AaC D4yHS2&&KTJ_N))r9   c                     [        U 5        [        U 5      u  pgnXU4/n	[        Xg4Xg* 4/U	Q7SUSS[        U 5       S3SSSUS.6n
U(       a  U
R	                  5         g	U
$ )
a-  
Generates the Nyquist plot for a continuous-time system.

Parameters
==========

system : SISOLinearTimeInvariant
    The LTI SISO system for which the Nyquist plot is to be generated.
initial_omega : float, optional
    The starting frequency value. Defaults to 0.01.
final_omega : float, optional
    The ending frequency value. Defaults to 100.
show : bool, optional
    If True, the plot is displayed. Default is True.
color : str, optional
    The color of the Nyquist plot. Default is 'b' (blue).
grid : bool, optional
    If True, grid lines are displayed. Default is False.
**kwargs
    Additional keyword arguments for customization.

Examples
========

.. plot::
    :context: close-figs
    :format: doctest
    :include-source: True

    >>> from sympy.abc import s
    >>> from sympy.physics.control.lti import TransferFunction
    >>> from sympy.physics.control.control_plots import nyquist_plot
    >>> tf1 = TransferFunction(2*s**2 + 5*s + 1, s**2 + 2*s + 3, s)
    >>> nyquist_plot(tf1)   # doctest: +SKIP

See Also
========

nichols_plot, bode_plot

FTzNyquist Plot of $rX   rV   rW         )rh   
line_coloradaptiverd   rb   rc   sizern   N)r8   r"   r   r   rh   )r4   initial_omegafinal_omegarh   rT   rn   r   r   r   w_valuesps              r7   r#   r#     s    V &/7I!;/0H		J	 
	 !%-2	A 	Hr9   c                     [        U 5        [        U 5      u  pgnXU4/n	[        Xv4/U	Q7SUS[        U 5       S3SSSUS.6n
U(       a  U
R	                  5         gU
$ )	a  
Generates the Nichols plot for a LTI system.

Parameters
==========

system : SISOLinearTimeInvariant
    The LTI SISO system for which the Nyquist plot is to be generated.
initial_omega : float, optional
    The starting frequency value. Defaults to 0.01.
final_omega : float, optional
    The ending frequency value. Defaults to 100.
show : bool, optional
    If True, the plot is displayed. Default is True.
color : str, optional
    The color of the Nyquist plot. Default is 'b' (blue).
grid : bool, optional
    If True, grid lines are displayed. Default is False.
**kwargs
    Additional keyword arguments for customization.

Examples
========

.. plot::
    :context: close-figs
    :format: doctest
    :include-source: True

    >>> from sympy.abc import s
    >>> from sympy.physics.control.lti import TransferFunction
    >>> from sympy.physics.control.control_plots import nichols_plot
    >>> tf1 = TransferFunction(1.5, s**2+14*s+40.02, s)
    >>> nichols_plot(tf1)   # doctest: +SKIP

See Also
========

nyquist_plot, bode_plot

FzNichols Plot of $rX   zPhase [deg]zMagnitude [dB]r   )rh   r   rd   rb   rc   r   rn   N)r8   r$   r   r   rh   )r4   r   r   rh   rT   rn   magnitude_dB_exprr   r   r   r   s              r7   r%   r%   5  s    T &+<V+D(q;/0H	+					 !%-2		A 	Hr9   N)bluer   orange   TTT)   r   r   )br   r   r   FTT)r,   r   r   r   )r,   r   r   r   r   FTT)r   r   )r   r   r   FTTr   )r   r   r   r   T)	r   r   r   FTTr   r   T)r   r   TFTr   r   T)g{Gz?d   Tr   )8sympy.core.numbersr   r   &sympy.functions.elementary.exponentialr   r   sympy.polys.partfracr   sympy.core.symbolr   sympy.externalr	   sympy.functionsr
   r   sympy.integrals.laplacer   sympy.physics.control.ltir   sympy.plotting.seriesr   sympy.plotting.plotr   sympy.polys.domainsr   r   sympy.polys.polytoolsr   sympy.printing.latexr   sympy.geometry.polygonr   __all__RuntimeErrorr&   r(   r`   r8   rG   r   r   r   r   r   r   r   r   r   r   r   r    r!   r"   r$   r#   r%    r9   r7   <module>r      s>   $ = & # ( $ 9 = 7 / & & & & Z($<o
 


CI" 88v ?AAE	Xv >?K\ ?@59FR ABK\ BC59FR 89!Rj HI59L^M` ;<@I:fR 78jn8 12_c@F
#
* DH=@:r9   