
    h#?                       S r SSKJr  SSKrSSKJr  SSKrSSKJ	r	  SSK
Jr          SS jr        SS jr      SS	 jrSS
 jrSS jr\	" S5      SS j5       r          SS jr\	" S5              SS j5       rg)ay  Module containing functional implementations of 3D transformations.

This module provides a collection of utility functions for manipulating and transforming
3D volumetric data (such as medical imaging volumes). The functions here implement the core
algorithms for operations like padding, cropping, rotation, and other spatial manipulations
specifically designed for 3D data.
    )annotationsN)Literal)handle_empty_array)NUM_VOLUME_DIMENSIONSc           
        US:X  a,  U S   S   U S   S   U S   S   U S   S   U S   S   U S   S   4$ [        U S   5      n[        U S   5      n[        U S   5      nUR                  SU5      X2R                  SU5      -
  UR                  SU5      XBR                  SU5      -
  UR                  SU5      XRR                  SU5      -
  4$ )a  Adjust padding values based on desired position for 3D data.

Args:
    paddings (list[tuple[int, int]]): List of tuples containing padding pairs
        for each dimension [(d_pad), (h_pad), (w_pad)]
    position (Literal["center", "random"]): Position of the image after padding.
    py_random (random.Random): Random number generator

Returns:
    tuple[int, int, int, int, int, int]: Final padding values (d_front, d_back, h_top, h_bottom, w_left, w_right)

centerr         )sumrandint)paddingsposition	py_randomd_padh_padw_pads         n/var/www/fran/franai/venv/lib/python3.13/site-packages/albumentations/augmentations/transforms3d/functional.pyadjust_padding_by_position3dr      s    " 8QKNQKNQKNQKNQKNQKN
 	
 EEE 	!U#!!!U++!U#!!!U++!U#!!!U++     c                    Uu  p4pVpx[        S U 5       5      (       a  U $ X44XV4Xx4/n	U R                  [        :X  a  U	R                  S5        [        R
                  " U U	SUS9$ )a  Pad 3D volume with given parameters.

Args:
    volume (np.ndarray): Input volume with shape (depth, height, width) or (depth, height, width, channels)
    padding (tuple[int, int, int, int, int, int]): Padding values in format:
        (depth_front, depth_back, height_top, height_bottom, width_left, width_right)
        where:
        - depth_front/back: padding at start/end of depth axis (z)
        - height_top/bottom: padding at start/end of height axis (y)
        - width_left/right: padding at start/end of width axis (x)
    value (tuple[float, ...] | float): Value to fill the padding

Returns:
    np.ndarray: Padded volume with same number of dimensions as input

Note:
    The padding order matches the volume dimensions (depth, height, width).
    For each dimension, the first value is padding at the start (smaller indices),
    and the second value is padding at the end (larger indices).

c              3  *   #    U  H	  oS :H  v   M     g7f)r   N ).0ps     r   	<genexpr>%pad_3d_with_params.<locals>.<genexpr>[   s     
#7a67s   )r   r   constant)	pad_widthmodeconstant_values)allndimr   appendnppad)
volumepaddingvaluedepth_front
depth_back
height_topheight_bottom
width_leftwidth_rightr   s
             r   pad_3d_with_paramsr/   >   s    4 SZOKZ
 
#7
### 
!	#	!I {{++ 66	 r   c                $    Uu  p#pEpgXU2XE2Xg24   $ )aP  Crop 3D volume using coordinates.

Args:
    volume (np.ndarray): Input volume with shape (z, y, x) or (z, y, x, channels)
    crop_coords (tuple[int, int, int, int, int, int]):
        (z_min, z_max, y_min, y_max, x_min, x_max) coordinates for cropping

Returns:
    np.ndarray: Cropped volume with same number of dimensions as input

r   )r&   crop_coordsz_minz_maxy_miny_maxx_minx_maxs           r   crop3dr8   q   s(     0;,E%+u{EK788r   c                T    U R                  5       n U H  u  p4pVpxX X62XG2XX24'   M     U $ )a  Cut out holes in 3D volume and fill them with a given value.

Args:
    volume (np.ndarray): Input volume with shape (depth, height, width) or (depth, height, width, channels)
    holes (np.ndarray): Array of holes with shape (num_holes, 6).
        Each hole is represented as [z1, y1, x1, z2, y2, x2]
    fill (tuple[float, ...] | float): Value to fill the holes

Returns:
    np.ndarray: Volume with holes filled with the given value

)copy)	r&   holesfillz1y1x1z2y2x2s	            r   cutout3drC      s:     [[]F"'&*rubeRU"# #(Mr   c                   SUs=::  a  S:  d  O  [        S5      e0 SS _SS _SS _S	S
 _SS _SS _SS _SS _SS _SS _SS _SS _SS _SS _SS  _S!S" _S#S$ _0 S%S& _S'S( _S)S* _S+S, _S-S. _S/S0 _S1S2 _S3S4 _S5S6 _S7S8 _S9S: _S;S< _S=S> _S?S@ _SASB _SCSD _SESF _ESG SH SI SJ SK SL SM SN SO SP SQ SR SS ST SU.EnX!   " U R                  5       5      $ )Va  Transform cube by index (0-47)

Args:
    cube (np.ndarray): Input array with shape (D, H, W) or (D, H, W, C)
    index (int): Integer from 0 to 47 specifying which transformation to apply

Returns:
    np.ndarray: Transformed cube with same shape as input

r   0   Index must be between 0 and 47c                    U $ )Nr   xs    r   <lambda> transform_cube.<locals>.<lambda>   s    Qr   r	   c                .    [         R                  " U SSS9$ )Nr	   r	   r
   kaxesr$   rot90rH   s    r   rJ   rK          RXXa162r   r
   c                .    [         R                  " U SSS9$ )Nr
   rM   rN   rQ   rH   s    r   rJ   rK      rS   r      c                .    [         R                  " U SSS9$ )NrU   rM   rN   rQ   rH   s    r   rJ   rK      rS   r      c                "    U S S S2S S 2S S S24   $ Nr   rH   s    r   rJ   rK      s    QttQ"}%r      c                V    [         R                  " [         R                  " U SSS9SSS9$ )Nr
   r   r
   rN   r	   rM   rQ   rH   s    r   rJ   rK          RXXbhhqAF;qvNr      c                "    U S S S2S S S2S S 24   $ rY   r   rH   s    r   rJ   rK      s    QttTrT1}%r      c                V    [         R                  " [         R                  " U SSS9SSS9$ )Nr
   r]   rN   rU   rM   rQ   rH   s    r   rJ   rK      r^   r      c                .    [         R                  " U SSS9$ )Nr	   r]   rN   rQ   rH   s    r   rJ   rK      rS   r   	   c                V    [         R                  " [         R                  " U SSS9SSS9$ )Nr	   r]   rN   r   r	   rQ   rH   s    r   rJ   rK      r^   r   
   c                V    [         R                  " [         R                  " U SSS9SSS9$ )Nr	   r]   rN   r
   rg   rQ   rH   s    r   rJ   rK          bhhrxxQV<Or      c                T    U R                   " SSS/[        SU R                  5      Q76 $ )Nr	   r
   r   rU   	transposeranger"   rH   s    r   rJ   rK      !    akk!Q=E!QVV,<=r      c                .    [         R                  " U SSS9$ NrZ   r]   rN   rQ   rH   s    r   rJ   rK          bhhqBV4r      c                V    [         R                  " [         R                  " U SSS9SSS9$ )NrZ   r]   rN   r	   rg   rQ   rH   s    r   rJ   rK          bhhrxxRf=Pr      c                V    [         R                  " [         R                  " U SSS9SSS9$ )NrZ   r]   rN   r
   rg   rQ   rH   s    r   rJ   rK      rw   r      c                V    [         R                  " [         R                  " U SSS9SSS9$ )NrZ   r]   rN   rU   rg   rQ   rH   s    r   rJ   rK      rw   r      c                .    [         R                  " U SSS9$ )Nr	   rg   rN   rQ   rH   s    r   rJ   rK      s    bhhqAF3r      c                V    [         R                  " [         R                  " U SSS9SSS9$ )Nr	   rg   rN   r]   rQ   rH   s    r   rJ   rK      rj   r      c                V    [         R                  " [         R                  " U SSS9SSS9$ )Nr	   rg   rN   r
   r]   rQ   rH   s    r   rJ   rK      rj   r      c                T    U R                   " SSS/[        SU R                  5      Q76 $ )Nr
   r   r	   rU   rm   rH   s    r   rJ   rK      rp   r      c                .    [         R                  " U SSS9$ NrZ   rg   rN   rQ   rH   s    r   rJ   rK      rt   r      c                V    [         R                  " [         R                  " U SSS9SSS9$ )NrZ   rg   rN   r	   r]   rQ   rH   s    r   rJ   rK      rw   r      c                V    [         R                  " [         R                  " U SSS9SSS9$ )NrZ   rg   rN   r
   r]   rQ   rH   s    r   rJ   rK      rw   r      c                V    [         R                  " [         R                  " U SSS9SSS9$ )NrZ   rg   rN   rU   r]   rQ   rH   s    r   rJ   rK      rw   r      c                     U S S 2S S 2S S S24   $ rY   r   rH   s    r   rJ   rK      s    a1dd
mr      c                T    U R                   " SSS/[        SU R                  5      Q76 $ )Nr   r
   r	   rU   rm   rH   s    r   rJ   rK      rp   r      c                     U S S 2S S S2S S 24   $ rY   r   rH   s    r   rJ   rK      s    a4R4
mr      c                H    [         R                  " U S S 2S S 2S S S24   SSS9$ )NrZ   rU   rM   rN   rQ   rH   s    r   rJ   rK          bhhqAtt}?r      c                     U S S S2S S 2S S 24   $ rY   r   rH   s    r   rJ   rK      s    a"a
mr      c                H    [         R                  " U S S S2S S 2S S 24   SSS9$ )NrZ   r	   rM   rN   rQ   rH   s    r   rJ   rK      s    bhhq2q!}?r      c                $    U S S S2S S S2S S S24   $ rY   r   rH   s    r   rJ   rK      s    a"ddDbD()r      c                H    [         R                  " U S S S2S S 2S S 24   SSS9$ )NrZ   rM   rN   rQ   rH   s    r   rJ   rK      s    bhhq2q!}@r       c                T    U R                   " SSS/[        SU R                  5      Q76 $ )Nr
   r	   r   rU   rm   rH   s    r   rJ   rK      rp   r   !   c                n    U R                   " SSS/[        SU R                  5      Q76 S S S2S S 2S S 24   $ Nr	   r
   r   rU   rZ   rm   rH   s    r   rJ   rK      0    akk!Q=E!QVV,<=ddAqjIr   c                p    U R                   " SSS/[        SU R                  5      Q76 S S S2S S S2S S 24   $ Nr
   r	   r   rU   rZ   rm   rH   s    r   rJ   rK      4    akk!Q=E!QVV,<=ddDbD!mLr   c                n    U R                   " SSS/[        SU R                  5      Q76 S S 2S S S2S S 24   $ r   rm   rH   s    r   rJ   rK      0    akk!Q=E!QVV,<=a2qjIr   c                H    [         R                  " U S S 2S S 2S S S24   SSS9$ rs   rQ   rH   s    r   rJ   rK          bhhqAtt}@r   c                r    U R                   " SSS/[        SU R                  5      Q76 S S S2S S S2S S S24   $ r   rm   rH   s    r   rJ   rK      9    akk!Q=E!QVV,<=ddDbD$B$>NOr   c                p    U R                   " SSS/[        SU R                  5      Q76 S S 2S S S2S S S24   $ r   rm   rH   s    r   rJ   rK      s4    akk!Q=E!QVV,<=a2ttmLr   c                n    U R                   " SSS/[        SU R                  5      Q76 S S 2S S 2S S S24   $ r   rm   rH   s    r   rJ   rK      0    akk!Q=E!QVV,<=aDbDjIr   c                H    [         R                  " U S S 2S S 2S S S24   SSS9$ )NrZ   r	   rg   rN   rQ   rH   s    r   rJ   rK      r   r   c                n    U R                   " SSS/[        SU R                  5      Q76 S S 2S S 2S S S24   $ Nr
   r   r	   rU   rZ   rm   rH   s    r   rJ   rK      r   r   c                T    U R                   " SSS/[        SU R                  5      Q76 $ )Nr	   r   r
   rU   rm   rH   s    r   rJ   rK      rp   r   c                n    U R                   " SSS/[        SU R                  5      Q76 S S S2S S 2S S 24   $ r   rm   rH   s    r   rJ   rK      r   r   c                H    [         R                  " U S S 2S S 2S S S24   SSS9$ r   rQ   rH   s    r   rJ   rK      r   r   c                n    U R                   " SSS/[        SU R                  5      Q76 S S 2S S S2S S 24   $ r   rm   rH   s    r   rJ   rK      r   r   c                p    U R                   " SSS/[        SU R                  5      Q76 S S S2S S S2S S 24   $ )Nr	   r   r
   rU   rZ   rm   rH   s    r   rJ   rK      r   r   c                r    U R                   " SSS/[        SU R                  5      Q76 S S S2S S S2S S S24   $ r   rm   rH   s    r   rJ   rK      r   r   )"   #   $   %   &   '   (   )   *   +   ,   -   .   /   )
ValueErrorr:   )cubeindextransformationss      r   transform_cuber      s4    OO9::6	;6 	
26 	
2	6
 	
26 	
%6 	
N6 	
%6 	
N6 	
26 	
N6 	O6 	=6  	4!6" 	P#6$ 	P%6& 	P'6* 	3+6, 	O-6. 	O/60 	=162 	4364 	P566 	P768 	P96< 	#=6> 	=?6@ 	#A6B 	?C6D 	#E6F 	?G6H 	)I6J 	@K6L 	=M6N 	IO6P MI@OLI?I=I@ILOk6Op !$))+..r   	keypointsc                N   UR                   S:X  a  U $ U SS2S4   SS2[        R                  4   nU SS2S4   SS2[        R                  4   nU SS2S4   SS2[        R                  4   nUSS2S4   nUSS2S4   nUSS2S4   nUSS2S4   nUSS2S4   n	USS2S4   n
X%:  X(:  -  X6:  -  X9:  -  XG:  -  XJ:  -  n[        R                  " USS9) nX   n[	        U5      S:X  a<  [        R
                  " / U R                  S	9R                  SU R                  S   5      $ U$ )
a  Filter out keypoints that are inside any of the 3D holes.

Args:
    keypoints (np.ndarray): Array of keypoints with shape (num_keypoints, 3+).
                           The first three columns are x, y, z coordinates.
    holes (np.ndarray): Array of holes with shape (num_holes, 6).
                       Each hole is represented as [z1, y1, x1, z2, y2, x2].

Returns:
    np.ndarray: Array of keypoints that are not inside any hole.

r   Nr
   r	   rU   rW   r[   )axis)dtype)	sizer$   newaxisanylenarrayr   reshapeshape)r   r;   kp_zkp_ykp_xhole_z1hole_y1hole_x1hole_z2hole_y2hole_x2inside_holevalid_keypointsresults                 r   filter_keypoints_in_holes3dr      sT    zzQ QT?1bjj=)DQT?1bjj=)DQT?1bjj=)D AqDkGAqDkGAqDkGAqDkGAqDkGAqDkG 
>	?	 >	 ?		
 >	  vvk22O 'F
6{axx)//2::1iooa>PQQMr   c                   US:X  d  [        U 5      S:X  a  U $ US-  S-   S-  nU R                  5       nU Vs/ s H  oSU   PM	     nnUSS2US   4   R                  5       nUSS2US   4   R                  5       nUS:X  a"  US   S-
  U-
  USS2US   4'   XtSS2US   4'   U$ US:X  a,  US   S-
  U-
  USS2US   4'   US   S-
  U-
  USS2US   4'   U$ US:X  a   XSS2US   4'   US   S-
  U-
  USS2US   4'   U$ s  snf )a  Rotate keypoints 90 degrees k times around the specified axes.

Args:
    keypoints (np.ndarray): Array of keypoints with shape (num_keypoints, 3+).
                           The first three columns are x, y, z coordinates.
    k (int): Number of times to rotate by 90 degrees.
    axes (tuple[int, int]): Axes to rotate around.
    volume_shape (tuple[int, int, int]): Shape of the volume (depth, height, width).

Returns:
    np.ndarray: Rotated keypoints with same shape as input.

r   rW   Nr	   r
   rU   )r   r:   )	r   rO   rP   volume_shaper   axdimscoords1coords2s	            r   keypoints_rot90r     s\   & 	AvY1$ a%1A^^F (,,ttD, QQZ %%'GQQZ %%'G 	Av"1gkW4q$q'z$q$q'z M 
a"1gkW4q$q'z"1gkW4q$q'z
 M	 
a$q$q'z"1gkW4q$q'zM# -s   C=c                   SUs=::  a  S:  d  O  [        S5      eU R                  5       nUSS2SS24   nUSS2/ SQ4   nXCSS2SS24'   UnUS:  a  US   S	-
  USS2S4   -
  USS2S4'   US-  nUS
:  a  [        X6SUS9nOUS:  a  [        USSUS9n[        XS
-
  SUS9nOUS:  aX  US:  a)  [        US	SUS9nUS   US	   US   4n	[        XS-
  SU	S9nO[        USSUS9nUS   US	   US   4n	[        XS-
  SU	S9nOWUS:  a)  [        US	SUS9nUS	   US   US   4n	[        XS-
  SU	S9nO([        USSUS9nUS	   US   US   4n	[        XS-
  SU	S9nUSS2SS24   nUSS2/ SQ4   nXGSS2SS24'   U$ )a  Transform keypoints according to the cube transformation specified by index.

Args:
    keypoints (np.ndarray): Array of keypoints with shape (num_keypoints, 3+).
                           The first three columns are x, y, z coordinates.
    index (int): Integer from 0 to 47 specifying which transformation to apply.
    volume_shape (tuple[int, int, int]): Shape of the volume (depth, height, width).

Returns:
    np.ndarray: Transformed keypoints with same shape as input.

r   rE   rF   NrU   )r
   r	   r   r   r
   r	   rW   rM   )rO   rP   r   rc   r]   r|   rq   rg   r   )r   r:   r   )
r   r   r   working_pointsxyzcurrent_shaperotation_indexr   temp
temp_shapes
             r   transform_cube_keypointsr   E  s(   $ OO9:: ^^%N BQB
C
al
C1bqb5 M {,Q/!3nQT6JJq!tRZN  ]jk	!	~m\ !);&Wcd	"	B">QVR_`D'*M!,<mA>NOJ$Ta-?f[efF">QVR_`D'*M!,<mA>NOJ$Tb-@v\fgF	"	~m\#A&a(8-:JK
 ")<6Xbc~m\#A&a(8-:JK
 ")<6Xbc BQB-C
al
C1bqb5MMr   )r   zlist[tuple[int, int]]r   zLiteral['center', 'random']r   zrandom.Randomreturn#tuple[int, int, int, int, int, int])r&   
np.ndarrayr'   r   r(   tuple[float, ...] | floatr   r   )r&   r   r1   r   r   r   )r&   r   r;   r   r<   r   r   r   )r   r   r   intr   r   )r   r   r;   r   r   r   )
r   r   rO   r   rP   ztuple[int, int]r   tuple[int, int, int]r   r   )r   r   r   r   r   r   r   r   )__doc__
__future__r   randomtypingr   numpyr$   "albumentations.augmentations.utilsr   $albumentations.core.type_definitionsr   r   r/   r8   rC   r   r   r   r   r   r   r   <module>r      s.   #    A F'#')' ' )	'T0000 %0 	0f9949 9(&F/R K 0 !0f--
- - '	-
 -` K CCC 'C 	C !Cr   