Ë
    ëÓ^jSH  ã            	       ó&  — d Z ddlZddlZddlmZ ddlmZ ddlmZ  e«       Z	dZ
deded	dfd
„Zddededed	efd„Zded	efd„Zdeej"                  e   z  d	dfd„Zdeeef   d	eeef   fd„Zdeeef   ded	eeef   fd„Zdeeef   ded	dfd„Zy)z"Checkpoint and state-dict helpers.é    N)ÚOrderedDict)ÚAny)Ú
get_logger)Ú
state_dictÚglobal_stepzpytorch-lightning_versionÚloopsÚoptimizer_statesÚlr_schedulersÚckpt_patch_sizeÚmodel_patch_sizeÚreturnc                 ó&   — t        d| › d|› d�«      ‚)uH  Raise a descriptive ValueError for a patch_size incompatibility.

    Args:
        ckpt_patch_size: patch_size recorded in (or inferred from) the checkpoint.
        model_patch_size: patch_size the current model is configured with.

    Raises:
        ValueError: Always â€” describes the mismatch and how to resolve it.
    z+The checkpoint was trained with patch_size=z(, but the current model uses patch_size=zë. The checkpoint is incompatible with this model architecture. To resolve this, either instantiate/configure the model with the checkpoint's patch_size or use a checkpoint that was trained with the same patch_size as the current model.)Ú
ValueError)r   r   s     úf/var/www/ramen.bs-engineer-server.com/venv/lib/python3.12/site-packages/rfdetr/utilities/state_dict.pyÚ_raise_patch_size_mismatchr      s1   € ô Ø
5°oÐ5Fð GØ&Ð'ð ([ð	[óð ó    ÚargsÚfieldÚdefaultc                 ó`   — t        | t        «      r| j                  ||«      S t        | ||«      S )ad  Get a field from checkpoint ``"args"``, handling both dict and attribute access.

    New checkpoints (PTL training stack) store ``"args"`` as a plain ``dict`` (via ``TrainConfig.model_dump()``).
    Legacy checkpoints (pre-PTL engine or the pre-release PTL code) stored it as a ``Namespace``-like object.  This
    helper abstracts both so callers do not need to branch on the type.

    Args:
        args: The ``checkpoint["args"]`` value.
        field: Field name to retrieve.
        default: Value returned when the field is absent.

    Returns:
        The field value, or ``default`` if not found.
    )Ú
isinstanceÚdictÚgetÚgetattr)r   r   r   s      r   Ú_ckpt_args_getr   /   s.   € ô �$œÔØ�x‰x˜˜wÓ'Ð'Ü�4˜ Ó(Ð(r   Úepochc                 óÎ   — | dz   }dddddœ}ddddœ}dddœ}||||dœ}i ddii |¥i |¥ddœi |¥i |¥d	œi d
i |¥i |¥d	œi |¥i |¥d	œdœii i |¥i |¥d	œi i |¥i |¥ddœi |¥i |¥d	œdœS )u�  Build a minimal ``fit_loop`` state dict that restores the epoch counter.

    ``BestModelCallback`` stores ``trainer.current_epoch`` as ``"epoch"`` in the checkpoint.  That value is captured
    during ``on_validation_end``, which fires *before* the loop's epoch-end hooks increment the counter.  To resume
    training *after* that epoch, PTL's epoch-progress counter must be set to ``epoch + 1`` so that
    ``trainer.current_epoch == epoch + 1`` when the new ``trainer.fit()`` call begins.

    Optimizer and scheduler states are intentionally omitted â€” loading a ``.pth`` file starts a fresh optimizer for the
    new training phase.

    Args:
        epoch: The ``"epoch"`` value from the checkpoint (``trainer.current_epoch``
            at the time of ``on_validation_end``).

    Returns:
        A ``fit_loop`` state dict compatible with :meth:`pytorch_lightning.loops._FitLoop.load_state_dict`.
    é   r   )ÚreadyÚstartedÚ	processedÚ	completed)r   r    r"   )r   r"   Ú_batches_that_steppedF)ÚtotalÚcurrentÚis_last_batch)r$   r%   Ú	optimizer)ÚstepÚ	zero_grad)r   zepoch_loop.state_dictzepoch_loop.batch_progresszepoch_loop.scheduler_progressz,epoch_loop.automatic_optimization.state_dictz0epoch_loop.automatic_optimization.optim_progressz)epoch_loop.manual_optimization.state_dictz2epoch_loop.manual_optimization.optim_step_progresszepoch_loop.val_loop.state_dictz"epoch_loop.val_loop.batch_progressÚepoch_progress© )r   ÚnÚzero4Úzero3Úzero2Ún4s         r   Ú_make_fit_loop_stater1   C   s  € ð$ 	�‰	€AØ A°AÀAÑF€EØ A°AÑ6€EØ aÑ(€EØ °ÀÑ	C€BàØ"9¸1Ð!=à˜�YØ ˜%�yØ"ñ&
ð ˜�YØ ˜%�yñ*
ð 9;àà& ˜YØ( %˜yñð
 ' ˜YØ( %˜yññ	ð=
ð 68à˜�YØ ˜%�yñ?
ð +-à˜�YØ ˜%�yØ"ñ/
ð ˜�VØ˜"�vñ
ñI(ð (r   Ú
checkpointc                 ó   — ddl }|j                  | dd¬«      }|d   |d   dœ}d	|v r|d	   |d	<   d
|v r|d
   |d
<   t        D ]  }||v sŒ||   ||<   Œ d|v r|d   }dD ]  }||vsŒdi i||<   Œ t        j                  j                  t        j                  j                  t        j                  | «      «      «      }t        j                  |d¬«      5 }|j                  }	ddd«       	 |j                  |	«       t        j                  |	| «       t        j                  j                  |	«      rt        j                  |	«       yy# 1 sw Y   ŒhxY w# t        j                  j                  	«      rt        j                  |	«       w w xY w)aÉ  Strip a checkpoint file down to ``model``, ``args``, and PTL-compatible keys.

    Preserves ``model_name`` (when present) so that ``RFDETR.from_checkpoint()`` can still resolve the model class from
    the stripped file.  Also preserves ``rfdetr_version`` (when present) for provenance tracking.

    Also preserves ``state_dict``, ``global_step``, ``pytorch-lightning_version``, ``loops``, ``optimizer_states``, and
    ``lr_schedulers`` when present so the stripped checkpoint can still be used directly with
    ``trainer.fit(ckpt_path=...)``.

    Overwrites the file atomically so a partial write cannot corrupt it.

    Args:
        checkpoint: Path to the ``.pth`` checkpoint file to strip in place.
    r   NÚcpuF)Úmap_locationÚweights_onlyÚmodelr   )r7   r   Ú
model_nameÚrfdetr_versionr   )Úvalidate_loopÚ	test_loopr   )ÚdirÚdelete)ÚtorchÚloadÚ_PTL_COMPAT_KEYSÚosÚpathÚdirnameÚabspathÚfspathÚtempfileÚNamedTemporaryFileÚnameÚsaveÚreplaceÚexistsÚremove)
r2   r>   r   Únew_state_dictÚkeyr   Úloop_keyÚcheckpoint_dirÚtmp_fileÚtmp_paths
             r   Ústrip_checkpointrS   …   s„  € ó ð —‘˜J°UÈ�ÓO€Jà˜GÑ$Ø˜6Ñ"ñ€Nð
 �zÑ!Ø'1°,Ñ'?ˆ�|Ñ$à˜:Ñ%Ø+5Ð6FÑ+GˆÐ'Ñ(äò 2ˆØ�*ÒØ",¨S¡/ˆN˜3Òð2ð �.Ñ Ø˜wÑ'ˆØ6ò 	5ˆHØ˜uÒ$Ø#/°Ð"4��h’ð	5ô —W‘W—_‘_¤R§W¡W§_¡_´R·Y±Y¸zÓ5JÓ%KÓL€NÜ	×	$Ñ	$¨ÀÔ	Fð !È(Ø—=‘=ˆ÷!ð Ø�
‰
�> 8Ô,ä
�
‰
�8˜ZÔ(ä�7‰7�>‰>˜(Ô#Ü�I‰I�hÕð $÷!ð !ûô �7‰7�>‰>˜(Ô#Ü�I‰I�hÕð $ús   ÃE
Ã,(E Å
EÅ7Fr   c                 ón   — t        «       }| j                  «       D ]  \  }}|dd dk(  r|dd }|||<   Œ |S )a
  Remove the ``module.`` prefix added by ``DataParallel`` / ``DistributedDataParallel``.

    Args:
        state_dict: State dict potentially containing ``module.``-prefixed keys.

    Returns:
        New ``OrderedDict`` with ``module.`` stripped from all keys.
    Né   zmodule.)r   Úitems)r   rM   ÚkÚvs       r   Úclean_state_dictrY   ¾   sR   € ô !“]€NØ× Ñ Ó"ò ‰ˆˆ1ØˆRˆaˆ5�IÒØ�!�"�ˆAØˆ�qÒðð Ðr   r7   c                 ó  — t        |d«      r|j                  d   nd}|€| S t        |dd«      du}t        t        |dd«      «      xs |}|s| S t	        d„ | D «       «      r| S | j                  «       D ��ci c]  \  }}|j                  d«      sŒ||“Œ }}}|s| S t        j                  d	t        |«      «       |j                  «       D ]+  \  }}|j                  dd
d«      }|j                  «       | |<   Œ- | S c c}}w )a7  Clone backbone projector weights into ``cross_attn_projector`` for dual-projector models.

    Older checkpoints can contain only ``backbone.0.projector.*`` keys. Dual-projector models expect an additional
    ``backbone.0.cross_attn_projector.*`` branch; this helper seeds it by cloning projector weights when missing.

    Args:
        state_dict: Checkpoint model-state dictionary (mutated in place).
        model: Instantiated model used to detect whether dual projector mode is active.

    Returns:
        The same ``state_dict`` object for convenience.
    Úbackboner   NÚcross_attn_projectorÚdual_projectorFc              3   ó>   K  — | ]  }|j                  d «      –— Œ y­w)ú backbone.0.cross_attn_projector.N)Ú
startswith)Ú.0rN   s     r   ú	<genexpr>z0remap_projector_to_cross_attn.<locals>.<genexpr>æ   s   è ø€ Ò
TÀ#ˆ3�>‰>Ð<×=Ñ
Tùs   ‚zbackbone.0.projector.z`Cloning %d backbone projector key(s) into cross_attn_projector for dual-projector compatibility.r_   r   )Úhasattrr[   r   ÚboolÚanyrV   r`   ÚloggerÚinfoÚlenrJ   Úclone)	r   r7   r[   Úhas_cross_attn_projectorÚdual_projector_enabledrN   ÚvalueÚprojector_keysÚnew_keys	            r   Úremap_projector_to_cross_attnro   Ï   s  € ô %,¨E°:Ô$>ˆu�~‰~˜aÒ ÀD€HØÐØÐô  ' xÐ1GÈÓNÐVZÐZÐÜ!¤'¨(Ð4DÀeÓ"LÓMÒiÐQiÐÙ!ØÐä
Ñ
TÈÔ
TÔTØÐà3=×3CÑ3CÓ3E×q¡Z S¨%ÈÏÉÐXoÕIp�c˜5‘jÐq€NÑqÙØÐä
‡K�KØjÜˆNÓôð %×*Ñ*Ó,ò ,‰
ˆˆUØ—+‘+Ð5Ð7YÐ[\Ó]ˆØ#Ÿk™k›mˆ
�7Òð,ð Ðùó rs   Á6C;ÂC;Ú
model_argsc                 ó¸  — | j                  di «      j                  dd«      }|�l|j                  d   }t        |dd«      }|�N||dz   k7  rF|dz   |k  rt        j	                  d|dz
  ||«       n"t        j	                  d|dz
  ||dz
  |dz
  «       | j                  d	«      }d}|�t        |d
«      }|€yd}| j                  di «      j                  |«      }t        |dd«      }	|	�Gt        |	«      dk(  r9|	d   |	d   k(  r.t        |	d   «      }
t        |d
d«      }|�|
|k7  rt        |
|«       d	| vry| d	   }t        |d«      }t        |dd«      }|�|�||k7  r|rt        d«      ‚t        d«      ‚t        |d
«      }t        |d
d«      }|�|�||k7  rt        ||«       t        |d«      }t        |dd«      }|�!|�||k7  r|rt        d«      ‚t        d«      ‚yyy)uy  Validate that a checkpoint is compatible with the model configuration.

    Checks for mismatches in ``segmentation_head`` and ``patch_size`` between the checkpoint's saved training arguments
    and the current model configuration. Raises a descriptive :class:`ValueError` before ``load_state_dict`` fires so
    that users receive a clear, actionable message instead of a cryptic tensor size mismatch error.

    If either side is missing an attribute (e.g. a legacy checkpoint saved before
        ``segmentation_head`` or ``patch_size`` was added to ``args``), that specific
        check is skipped silently â€” this preserves backwards compatibility with pre-existing checkpoints.

    Args:
        checkpoint: Loaded checkpoint dictionary, expected to contain an optional
            ``"args"`` key with training namespace attributes or a plain dict.
        model_args: Namespace (e.g. ``types.SimpleNamespace``) with at least
            ``segmentation_head`` and ``patch_size`` attributes describing the current model.

    Raises:
        ValueError: If ``segmentation_head`` or ``patch_size`` in the checkpoint
            args do not match those of the model, or if the ``patch_size`` inferred from the DINOv2 projection weight
            shape differs from ``model_args.patch_size`` when no explicit ``args.patch_size`` is present.

    Note:
        This helper does not mutate ``model_args``. It emits ``logger.warning`` (not an exception) for class-count
        mismatches so that callers can still proceed with reinitialization or weight loading.

        When ``"args"`` is absent or ``args.patch_size`` is not set, a fallback infers ``patch_size`` from the DINOv2
        patch-embedding projection weight shape (key
        ``backbone.0.encoder.encoder.embeddings.patch_embeddings.projection.weight``). This fallback **can raise**
        :class:`ValueError` on a mismatch, providing a clear error before the cryptic :class:`RuntimeError` from
        :meth:`~torch.nn.Module.load_state_dict` would otherwise fire. For all other attributes (e.g.
        ``segmentation_head``), if either side is missing, that check is skipped silently â€” preserving backward
        compatibility.

        Two class-count scenarios are distinguished:

        * Backbone pretrain: the checkpoint head was trained with more classes
          than the current ``model_args.num_classes``. In this case the detection head is typically reinitialized or
          trimmed externally to match the configured number of classes.
        * Fine-tuned checkpoint: the checkpoint head was trained with fewer
          classes than the current ``model_args.num_classes``. If you intend to reuse the checkpoint's classification
          head as-is, set ``model_args.num_classes`` to ``ckpt_num_classes - 1`` (the value reported in the warning)
          before loading the state dict to align the configuration and silence the warning.
    r7   zclass_embed.biasNr   Únum_classesr   zrCheckpoint has %d classes but model is configured for %d. The detection head will be re-initialized to %d classes.zŠCheckpoint has %d classes but model is configured for %d. Using checkpoint class count (%d). Pass num_classes=%d to suppress this warning.r   Ú
patch_sizezHbackbone.0.encoder.encoder.embeddings.patch_embeddings.projection.weightÚshapeé   é   é   éÿÿÿÿÚsegmentation_headz»The checkpoint was trained with a segmentation head, but the current model does not have one. Load the weights into a segmentation model (e.g. RFDETRSegNano) instead of a detection model.z±The current model has a segmentation head, but the checkpoint was trained without one. Load the weights into a detection model (e.g. RFDETRNano) instead of a segmentation model.Úuse_grouppose_keypointsz»The checkpoint was trained with a keypoint head, but the current model does not have one. Load the weights into a keypoint model (e.g. RFDETRKeypointPreview) instead of a detection model.z©The current model has a keypoint head, but the checkpoint was trained without one. Load the weights into a detection model (e.g. RFDETRNano) instead of a keypoint model.)
r   rt   r   rf   Úwarningr   rh   Úintr   r   )r2   rp   Úckpt_class_biasÚckpt_num_classesÚmodel_num_classesÚ
_ckpt_argsÚ_ckpt_patch_size_from_argsÚ_patch_proj_keyÚ_ckpt_proj_wÚ_ckpt_proj_shapeÚ_inferred_psÚ	_model_psÚ	ckpt_argsÚckpt_segmentation_headÚmodel_segmentation_headr   r   Úckpt_keypoint_headÚmodel_keypoint_heads                      r   Ú!validate_checkpoint_compatibilityrŒ   ø   s–  € ðZ !—n‘n W¨bÓ1×5Ñ5Ð6HÈ$ÓO€OØÐ"Ø*×0Ñ0°Ñ3ÐÜ(/°
¸MÈ4Ó(PÐØÐ(Ð-=ÐARÐUVÑAVÒ-VØ  1Ñ$Ð'7Ò7ä—‘ðOà$ qÑ(Ø%Ø%õô —‘ðDð % qÑ(Ø%Ø$ qÑ(Ø$ qÑ(ôð$ —‘ Ó'€JØ-1ÐØÐÜ%3°JÀÓ%MÐ"à!Ð)ØdˆØ!—~‘~ g¨rÓ2×6Ñ6°ÓGˆÜ" <°¸$Ó?ÐØÐ'¬CÐ0@Ó,AÀQÒ,FÐK[Ð\]ÑK^ÐbrÐstÑbuÒKuÜÐ/°Ñ3Ó4ˆLÜ$+¨J¸ÀdÓ$KˆIØÐ$¨¸Ò)BÜ*¨<¸ÔCØ�ZÑØà˜6Ñ"€IÜ*8¸ÐDWÓ*XÐÜ+2°:Ð?RÐTXÓ+YÐð 	Ð*Ø#Ð/Ø"Ð&=Ò=á!Üðpóð ô
 ðmóð ô
 #1°¸LÓ"I€OÜ#*¨:°|ÀTÓ#JÐØÐ"Ð'7Ð'CÈÐ[kÒHkÜ" ?Ð4DÔEä&4°YÐ@YÓ&ZÐÜ'.¨zÐ;TÐVZÓ'[ÐàÐ%Ð*=Ð*IÐN`ÐdwÒNwÙÜðtóð ô
 ðióð ð OxÐ*IÐ%r   )N)Ú__doc__rA   rF   Úcollectionsr   Útypingr   Úrfdetr.utilities.loggerr   rf   r@   r|   r   Ústrr   r   r1   ÚPathLikerS   rY   Úobjectro   rŒ   r+   r   r   ú<module>r”      s  ðñ )ã 	Û Ý #Ý å .á	‹€ðÐ ð°ð Àsð Ètó ñ$)˜ð ) Sð )°3ð )À#ó )ð(? ð ?¨ó ?ðD6   r§{¡{°3Ñ'7Ñ!7ð 6 ¸Dó 6 ðr  c¨3 h¡ð °KÀÀSÀÑ4Ió ð"&¨d°3¸°8©nð &ÀVð &ÐPTÐUXÐZ]ÐU]ÑP^ó &ðRF°$°s¸C°x±.ð FÈcð FÐVZô Fr   