
    7 d2E                         d dl Zd dlmZ d dlmZ d dlmZmZm	Z	 ddgZ
ddgZ	 d dlmZ d	Zn# e$ r d
Z ed          ZY nw xY w G d de          ZdS )    N)interpolate)argrelextrema)TupleOptionalIterableconvexconcave
increasing
decreasingTFz\This function needs Matplotlib to be executed. Please run command `pip install kneed[plot]` c                   .   e Zd ZdZ	 	 	 	 	 	 d'dee         d	ee         d
edededededefdZ	e
dee         dee         fd            Ze
d	ee         dededefd            Zd Z	 	 	 	 d(deeeef                  dedee         dee         fdZ	 	 	 	 d)deeeef                  dedee         dee         fdZed             Zed              Zed!             Zed"             Zed#             Zed$             Zed%             Zed&             ZdS )*KneeLocatora0  
    Once instantiated, this class attempts to find the point of maximum
    curvature on a line. The knee is accessible via the `.knee` attribute.

    :param x: x values, must be the same length as y.
    :type x: 1D array of shape (`number_of_y_values`,) or list
    :param y: y values, must be the same length as x.
    :type y: 1D array of shape (`number_of_y_values`,) or list
    :param S: Sensitivity, the number of minimum number of data points below the local distance maximum before calling a knee. The original paper suggests default of 1.0
    :type S: float
    :param curve: If 'concave', algorithm will detect knees. If 'convex', it
        will detect elbows.
    :type curve: str
    :param direction: one of {"increasing", "decreasing"}
    :type direction: str
    :param interp_method: one of {"interp1d", "polynomial"}
    :type interp_method: str
    :param online: kneed will correct old knee points if True, will return first knee if False
    :type online: bool
    :param polynomial_degree: The degree of the fitting polynomial. Only used when interp_method="polynomial". This argument is passed to numpy polyfit `deg` parameter.
    :type polynomial_degree: int
    :ivar x: x values.
    :vartype x: array-like
    :ivar y: y values.
    :vartype y: array-like
    :ivar S: Sensitivity, original paper suggests default of 1.0
    :vartype S: integer
    :ivar curve: If 'concave', algorithm will detect knees. If 'convex', it
        will detect elbows.
    :vartype curve: str
    :ivar direction: one of {"increasing", "decreasing"}
    :vartype direction: str
    :ivar interp_method: one of {"interp1d", "polynomial"}
    :vartype interp_method: str
    :ivar online: kneed will correct old knee points if True, will return first knee if False
    :vartype online: str
    :ivar polynomial_degree: The degree of the fitting polynomial. Only used when interp_method="polynomial". This argument is passed to numpy polyfit `deg` parameter.
    :vartype polynomial_degree: int
    :ivar N: The number of `x` values in the
    :vartype N: integer
    :ivar all_knees: A set containing all the x values of the identified knee points.
    :vartype all_knees: set
    :ivar all_norm_knees: A set containing all the normalized x values of the identified knee points.
    :vartype all_norm_knees: set
    :ivar all_knees_y: A list containing all the y values of the identified knee points.
    :vartype all_knees_y: list
    :ivar all_norm_knees_y: A list containing all the normalized y values of the identified knee points.
    :vartype all_norm_knees_y: list
    :ivar Ds_y: The y values from the fitted spline.
    :vartype Ds_y: numpy array
    :ivar x_normalized: The normalized x values.
    :vartype x_normalized: numpy array
    :ivar y_normalized: The normalized y values.
    :vartype y_normalized: numpy array
    :ivar x_difference: The x values of the difference curve.
    :vartype x_difference: numpy array
    :ivar y_difference: The y values of the difference curve.
    :vartype y_difference: numpy array
    :ivar maxima_indices: The indices of each of the maxima on the difference curve.
    :vartype maxima_indices: numpy array
    :ivar maxima_indices: The indices of each of the maxima on the difference curve.
    :vartype maxima_indices: numpy array
    :ivar x_difference_maxima: The x values from the difference curve where the local maxima are located.
    :vartype x_difference_maxima: numpy array
    :ivar y_difference_maxima: The y values from the difference curve where the local maxima are located.
    :vartype y_difference_maxima: numpy array
    :ivar minima_indices: The indices of each of the minima on the difference curve.
    :vartype minima_indices: numpy array
    :ivar minima_indices: The indices of each of the minima on the difference curve.
    :vartype maxima_indices: numpy array
    :ivar x_difference_minima: The x values from the difference curve where the local minima are located.
    :vartype x_difference_minima: numpy array
    :ivar y_difference_minima: The y values from the difference curve where the local minima are located.
    :vartype y_difference_minima: numpy array
    :ivar Tmx: The y values that correspond to the thresholds on the difference curve for determining the knee point.
    :vartype Tmx: numpy array
    :ivar knee: The x value of the knee point. None if no knee/elbow was detected.
    :vartype knee: float
    :ivar knee_y: The y value of the knee point. None if no knee/elbow was detected
    :vartype knee_y: float
    :ivar norm_knee: The normalized x value of the knee point. None if no knee/elbow was detected
    :vartype norm_knee: float
    :ivar norm_knee_y: The normalized y value of the knee point. None if no knee/elbow was detected
    :vartype norm_knee_y: float
    :ivar all_knees: The x values of all the identified knee points.
    :vartype all_knees: set
    :ivar all_knees_y: The y values of all the identified knee points.
    :vartype all_knees: set
    :ivar all_norm_knees: The normalized x values of all the identified knee points.
    :vartype all_norm_knees: set
    :ivar all_norm_knees_y: The normalized y values of all the identified knee points.
    :vartype all_norm_knees: set
    :ivar elbow: The x value of the elbow point (elbow and knee are interchangeable). None if no knee/elbow was detected
    :vartype elbow: float
    :ivar elbow_y: The y value of the knee point (elbow and knee are interchangeable). None if no knee/elbow was detected
    :vartype elbow_y: float
    :ivar norm_elbow: The normalized x value of the knee point (elbow and knee are interchangeable). None if no knee/elbow was detected
    :vartype norm_knee: float
    :ivar norm_elbow_y: The normalized y value of the knee point (elbow and knee are interchangeable). None if no knee/elbow was detected
    :vartype norm_elbow_y: float
    :ivar all_elbows: The x values of all the identified knee points (elbow and knee are interchangeable).
    :vartype all_elbows: set
    :ivar all_elbows_y: The y values of all the identified knee points (elbow and knee are interchangeable).
    :vartype all_elbows: set
    :ivar all_norm_elbows: The normalized x values of all the identified knee points (elbow and knee are interchangeable).
    :vartype all_norm_elbows: set
    :ivar all_norm_elbows_y: The normalized y values of all the identified knee points (elbow and knee are interchangeable).
    :vartype all_norm_elbows: set
          ?r	   r
   interp1dF   xyScurve	directioninterp_methodonlinepolynomial_degreec	                 F   t          j        |          | _        t          j        |          | _        || _        || _        t          | j                  | _        || _        t                      | _
        t                      | _        g | _        g | _        || _        || _        | j        t           v }	| j        t"          v }
t%          |	|
f          st'          d          |dk    r5t)          j        | j        | j                  } || j                  | _        nf|dk    r>t          j        t          j        ||| j                            } ||          | _        n"t'          d                    |                    |                     | j                  | _        |                     | j                  | _        |                     | j        | j        | j                  | _        | j        | j        z
  | _        | j                                        | _         tC          | j        t           j"                  d         | _#        | j         | j#                 | _$        | j        | j#                 | _%        tC          | j        t           j&                  d         | _'        | j         | j'                 | _(        | j        | j'                 | _)        | j%        | j        t          j*        t          j+        | j                  ,                                          z  z
  | _-        | .                                \  | _/        | _0        d x| _1        | _2        | j/        rN| j        | j        | j/        k             d         | _1        | j        | j        | j0        k             d         | _2        d S d S )Nz>Please check that the curve and direction arguments are valid.r   
polynomialzO{} is an invalid interp_method parameter, use either 'interp1d' or 'polynomial'r   )3nparrayr   r   r   r   lenNr   set	all_kneesall_norm_kneesall_knees_yall_norm_knees_yr   r   VALID_CURVEVALID_DIRECTIONall
ValueErrorr   r   Ds_ypoly1dpolyfitformat_KneeLocator__normalizex_normalizedy_normalizedtransform_yy_differencecopyx_differencer   greater_equalmaxima_indicesx_difference_maximay_difference_maxima
less_equalminima_indicesx_difference_minimay_difference_minimaabsdiffmeanTmx	find_kneeknee	norm_kneeknee_ynorm_knee_y)selfr   r   r   r   r   r   r   r   valid_curvevalid_directionusplineps                2lib/python3.11/site-packages/kneed/knee_locator.py__init__zKneeLocator.__init__   s,    !!
"TV!ee "!2 jK/.O;K122 	P  
 J&&!*4646::GDIIl**	"*Q4+ABBCCA!DIIahh!    !,,TV44 ,,TY77 !,,t~tz
 
 !-0AA -2244 ,D,=r?OPPQRS#'#4T5H#I #'#4T5H#I  ,D,=r}MMaP#'#4T5H#I #'#4T5H#I  +FRVBGD$566;;==>>>

 %)NN$4$4!	4> *.-d&9 	Y&49!45a8DK#01Bdn1TUVWXD	Y 	Y    areturnc                 f    | t          |           z
  t          |           t          |           z
  z  S )zDnormalize an array
        :param a: The array to normalize
        )minmax)rL   s    rI   __normalizezKneeLocator.__normalize   s)    
 CFF
s1vvA//rK   c                     |dk    r9|dk    rt          j        |           } nS|dk    r|                                 | z
  } n5|dk    r/|dk    r)t          j        |                                 | z
            } | S )zEtransform y to concave, increasing based on given direction and curver   r	   r   r
   )r   fliprP   )r   r   r   s      rI   r/   zKneeLocator.transform_y   s{     $$	!!GAJJ(""EEGGaK,&&5H+<+<!$$ArK   c                    | j         j        sdS d}d}d}t          | j                  D ]\  }}|| j         d         k     r|dz   }|t	          | j                  dz
  k    r n| j         |k                                    r| j        |         }|}|dz  }| j        |k                                    rd}|dz  }| j        |         |k     rW| j	        dk    rE| j
        dk    r| j        |         }	| j        |         }
nn| j        |dz             }	| j        |         }
nO| j	        dk    rD| j
        dk    r| j        |dz             }	| j        |         }
n| j        |         }	| j        |         }
| j        | j        |	k             d         }| j        | j        |
k             d         }|	| j        vr4| j                            |           | j                            |           | j                            |	           | j                            |
           | j        du r|	|
fc S | j        t-                      k    rdS |	|
fS )	zxThis function is called when KneeLocator is instantiated. It identifies the knee value and sets the instance attributes.)NNr   F   g        r   r   r	   )r4   size	enumerater2   r   anyr>   r8   r0   r   r   r   r-   r   r.   r    r"   appendr#   addr!   r   r   )rD   maxima_threshold_indexminima_threshold_indextraversed_maximair   j	thresholdthreshold_indexr@   rA   	y_at_kneey_norm_at_knees                rI   r?   zKneeLocator.find_knee   s    "' 	
 :!"!" d/00 3	+ 3	+DAq4&q)))AA S*++a/00 #q(--// , H%;<	"#&!+&#q(--// ,	&!+& #i//:))~55#vo6$($5o$F		#v!(;&<=$($5o$F		Z9,,~55#v!(;&<=$($5o$F		#vo6$($5o$F	 !F46T>215	!%!243D	3Q!RST!Ut~--$++I666)00@@@ ""4(((#''	222 ;%''?***>SUU"":YrK   NNormalized Knee Pointfigsizetitlexlabelylabelc                    t           st          |d}t          j        |           t          j        |           |rt          j        |           |rt          j        |           t          j        | j        | j	        dd           t          j        | j
        | j        dd           t          j        t          j        | j                                        | j                                        d	z   d	                     t          j        t          j        | j                                        | j	                                        d	z   d	                     t          j        | j        t          j                    d
         t          j                    d         dd           t          j        d           dS )a  Plot the normalized curve, the difference curve (x_difference, y_normalized) and the knee, if it exists.

        :param figsize: Optional[Tuple[int, int]
            The figure size of the plot. Example (12, 8)
        :param title: str
            Title of the visualization, defaults to "Normalized Knee Point"
        :param xlabel: Optional[str]
            X-axis label
        :param ylabel: Optional[str]
            y-axis label
        :return: NoReturn
        N   rk   re   bznormalized curvelabelrzdifference curveg?r   rU   --
knee/elbow
linestylesro   bestloc)_has_matplotlib_matplotlib_not_found_errpltfigurerf   rg   rh   plotr-   r.   r2   r0   xticksr   arangerO   rP   yticksvlinesrA   ylimlegendrD   re   rf   rg   rh   s        rI   plot_knee_normalizedz KneeLocator.plot_knee_normalized;  s   &  	,++?G
7####	% 	Jv 	Jv"D$5sBTUUUU"D$5sBTUUUU
Id'++--t/@/D/D/F/F/LcRR	
 	
 	
 	
Id'++--t/@/D/D/F/F/LcRR	
 	
 	
 	
NHJJqMHJJqM	
 	
 	
 	
 	
vrK   
Knee Pointc                    t           st          |d}t          j        |           t          j        |           |rt          j        |           |rt          j        |           t          j        | j        | j	        dd           t          j
        | j        t          j                    d         t          j                    d         d	d
           t          j        d           dS )a  
        Plot the curve and the knee, if it exists

        :param figsize: Optional[Tuple[int, int]
            The figure size of the plot. Example (12, 8)
        :param title: str
            Title of the visualization, defaults to "Knee Point"
        :param xlabel: Optional[str]
            X-axis label
        :param ylabel: Optional[str]
            y-axis label
        :return: NoReturn
        Nrj   rl   rm   datarn   r   rU   rq   rr   rs   ru   rv   )rx   ry   rz   r{   rf   rg   rh   r|   r   r   r   r@   r   r   r   s        rI   	plot_kneezKneeLocator.plot_kneel  s    (  	,++?G
7####	% 	Jv 	JvF3333
Isxzz!}chjjmL	
 	
 	
 	
 	
vrK   c                     | j         S N)r@   rD   s    rI   elbowzKneeLocator.elbow  s
    yrK   c                     | j         S r   )rA   r   s    rI   
norm_elbowzKneeLocator.norm_elbow  
    ~rK   c                     | j         S r   )rB   r   s    rI   elbow_yzKneeLocator.elbow_y  s
    {rK   c                     | j         S r   )rC   r   s    rI   norm_elbow_yzKneeLocator.norm_elbow_y      rK   c                     | j         S r   )r    r   s    rI   
all_elbowszKneeLocator.all_elbows  r   rK   c                     | j         S r   )r!   r   s    rI   all_norm_elbowszKneeLocator.all_norm_elbows  s    ""rK   c                     | j         S r   )r"   r   s    rI   all_elbows_yzKneeLocator.all_elbows_y  r   rK   c                     | j         S r   )r#   r   s    rI   all_norm_elbows_yzKneeLocator.all_norm_elbows_y  s    $$rK   )r   r	   r
   r   Fr   )Nrd   NN)Nr   NN)__name__
__module____qualname____doc__r   floatstrboolintrJ   staticmethodr,   r/   r?   r   r   r   r   propertyr   r   r   r   r   r   r   r    rK   rI   r   r      s       l ld %'!"WY WYE?WY E?WY 	WY
 WY WY WY WY WY WY WY WYr 0x 08E? 0 0 0 \0 x 3 s u    \H H HX .2, $ $/ /%S/*/ / 	/
 / / / /f .2! $ $$ $%S/*$ $ 	$
 $ $ $ $N   X   X   X     X    X # # X#     X  % % X% % %rK   r   )numpyr   scipyr   scipy.signalr   typingr   r   r   r$   r%   matplotlib.pyplotpyplotrz   rx   ImportErrorModuleNotFoundErrorry   objectr   r   rK   rI   <module>r      s             & & & & & & , , , , , , , , , ,#.###### OO    O 3 3f! !]% ]% ]% ]% ]%& ]% ]% ]% ]% ]%s   - AA