Ë
    ëÓ^jl"  ã                  ó"  — U d Z ddlmZ ddlZddlZddlZddlZddlmZ ddl	m
Z
mZ ddlmZ ddlmZmZmZ ddlmZ ddlZddlZdd	lmZ dd
lmZ  e«       ZerddlZddddœZdZded<   dd„Zdd„Z dd„Z! G d„ d«      Z"dd„Z#e
ddd„«       Z$y)zÏPrivate developer tools for testing and benchmarking RF-DETR.

These utilities are intended for internal use by developers and test suites. They are not part of the public API and may
change without notice.
é    )ÚannotationsN)Ú	Generator)ÚcontextmanagerÚsuppress)ÚPath)ÚTYPE_CHECKINGÚAnyÚLiteral)Úurlretrieve)ÚImage)Ú
get_loggerz0http://images.cocodataset.org/zips/train2017.zipz.http://images.cocodataset.org/zips/val2017.zipzFhttp://images.cocodataset.org/annotations/annotations_trainval2017.zip)Ú	train2017Úval2017r   iˆ  ÚintÚ_COCO_VAL_IMAGE_COUNTc                ór   — | j                  «       syt        d„ | j                  «       D «       «      t        k\  S )a�  Check whether the COCO val2017 image directory contains the expected number of JPEG files.

    Returns ``False`` for a missing or empty directory so callers can trigger a
    re-download without inspecting the directory manually.

    Args:
        images_dir: Path to the directory that should contain the val2017 images.

    Returns:
        ``True`` if *images_dir* exists and contains at least ``_COCO_VAL_IMAGE_COUNT``
        ``.jpg`` files, ``False`` otherwise.

    Raises:
        OSError: If *images_dir* exists but cannot be read (e.g. ``PermissionError``
            when the directory is not accessible, or ``FileNotFoundError`` on a
            TOCTOU race between the ``is_dir()`` check and ``iterdir()``).

    Examples:
        >>> import tempfile
        >>> with tempfile.TemporaryDirectory() as tmpdir:
        ...     _coco_val_images_complete(Path(tmpdir) / "val2017")
        False
    Fc              3  ó~   K  — | ]5  }|j                  «       sŒ|j                  j                  «       d k(  sŒ2d–— Œ7 y­w)z.jpgé   N)Úis_fileÚsuffixÚlower)Ú.0Úentrys     úc/var/www/ramen.bs-engineer-server.com/venv/lib/python3.12/site-packages/rfdetr/datasets/_develop.pyú	<genexpr>z,_coco_val_images_complete.<locals>.<genexpr>F   s-   è ø€ Òf�%°5·=±=µ?ÀuÇ|Á|×GYÑGYÓG[Ð_eÓGeŒAÑfùs   ‚=˜=¶=)Úis_dirÚsumÚiterdirr   )Ú
images_dirs    r   Ú_coco_val_images_completer    +   s7   € ð0 ×ÑÔØäÑf˜:×-Ñ-Ó/ÔfÓfÜ ñ	!ðó    c                ó€   — 	 | j                  «       xr | j                  «       j                  dkD  S # t        $ r Y yw xY w)a"  Check whether a file exists and contains at least one byte.

    Returns ``False`` for a missing or empty file so callers can trigger a
    re-download without inspecting the file manually.

    Args:
        path: Path to the file to check.

    Returns:
        ``True`` if *path* refers to an existing file with ``size > 0``,
        ``False`` otherwise.

    Examples:
        >>> import tempfile
        >>> with tempfile.TemporaryDirectory() as tmpdir:
        ...     _nonempty_file_exists(Path(tmpdir) / "missing.json")
        False
    r   F)r   ÚstatÚst_sizeÚOSError)Úpaths    r   Ú_nonempty_file_existsr'   K   s;   € ð&Ø�|‰|‹~Ò9 $§)¡)£+×"5Ñ"5¸Ñ"9Ð9øÜò Ùðús   ‚.1 ±	=¼=c                ó   — t         |    S )zCReturn the official COCO 2017 download URL for the requested asset.)Ú
_COCO_URLS)Úassets    r   Úget_coco_download_urlr+   d   s   € ä�eÑÐr!   c                  ó*   — e Zd ZdZddd„Zdd„Zd	d„Zy)
Ú_SimpleDatasetaH  Simple synthetic dataset for testing augmentations and training loops.

    Creates synthetic images with varying numbers of bounding boxes to test edge cases in augmentation pipelines,
    particularly the case where num_boxes=2 (which matches orig_size shape [2]).

    Implements the ``__len__`` / ``__getitem__`` protocol expected by ``torch.utils.data.DataLoader`` without inheriting
    from ``torch.utils.data.Dataset``, so importing this class does not pull in torch at module load time.

    Args:
        num_samples: Number of samples in the dataset.
        transforms: Optional transforms to apply (e.g., Compose of AlbumentationsWrapper).

    Examples:
        >>> from albumentations import HorizontalFlip
        >>> from torchvision.transforms.v2 import Compose
        >>> from rfdetr.datasets.transforms import AlbumentationsWrapper
        >>>
        >>> transforms = Compose([
        ...     AlbumentationsWrapper(HorizontalFlip(p=0.5)),
        ... ])
        >>> dataset = _SimpleDataset(num_samples=10, transforms=transforms)
        >>> image, target = dataset[0]
    Nc                ó    — || _         || _        y ©N)Únum_samplesÚ
transforms)Úselfr0   r1   s      r   Ú__init__z_SimpleDataset.__init__‚   s   € Ø&ˆÔØ$ˆ�r!   c                ó   — | j                   S r/   )r0   )r2   s    r   Ú__len__z_SimpleDataset.__len__†   s   € Ø×ÑÐr!   c           
     óB  — t        j                  dd«      }|dz  dz   }g }g }t        |«      D ]E  }d|dz  z   }d|dz  z   }|dz   }	|dz   }
|j                  |||	|
g«       |j                  |dz   «       ŒG t	        j
                  |t        j                  ¬	«      t	        j
                  |t        j                  ¬	«      t	        j
                  d
dg«      t	        j
                  d
dg«      t	        j
                  |g«      t	        j
                  dg|z  «      t	        j
                  dg|z  «      dœ}| j                  r| j                  ||«      \  }}t	        j                  t        j                  |«      «      j                  ddd«      j                  «       dz  }||fS )NÚRGB)é€  éà  é   r   é
   éd   é2   éP   )Údtyper9   r8   g      Y@r   )ÚboxesÚlabelsÚ	orig_sizeÚsizeÚimage_idÚareaÚiscrowdé   g     ào@)r   ÚnewÚrangeÚappendÚtorchÚtensorÚfloat32Úint64r1   Ú
from_numpyÚnpÚarrayÚpermuteÚfloat)r2   ÚidxÚimageÚ	num_boxesr@   rA   ÚiÚx1Úy1Úx2Úy2Útargets               r   Ú__getitem__z_SimpleDataset.__getitem__‰   sn  € ä—	‘	˜% Ó,ˆð ˜1‘W ‘Mˆ	àˆØˆÜ�yÓ!ò 	!ˆAØ�a˜#‘g‘ˆBØ�a˜"‘f‘ˆBØ�b‘ˆBØ�c‘ˆBØ�L‰L˜"˜b " bÐ)Ô*Ø�M‰M˜!˜a™%Õ ð	!ô —\‘\ %¬u¯}©}Ô=Ü—l‘l 6´·±Ô=ÜŸ™ s¨C jÓ1Ü—L‘L # s Ó,ÜŸ™ c UÓ+Ü—L‘L % ¨9Ñ!4Ó5Ü—|‘| Q C¨)¡OÓ4ñ
ˆð �?Š?Ø ŸO™O¨E°6Ó:‰MˆE�6ô × Ñ ¤§¡¨%£Ó1×9Ñ9¸!¸QÀÓB×HÑHÓJÈUÑRˆà�fˆ}Ðr!   )r;   N)r0   r   r1   z
Any | NoneÚreturnÚNone)r^   r   )rT   r   r^   z#tuple[torch.Tensor, dict[str, Any]])Ú__name__Ú
__module__Ú__qualname__Ú__doc__r3   r5   r]   © r!   r   r-   r-   i   s   „ ñô0%ó ô#r!   r-   c           	     óÞ  — |j                  dd¬«       || j                  dd«      d   z  }t        j                  d| «       t	        | t        |«      «       t        j                  d|«       |j                  «       }t        j                  t        |«      d«      5 }|j                  «       D ]Ü  }|j                  sŒ||j                  z  j                  «       }|j                  |«      st        d	|j                  ›�«      ‚|j                  «       r|j                  dd¬«       Œz|j                  j                  dd¬«       |j                  |d«      5 }t        |d
«      5 }t!        j"                  ||«       ddd«       ddd«       ŒÞ 	 ddd«       t%        t&        «      5  |j)                  «        ddd«       y# 1 sw Y   ŒExY w# 1 sw Y   �Œ'xY w# 1 sw Y   ŒKxY w# 1 sw Y   yxY w)zÇDownload a zip file and safely extract it into the destination directory.

    Args:
        url: URL to a zip archive.
        dest_dir: Directory where the archive will be saved and extracted.
    T©ÚparentsÚexist_okú/r   éÿÿÿÿzDownloading %s ...zExtracting %s ...Úrz"Unsafe path detected in ZIP file: ÚwbN)ÚmkdirÚrsplitÚloggerÚinfor   ÚstrÚresolveÚzipfileÚZipFileÚinfolistÚfilenameÚis_relative_toÚRuntimeErrorr   ÚparentÚopenÚshutilÚcopyfileobjr   ÚFileNotFoundErrorÚunlink)	ÚurlÚdest_dirÚzip_pathÚdest_dir_resolvedÚzfÚmemberÚtarget_pathÚsrcÚdsts	            r   Ú_download_and_extractrˆ   ¯   s­  € ð ‡N�N˜4¨$€NÔ/Ø˜#Ÿ*™* S¨!Ó,¨RÑ0Ñ0€HÜ
‡K�KÐ$ cÔ*Ü�”S˜“]Ô#Ü
‡K�KÐ# XÔ.Ø ×(Ñ(Ó*ÐÜ	�‰œ˜X›¨Ó	,ð 1°Ø—k‘k“mò 	1ˆFØ—?’?ØØ,¨v¯©Ñ>×GÑGÓIˆKØ×-Ñ-Ð.?Ô@Ü"Ð%GÈÏÉÐGZÐ#[Ó\Ð\Ø�}‰}ŒØ×!Ñ!¨$¸Ð!Õ>à×"Ñ"×(Ñ(°ÀÐ(ÔEØ—W‘W˜V SÓ)ð 1¨S´$°{ÀDÓ2Ið 1ÈSÜ×&Ñ& s¨CÔ0÷1÷ 1ð 1ñ	1÷1ô 
Ô#Ó	$ñ Ø�‰Ô÷ð ÷1ð 1ú÷ 1ñ 1ú÷1ð 1ú÷ð úsI   ÂB:GÅG
Å#F>	Å:G
Æ
GÆ$G#Æ>GÇG
Ç
GÇGÇG Ç#G,c              #  ó¼  K  — | j                   j                  dd¬«       t        j                  «       }	 	 t        j                  | t        j
                  t        j                  z  t        j                  z  «      }t        j                  |«       	 	 d–— t        t        «      5  t        j                  | «       ddd«       y# t        $ r@ t        j                  «       |z
  |kD  rt        d| › �«      ‚t        j                  |«       Y nw xY wŒÝ# 1 sw Y   yxY w# t        t        «      5  t        j                  | «       ddd«       w # 1 sw Y   w xY wxY w­w)aæ  Provide a simple cross-process lock using an exclusive lock file.

    Args:
        lock_path: Path to the lock file used for mutual exclusion.
        timeout_s: Maximum time in seconds to wait for the lock.
        poll_s: Sleep interval in seconds between lock attempts.

    Yields:
        None. The caller runs inside the locked region.

    Raises:
        TimeoutError: If the lock cannot be acquired within the timeout.

    Note:
        Lock identity is file existence (``O_CREAT | O_EXCL``), not a held file descriptor.
        A SIGKILL-terminated process will leak the lock file until ``timeout_s`` expires.
        If all worker processes have exited but the lock persists, remove it manually:
        ``rm <lock_path>``.
    Trf   zTimed out waiting for lock: N)ry   rm   ÚtimeÚosrz   ÚO_CREATÚO_EXCLÚO_WRONLYÚcloseÚFileExistsErrorÚTimeoutErrorÚsleepr   r}   r~   )Ú	lock_pathÚ	timeout_sÚpoll_sÚstartÚfds        r   Ú_download_lockr˜   Í   s  è ø€ ð* ×Ñ×Ñ 4°$ÐÔ7Ü�I‰I‹K€EØ
ð	ä—‘˜¤B§J¡J´·±Ñ$:¼R¿[¹[Ñ$HÓIˆBÜ�H‰H�RŒLØð
!Ûô Ô'Ó(ñ 	!Ü�I‰I�iÔ ÷	!ð 	!øô ò 	Ü�y‰y‹{˜UÑ" YÒ.Ü"Ð%AÀ)ÀÐ#MÓNÐNÜ�J‰J�vÖð	úð ÷	!ð 	!ûŒXÔ'Ó(ñ 	!Ü�I‰I�iÔ ÷	!÷ 	!ñ 	!ÿsr   ‚3E¶AC ÂEÂD ÂEÂ&DÂ<	EÃADÄEÄDÄEÄDÄEÄEÄ.EÅ	EÅEÅEÅE)r   r   r^   Úbool)r&   r   r^   r™   )r*   z.Literal['train2017', 'val2017', 'annotations']r^   rq   )r   rq   r€   r   r^   r_   )g     À‚@g      à?)r“   r   r”   rS   r•   rS   r^   zGenerator[None, Any, None])%rc   Ú
__future__r   r‹   r{   rŠ   rs   Úcollections.abcr   Ú
contextlibr   r   Úpathlibr   Útypingr   r	   r
   Úurllib.requestr   ÚnumpyrP   rK   ÚPILr   Úrfdetr.util.loggerr   ro   r)   r   Ú__annotations__r    r'   r+   r-   rˆ   r˜   rd   r!   r   ú<module>r¤      sœ   ðòõ #ã 	Û Û Û Ý %ß /Ý ß .Ñ .Ý &ã Û Ý å )á	‹€áÛð DØ?Ø[ñ€
ð
 "Ð �sÓ !óó@ó2÷
Cñ CóLð< ó%!ó ñ%!r!   