
    h3                        S 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
  SSKJr  SSKrSS	 jrSS
 jr " S S5      r\ " S S5      5       r " S S5      rg)a  Module for managing and transforming label data during augmentation.

This module provides utilities for encoding, decoding, and tracking metadata for labels
during the augmentation process. It includes classes for managing label transformations,
preserving data types, and ensuring consistent handling of categorical, numerical, and
mixed label types. The module supports automatic encoding of string labels to numerical
values and restoration of original data types after processing.
    )annotations)defaultdict)Sequence)	dataclass)Real)AnyNc                N    [        U [        5      (       a  SU 4$ S[        U 5      4$ )a:  Sort items by type then value for consistent label ordering.

This function is used to sort labels in a consistent order, prioritizing numerical
values before string values. All numerical values are given priority 0, while
string values are given priority 1, ensuring numerical values are sorted first.

Args:
    item (Any): Item to be sorted, can be either a numeric value or any other type.

Returns:
    tuple[int, Real | str]: A tuple with sort priority (0 for numbers, 1 for others)
        and the value itself (or string representation for non-numeric values).

r      )
isinstancer   str)items    [/var/www/fran/franai/venv/lib/python3.13/site-packages/albumentations/core/label_manager.pycustom_sortr      s'     #4..At9BQD	NB    c                r    / n/ nU  H+  n[        U[        5      (       a  UOUR                  U5        M-     X4$ N)r   r   append)labelsnumeric_labelsstring_labelslabels       r   _categorize_labelsr   '   s;    !#N!M%eT22MMeT ((r   c                  T    \ 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	rg
)LabelEncoder0   a  Encodes labels into integer indices.

This class handles the conversion between original label values and their
numerical representations. It supports both numerical and categorical labels.

Args:
    classes_ (dict[str | Real, int]): Mapping from original labels to encoded indices.
    inverse_classes_ (dict[int, str | Real]): Mapping from encoded indices to original labels.
    num_classes (int): Number of unique classes.
    is_numerical (bool): Whether the original labels are numerical.

c                <    0 U l         0 U l        SU l        SU l        g )Nr   T)classes_inverse_classes_num_classesis_numericalselfs    r   __init__LabelEncoder.__init__>   s!    /179 !"&r   c                   [        U[        R                  5      (       a  UR                  5       R	                  5       nU(       d	  SU l        U $ [        S U 5       5      U l        U R
                  (       a  U $ [        [        U5      [        S9nU HZ  nX0R                  ;  d  M  U R                  U R                  U'   X0R                  U R                  '   U =R                  S-  sl        M\     U $ )zFit the encoder to the input labels.

Args:
    y (Sequence[Any] | np.ndarray): Input labels to fit the encoder.

Returns:
    LabelEncoder: The fitted encoder instance.

Fc              3  B   #    U  H  n[        U[        5      v   M     g 7fr   )r   r   .0r   s     r   	<genexpr>#LabelEncoder.fit.<locals>.<genexpr>V   s     GQE
5$ 7 7Qs   keyr
   )r   npndarrayflattentolistr    allsortedsetr   r   r   r   )r"   yunique_labelsr   s       r   fitLabelEncoder.fitD   s     a$$		""$A  %DKGQGGKs1v;7"EMM)'+'7'7e$:?%%d&6&67  A% 	 #
 r   c                :   [        U[        R                  5      (       a  UR                  5       R	                  5       nU R
                  (       a  [        R                  " U5      $ [        R                  " U Vs/ s H  o R                  U   PM     sn5      $ s  snf )zTransform labels to encoded integer indices.

Args:
    y (Sequence[Any] | np.ndarray): Input labels to transform.

Returns:
    np.ndarray: Encoded integer indices.

)r   r-   r.   r/   r0   r    arrayr   r"   r4   r   s      r   	transformLabelEncoder.transformc   sh     a$$		""$A88A;xx1=1%u-1=>>=   9Bc                F    U R                  U5        U R                  U5      $ )zFit the encoder and transform the input labels in one step.

Args:
    y (Sequence[Any] | np.ndarray): Input labels to fit and transform.

Returns:
    np.ndarray: Encoded integer indices.

)r6   r;   )r"   r4   s     r   fit_transformLabelEncoder.fit_transformu   s     	~~a  r   c                :   [        U[        R                  5      (       a  UR                  5       R	                  5       nU R
                  (       a  [        R                  " U5      $ [        R                  " U Vs/ s H  o R                  U   PM     sn5      $ s  snf )zTransform encoded indices back to original labels.

Args:
    y (Sequence[Any] | np.ndarray): Encoded integer indices.

Returns:
    np.ndarray: Original labels.

)r   r-   r.   r/   r0   r    r9   r   r:   s      r   inverse_transformLabelEncoder.inverse_transform   sj     a$$		""$A88A;xx1E1%..u51EFFEr=   c                r   U R                   (       a  U $ [        U[        R                  5      (       a  UR	                  5       R                  5       nO>[        U[        5      (       a!  [        U[        5      (       d  [        U5      nOUc  U $ U/n[        U R                  R                  5       5      n[        U5      U-
  nU(       d  U $ [        U5      u  pV[        U5      [        U[        S9-   nU H@  nU R                  n	XR                  U'   XR                  U	'   U =R                  S-  sl        MB     U $ )a  Update the encoder with new labels encountered after initial fitting.

This method identifies labels in the input sequence that are not already
known to the encoder and adds them to the internal mapping. It does not
change the encoding of previously seen labels.

Args:
    y (Sequence[Any] | np.ndarray): A sequence or array of potentially new labels.

Returns:
    LabelEncoder: The updated encoder instance.

r+   r
   )r    r   r-   r.   r/   r0   r   r   listr3   r   keysr   r2   r   r   )
r"   r4   input_labelscurrent_labels_setnew_unique_labelsr   r   sorted_new_labelsr   new_ids
             r   updateLabelEncoder.update   s    K a$$99;--/L8$$Z3-?-?7LYK 3L !!3!3!56-0BB K );;L(M%">2VMs5SS&E%%F#)MM% ,1!!&)!	 ' r   )r   r   r    r   NreturnNone)r4   Sequence[Any] | np.ndarrayrO   r   )r4   rQ   rO   
np.ndarray)__name__
__module____qualname____firstlineno____doc__r#   r6   r;   r?   rB   rL   __static_attributes__ r   r   r   r   0   s&    '>?$!G$0r   r   c                  J    \ rS rSr% SrS\S'   S\S'   SrS\S	'   SrS
\S'   Srg)LabelMetadata   z$Stores metadata about a label field.type
input_typeboolr    Nznp.dtype | NonedtypeLabelEncoder | NoneencoderrY   )	rS   rT   rU   rV   rW   __annotations__r`   rb   rX   rY   r   r   r[   r[      s&    .!E?!#'G 'r   r[   c                  r    \ 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rSrg)LabelManager   a  Manages label encoding and decoding across multiple data fields.

This class handles the encoding, decoding, and type management for label fields.
It maintains metadata about each field to ensure proper conversion between
original and encoded representations.

Args:
    metadata (dict[str, dict[str, LabelMetadata]]): Dictionary mapping data types
        and label fields to their metadata.

c                ,    [        [        5      U l        g r   )r   dictmetadatar!   s    r   r#   LabelManager.__init__   s    =H=Nr   c                J   XR                   ;   ab  X R                   U   ;   aP  U R                   U   U   nUR                  (       d,  UR                  (       a  UR                  R                  U5        O"U R	                  U5      nX@R                   U   U'   U R                  X45      $ )aP  Process a label field, store metadata, and encode.

If the field has been processed before (metadata exists), this will update
the existing LabelEncoder with any new labels found in `field_data` before encoding.
Otherwise, it analyzes the input, creates metadata, and fits the encoder.

Args:
    data_name (str): The name of the main data type (e.g., 'bboxes', 'keypoints').
    label_field (str): The specific label field being processed (e.g., 'class_labels').
    field_data (Any): The actual label data for this field.

Returns:
    np.ndarray: The encoded label data as a numpy array.

)ri   r    rb   rL   _analyze_input_encode_data)r"   	data_namelabel_field
field_datari   s        r   process_fieldLabelManager.process_field   s      %+y9Q*Q}}Y/<H((X-=-=  ''
3 **:6H4<MM)$[1   66r   c                j    U R                   U   U   nU R                  X45      nU R                  XT5      $ )z-Restore a label field to its original format.)ri   _decode_data_restore_type)r"   rn   ro   encoded_datari   decoded_datas         r   restore_fieldLabelManager.restore_field   s6    ==+K8((@!!,99r   c                >   [        U5      n[        U[        R                  5      (       a  UR                  OSn[        U[        R                  5      (       a@  UR
                  S:  a0  [        R                  " UR                  [        R                  5      nOd[        U[        5      (       a/  [        U[        5      (       d  U(       a  [        S U 5       5      nO [        U[        [        45      (       a  SnOSn[        UUUS9nU(       d  [        5       Ul        U$ )z'Analyze input data and create metadata.Nr   c              3  N   #    U  H  n[        U[        [        45      v   M     g 7fr   )r   intfloatr'   s     r   r)   .LabelManager._analyze_input.<locals>.<genexpr>  s     WJ5z%#u>>Js   #%TF)r^   r    r`   )r]   r   r-   r.   r`   size
issubdtypenumberr   r   r1   r|   r}   r[   r   rb   )r"   rp   r^   r`   r    ri   s         r   rl   LabelManager._analyze_input  s    *%
$.z2::$F$F
  D j"**--*//A2E==)9)9299EL
H--jS6Q6QV`WJWWL
S%L11L !L !%
 +~Hr   c                   UR                   (       a  [        U[        R                  5      (       a/  UR	                  SS5      R                  [        R                  5      $ [        R                  " U[        R                  S9R	                  SS5      $ UR                  c  [        S5      eUR                  R                  U5      R	                  SS5      $ )z!Encode field data for processing.r
   )r`   z.Encoder not initialized for non-numerical data)r    r   r-   r.   reshapeastypefloat32r9   rb   
ValueErrorr?   )r"   rp   ri   s      r   rm   LabelManager._encode_data  s      *bjj11!))"a077

CC88Jbjj9AA"aHH #MNN--j9AA"aHHr   c                B   UR                   (       a8  UR                  b  UR                  UR                  5      $ UR                  5       $ UR                  c  [        S5      eUR                  R                  UR                  [        5      5      nUR                  S5      $ )zDecode processed data.z(Encoder not found for non-numerical datar   )	r    r`   r   r/   rb   r   rB   r|   r   )r"   rv   ri   decodeds       r   rt   LabelManager._decode_data,  s      ~~)#**8>>::''))#GHH""44\5H5H5MNr""r   c                   [        UR                  [        5      (       a5  [        UR                  [        [
        45      (       a  UR                  5       $ [        UR                  [        5      (       aS  [        UR                  [        R                  5      (       a*  UR                  b  UR                  UR                  5      $ U$ UR                  5       $ )z"Restore data to its original type.)r   r^   r]   
issubclassrE   r   r0   r-   r.   r`   r   )r"   rw   ri   s      r   ru   LabelManager._restore_type9  s     h))400Z@S@SVZ\dUe5f5f&&(( h))400Z@S@SUWU_U_5`5`~~)#**8>>:: ""$$r   c                    / $ )zHandle empty data case.rY   r!   s    r   handle_empty_dataLabelManager.handle_empty_dataH  s    	r   c                    XR                   ;   aE  X R                   U   ;   a3  U R                   U   U   R                  n[        U[        5      (       a  U$ g)zFRetrieves the fitted LabelEncoder for a specific data and label field.N)ri   rb   r   r   )r"   rn   ro   rb   s       r   get_encoderLabelManager.get_encoderL  sH    %+y9Q*QmmI.{;CCG'<00r   )ri   NrN   )rn   r   ro   r   rp   r   rO   rR   )rn   r   ro   r   rv   rR   rO   r   )rp   r   rO   r[   )rp   r   ri   r[   rO   rR   )rv   rR   ri   r[   rO   rR   )rw   rR   ri   r[   rO   r   )rO   z	list[Any])rn   r   ro   r   rO   ra   )rS   rT   rU   rV   rW   r#   rq   rx   rl   rm   rt   ru   r   r   rX   rY   r   r   re   re      s6    
O7::6I#%r   re   )r   r   rO   ztuple[int, Real | str])r   zset[Any]rO   ztuple[list[Real], list[str]])rW   
__future__r   collectionsr   collections.abcr   dataclassesr   numbersr   typingr   numpyr-   r   r   r   r[   re   rY   r   r   <module>r      s^    # # $ !   C$)T Tn ( ( (B Br   