Ë
    ëÓ^j_‚  ã                  óâ   — d 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rddlm	Z	 ddl
Z
ddlmZmZ ddlmZ dd	lmZmZ dd
lmZ ddlmZ ddlmZmZ  e«       Z G d„ de«      Z G d„ de«      Zy)zUBest-model checkpointing and early stopping callbacks for RF-DETR Lightning training.é    )ÚannotationsN)ÚPath)ÚTYPE_CHECKING)ÚAny)ÚLightningModuleÚTrainer)Ú__version__)ÚEarlyStoppingÚModelCheckpoint)Ú
get_logger)Úget_version)Ú_make_fit_loop_stateÚstrip_checkpointc                  ó  ‡ — e Zd ZdZdZ	 	 	 	 	 d	 	 	 	 	 	 	 	 	 	 	 	 	 dˆ fd„Ze	 	 d	 	 	 	 	 	 	 	 	 	 	 dd„«       Zedd„«       Ze	 	 	 	 	 	 dd„«       Z	e	 d	 	 	 	 	 dd„«       Z
edd„«       Zdˆ fd	„Zdˆ fd
„Zdd„Zdˆ fd„Zdd„Zˆ xZS )ÚBestModelCallbackaS  Track best validation mAP and save best checkpoints during training.

    Extends :class:`pytorch_lightning.callbacks.ModelCheckpoint` to save stripped ``{model, args, epoch}`` ``.pth``
    files (instead of full ``.ckpt`` files) and to track a separate EMA checkpoint in parallel.

    At the end of training the overall winner (regular vs EMA, strict ``>`` for EMA) is copied to
    ``checkpoint_best_total.pth`` and optimizer/scheduler state is stripped via
    :func:`rfdetr.util.misc.strip_checkpoint`.

    Checkpoints are only updated on validation epochs where the monitor metric is actually logged.  On non-eval epochs
    (when ``eval_interval > 1`` causes COCO evaluation to be skipped) the callback is a no-op.

    ``state_dict()`` and ``load_state_dict()`` are overridden to persist ``_best_ema`` in the Lightning callback state,
    ensuring that ``trainer.fit(ckpt_path=...)`` resumes EMA high-water-mark tracking from the correct value.

    Args:
        output_dir: Directory where checkpoint files are written.
        monitor_regular: Metric key for the regular model mAP.
        monitor_ema: Metric key for the EMA model mAP.  ``None`` disables EMA tracking.
        run_test: If ``True``, run ``trainer.test()`` on the best model at the end of training.
        skip_best_epochs: Ignore the first N epochs (0..N-1) when tracking
            best regular and EMA checkpoints.  Useful when fine-tuning from ``pretrain_weights``: the pretrained model's
            epoch-0 mAP can artificially dominate best-checkpoint selection before training adapts to the new dataset.
        smooth_alpha: Exponential-moving-average smoothing factor in ``[0.0, 1.0)`` applied to the regular monitor
            metric before checkpoint comparison.  ``0.0`` (default) disables smoothing and keeps legacy behaviour:
            ``trainer.callback_metrics[monitor_regular]`` is consumed as-is by the parent
            :class:`~pytorch_lightning.callbacks.ModelCheckpoint`.  ``smooth_alpha > 0`` maintains an internal EMA
            state ``self._smoothed_regular = alpha * self._smoothed_regular + (1 - alpha) * raw`` and temporarily
            substitutes the smoothed value into ``trainer.callback_metrics`` for the duration of the parent's
            improvement check; the original raw value is always restored before returning so what gets logged to
            ``metrics.csv`` is unaffected.  Useful for noisy metrics (e.g. keypoint mAP under NLL-Cholesky losses) where
            raw per-epoch swings can lock the best checkpoint to an early local peak.  The EMA accumulator is updated
            on every validation epoch including epochs within the ``skip_best_epochs`` window so the smoothed value
            is pre-warmed by the first eligible comparison.

    Examples:
        Skip the first 3 epochs so pretrained weights do not dominate:

        >>> import tempfile
        >>> from rfdetr.training.callbacks.best_model import BestModelCallback
        >>> with tempfile.TemporaryDirectory() as tmp:
        ...     cb = BestModelCallback(output_dir=tmp, skip_best_epochs=3)
        ...     cb._skip_best_epochs
        3
    z.pthc                ó  •— t         ‰| �  |d|dddddd¬«	       || _        || _        d| _        t        |«      | _        t        |t        «      st        |t        «      st        d«      ‚|dk  rt        d	«      ‚|| _        t        |t        «      st        |t        t        f«      st        d
«      ‚t        j                  |«      r
|dk  s|dk\  rt        d«      ‚t        |«      | _        d| _        d| _        d | _        y )NÚcheckpoint_best_regularÚmaxé   F)	ÚdirpathÚfilenameÚmonitorÚmodeÚ
save_top_kÚsave_on_train_epoch_endÚverboseÚauto_insert_metric_nameÚenable_version_counterç        ú/skip_best_epochs must be a non-negative integerr   ú3skip_best_epochs must be greater than or equal to 0z*smooth_alpha must be a float in [0.0, 1.0)ç      ð?z"smooth_alpha must be in [0.0, 1.0))ÚsuperÚ__init__Ú_monitor_emaÚ	_run_testÚ	_best_emar   Ú_output_dirÚ
isinstanceÚboolÚintÚ	TypeErrorÚ
ValueErrorÚ_skip_best_epochsÚfloatÚmathÚisfiniteÚ_smooth_alphaÚ_smoothed_regularÚ_best_raw_regularÚ_current_pl_module)ÚselfÚ
output_dirÚmonitor_regularÚmonitor_emaÚrun_testÚskip_best_epochsÚsmooth_alphaÚ	__class__s          €úo/var/www/ramen.bs-engineer-server.com/venv/lib/python3.12/site-packages/rfdetr/training/callbacks/best_model.pyr$   zBestModelCallback.__init__O   s	  ø€ ô 	‰ÑØØ.Ø#ØØØ$)ØØ$)Ø#(ð 	ô 
	
ð (ˆÔØ!ˆŒØ #ˆŒÜ 
Ó+ˆÔÜÐ&¬Ô-´ZÐ@PÔRUÔ5VÜÐMÓNÐNØ˜aÒÜÐRÓSÐSØ!1ˆÔÜ�l¤DÔ)´¸LÌ3ÔPUÈ,Ô1WÜÐHÓIÐIÜ�}‰}˜\Ô*¨l¸SÒ.@ÀLÐTWÒDWÜÐAÓBÐBÜ$)¨,Ó$7ˆÔð ),ˆÔð ),ˆÔà:>ˆÕó    c           
     ó  — | ||j                   | j                  «       D ��ci c]  \  }}d|› �|“Œ c}}|j                  t        t	        |j                   «      di idi idœg g dœ	}|�||d<   |�||d<   t        «       }|�||d<   |S c c}}w )a~  Build a PTL-compatible RF-DETR checkpoint payload.

        Args:
            model_state_dict: Model weights with raw (non-prefixed) keys.
            args_dict: Serialized training args/config payload.
            trainer: Active Lightning trainer providing epoch/step counters.
            model_name: Name of the model class (e.g. ``"RFDETRLarge"``).
            model_config_dict: Serialized architecture config needed to reconstruct schema-dependent models.

        Returns:
            Checkpoint dictionary that supports ``Trainer.fit(ckpt_path=...)`` while intentionally omitting
            optimizer/scheduler states.
        zmodel.Ú
state_dict)Úfit_loopÚvalidate_loopÚ	test_loop)	ÚmodelÚargsÚepochrA   Úglobal_stepzpytorch-lightning_versionÚloopsÚoptimizer_statesÚlr_schedulersÚ
model_nameÚmodel_configÚrfdetr_version)Úcurrent_epochÚitemsrH   Úptl_versionr   r   )	Úmodel_state_dictÚ	args_dictÚtrainerrL   Úmodel_config_dictÚkÚvÚpayloadÚversions	            r>   Ú_build_checkpoint_payloadz+BestModelCallback._build_checkpoint_payload|   s¿   € ð, &ØØ×*Ñ*à7G×7MÑ7MÓ7O×P©t¨q°!˜V A 3˜<¨™?ÓPØ"×.Ñ.Ü)4ä0°×1FÑ1FÓGð #/°Ð!3Ø*¨BÐ/ñð !#Øñ'&
ˆð. Ð!Ø$.ˆG�LÑ!ØÐ(Ø&7ˆG�NÑ#ô “-ˆØÐØ(/ˆGÐ$Ñ%Øˆùó9 Qs   ¡Bc                ó´   — t        | j                  dd«      }t        |t        j                  j
                  «      r|n| j                  }|j                  «       S )a	  Resolve live model weights from the active Lightning module.

        Args:
            pl_module: The ``RFDETRModelModule`` being trained.

        Returns:
            State dict from the live, non-EMA model, unwrapped from ``torch.compile`` when needed.
        Ú	_orig_modN)ÚgetattrrE   r)   ÚtorchÚnnÚModulerA   )Ú	pl_moduleÚ_origÚraws      r>   Ú_get_live_model_state_dictz,BestModelCallback._get_live_model_state_dict´   s?   € ô ˜	Ÿ™¨°dÓ;ˆÜ! %¬¯©¯©Ô9‰e¸y¿¹ˆØ�~‰~ÓÐr?   c                óN  — | j                   D ])  }t        |dd«      }t        |«      sŒ |«       }|�|c S  n t        j	                  d«       t        |j
                  dd«      }t        |t        j                  j                  «      r|n|j
                  }|j                  «       S )a,  Resolve EMA model weights from the active EMA callback.

        Args:
            trainer: The Lightning Trainer instance.
            pl_module: The ``RFDETRModelModule`` being trained.

        Returns:
            EMA model state dict when available, otherwise the live model state dict.
        Úget_ema_model_state_dictNzhEMA metric improved but EMA callback weights were unavailable; saving current model weights as fallback.r\   )Ú	callbacksr]   ÚcallableÚloggerÚwarningrE   r)   r^   r_   r`   rA   )rT   ra   ÚcallbackÚgetterrA   rb   rc   s          r>   Ú_get_ema_model_state_dictz+BestModelCallback._get_ema_model_state_dictÂ   s”   € ð  ×)Ñ)ò 	ˆHÜ˜XÐ'AÀ4ÓHˆFÜ˜ÕÙ#›X�
ØÐ)Ø%Ò%Ùð	ô 	�‰Øvô	
ô ˜	Ÿ™¨°dÓ;ˆÜ! %¬¯©¯©Ô9‰e¸y¿¹ˆØ�~‰~ÓÐr?   c                ó  — t        | dd«      }|€yt        |t        «      r|S t        |dd«      }t        |«      sy |«       }t        |t        «      sy|€Yt        | j                  dd«      }t        |t
        j                  j                  «      r|n| j                  }|j                  «       }|j                  d«      }t        |t
        j                  «      rM|j                  dk(  r>d|v r:|j                  d¬	«      j                  «       D �cg c]  }t        |«      ‘Œ c}|d<   |j                  d
«      }	t        |	t
        j                  «      r(|	j                  dk(  rd|v r|	j                  d   dz
  |d<   |S c c}w )a“  Serialize the model architecture config when the module exposes one.

        Schema-critical fields (``num_keypoints_per_class``, ``num_classes``) are synced from live model weights so the
        saved config reflects what the model actually learned, not a stale constructor default (e.g. COCO ``[0, 17]``
        when the model was fine-tuned on ``[0, 33]``).

        Args:
            pl_module: The Lightning module whose model config will be serialized.
            state_dict: Pre-computed model state dict. If ``None``, computed from the live model.
                Pass the already-retrieved checkpoint state dict to avoid a redundant copy.
        rM   NÚ
model_dumpr\   Ú_kp_active_maské   Únum_keypoints_per_classr   )Údimzclass_embed.weightÚnum_classesr   )r]   r)   Údictrh   rE   r^   r_   r`   rA   ÚgetÚTensorÚndimÚsumÚtolistr+   Úshape)
ra   rA   rM   ro   Údumpedrb   rc   Ú_kp_maskÚnÚ
_ce_weights
             r>   Ú_serialize_model_configz)BestModelCallback._serialize_model_configÞ   sO  € ô ˜y¨.¸$Ó?ˆØÐØÜ�l¤DÔ)ØÐÜ˜\¨<¸Ó>ˆ
Ü˜
Ô#ØÙ“ˆÜ˜&¤$Ô'Øð ÐÜ˜IŸO™O¨[¸$Ó?ˆEÜ% e¬U¯X©X¯_©_Ô=‘%À9Ç?Á?ˆCØŸ™Ó)ˆJà—>‘>Ð"3Ó4ˆÜ�h¤§¡Ô-°(·-±-À1Ò2DÐIbÐflÑIlØAIÇÁÐRSÀÓAT×A[ÑA[ÓA]Ö0^¸A´°QµÒ0^ˆFÐ,Ñ-à—^‘^Ð$8Ó9ˆ
Ü�j¤%§,¡,Ô/°J·O±OÀqÒ4HÈ]Ð^dÑMdØ$.×$4Ñ$4°QÑ$7¸!Ñ$;ˆF�=Ñ!àˆùò 1_s   ÄE<c                ó`  — t        | dd«      }|�t        |dd«      nd}t        |t        «      r|j                  «       }|r|S |�t	        |«      j
                  nd}|j                  d«      rt        d|› d�«      ‚|j                  d«      r"|j                  d	«      r|j                  d	«      S y)
a‹  Resolve checkpoint model_name from model_config or config type.

        The CLI/PTL path does not call ``RFDETR.train()``, so ``model_config.model_name`` may be unset. In that case,
        infer the model class from concrete config names like ``RFDETRSmallConfig``.

        Note:
            The ``DeprecatedConfig`` ``RuntimeError`` guard is only reachable from the CLI/PTL path. ``RFDETR.train()``
            pre-populates ``model_config.model_name`` before saving any checkpoint, so the config type-name branch (and
            therefore the ``DeprecatedConfig`` guard) is never reached when training is started via ``RFDETR.train()``.
        rM   NrL   Ú ÚDeprecatedConfigzDeprecated model config 'zL' is no longer supported. Re-train your model using a current model variant.ÚRFDETRÚConfig)
r]   r)   ÚstrÚstripÚtypeÚ__name__ÚendswithÚRuntimeErrorÚ
startswithÚremovesuffix)ra   rM   Úconfigured_nameÚnormalized_nameÚconfig_type_names        r>   Ú_resolve_model_namez%BestModelCallback._resolve_model_name	  sÅ   € ô ˜y¨.¸$Ó?ˆØGSÐG_œ' ,°¸dÔCÐeiˆÜ�o¤sÔ+Ø-×3Ñ3Ó5ˆOÙØ&Ð&à:FÐ:Rœ4 Ó-×6Ò6ÐXZÐà×$Ñ$Ð%7Ô8ÜØ+Ð,<Ð+=ð >Eð Eóð ð ×&Ñ& xÔ0Ð5E×5NÑ5NÈxÔ5XØ#×0Ñ0°Ó:Ð:Ør?   c                ó~   •— t         ‰| �  «       }| j                  |d<   | j                  |d<   | j                  |d<   |S )aW  Return callback state including ``_best_ema``, ``_smoothed_regular``, and ``_best_raw_regular``.

        Extends the parent :class:`~pytorch_lightning.callbacks.ModelCheckpoint` state dict with three extra keys so
        that ``trainer.fit(ckpt_path=...)`` resumes the EMA high-water mark, the smoothed-metric accumulator, and the
        raw metric at the smoothed-best epoch from their correct values rather than resetting to ``0.0``.

        Returns:
            State dict with all parent fields plus ``"_best_ema"``, ``"_smoothed_regular"``,
            and ``"_best_raw_regular"``.
        r'   r3   r4   )r#   rA   r'   r3   r4   )r6   Ústater=   s     €r>   rA   zBestModelCallback.state_dict'  sG   ø€ ô ‘Ñ"Ó$ˆØ!Ÿ^™^ˆˆkÑØ%)×%;Ñ%;ˆÐ!Ñ"Ø%)×%;Ñ%;ˆÐ!Ñ"Øˆr?   c                óÞ  •— t        |«      }t        |j                  dd«      «      | _        t	        j
                  | j                  «      sd| _        t        |j                  dd«      «      | _        t	        j
                  | j                  «      sd| _        t        |j                  dd«      «      | _        t	        j
                  | j                  «      sd| _        t        ‰| �%  |«       y)a  Restore callback state from a Lightning checkpoint.

        Pops ``"_best_ema"``, ``"_smoothed_regular"``, and ``"_best_raw_regular"`` from a shallow copy of *state_dict*
        before delegating to the parent so the parent does not receive unexpected keys.  Each key defaults to ``0.0``
        when absent (e.g. checkpoints saved before these fields were persisted) and is reset to ``0.0`` when the stored
        value is non-finite.

        Args:
            state_dict: Callback state dict as produced by :meth:`state_dict`.
        r'   r   r3   r4   N)
ru   r/   Úpopr'   r0   r1   r3   r4   r#   Úload_state_dict)r6   rA   r“   r=   s      €r>   r–   z!BestModelCallback.load_state_dict8  s°   ø€ ô �ZÓ ˆÜ˜uŸy™y¨°cÓ:Ó;ˆŒÜ�}‰}˜TŸ^™^Ô,Ø ˆDŒNÜ!& u§y¡yÐ1DÀcÓ'JÓ!KˆÔÜ�}‰}˜T×3Ñ3Ô4Ø%(ˆDÔ"Ü!& u§y¡yÐ1DÀcÓ'JÓ!KˆÔÜ�}‰}˜T×3Ñ3Ô4Ø%(ˆDÔ"Ü‰Ñ Õ&r?   c           	     ó”  — |j                   sy| j                  }|€t        d|›d|j                  › d�«      ‚t	        |«      }|j
                  j                  dd¬«       | j                  |«      }|j                  }t        |j                  dd«      }|�-t        |d«      r!t        |dd«      €|j                  d|i¬	«      }t        |d
«      r|j                  «       n|}| j                  |«      }	| j                  ||«      }
t!        j"                  | j%                  ||||	|
¬«      |«       |j&                  | _        |j*                  j-                  | j.                  «      }t!        j0                  |«      r|j3                  «       d›}n|�t5        |«      }nd}t6        j9                  d||j                  | j.                  |«       y)um  Save stripped ``.pth`` format instead of a full ``.ckpt``.

        Skips on non-main processes.  Intentionally does NOT call ``trainer.save_checkpoint()`` â€” we only want ``{model,
        args, epoch}``.

        Args:
            trainer: The Lightning Trainer instance.
            filepath: Destination path (ends in ``.pth`` via ``FILE_EXTENSION``).
        Nz8BestModelCallback._save_checkpoint called with filepath=z
 at epoch=z but pl_module was not set.T©ÚparentsÚexist_okÚclass_namesÚ
model_copy©Úupdatero   ©rL   rU   z.6gÚunknownzDBest regular checkpoint saved to %s (epoch %d, monitor=%s, value=%s))Úis_global_zeror5   r‹   rO   r   ÚparentÚmkdirrd   Útrain_configr]   Ú
datamoduleÚhasattrrœ   ro   r‘   r€   r^   ÚsaverZ   rH   Ú_last_global_step_savedÚcallback_metricsrv   r   Ú	is_tensorÚitemr†   ri   Úinfo)r6   rT   Úfilepathra   Úpth_pathrR   r¤   Údataset_class_namesrS   rL   rU   Úmonitor_valueÚmonitor_displays                r>   Ú_save_checkpointz"BestModelCallback._save_checkpointP  sÓ  € ð ×%Ò%ØØ×+Ñ+ˆ	ØÐÜØJÈ8È,ð WØ#×1Ñ1Ð2Ð2MðOóð ô ˜“>ˆØ�‰×Ñ d°TÐÔ:ð  ×:Ñ:¸9ÓEÐð !×-Ñ-ˆÜ% g×&8Ñ&8¸-ÈÓNÐàÐ+Ü˜ lÔ3Ü˜ m°TÓ:ÐBà'×2Ñ2¸=ÐJ]Ð:^Ð2Ó_ˆLÜ18¸À|Ô1T�L×+Ñ+Ô-ÐZfˆ	Ø×-Ñ-¨iÓ8ˆ
Ø ×8Ñ8¸ÐDTÓUÐÜ�
‰
Ø×*Ñ*Ø ØØØ%Ø"3ð +ó ð ô		
ð (/×':Ñ':ˆÔ$Ø×0Ñ0×4Ñ4°T·\±\ÓBˆÜ�?‰?˜=Ô)Ø!.×!3Ñ!3Ó!5°cÐ :‰OØÐ&Ü! -Ó0‰Oà'ˆOÜ�‰ØRØØ×!Ñ!Ø�L‰LØõ	
r?   c           	     ót  •— || _         d}| j                  dkD  rp| j                  |j                  v rX|j                  | j                     j	                  «       }| j                  | j
                  z  d| j                  z
  |z  z   | _        |j                  | j                  k  ry| j                  |j                  vry| j                  dkD  �r,|�|n&|j                  | j                     j	                  «       }| j                  �| j                  j	                  «       nt        d«       }|j                  | j                     }t        j                  | j
                  |j                  |j                  ¬«      |j                  | j                  <   	 t        ‰| �=  ||«       ||j                  | j                  <   | j                  �| j                  j	                  «       nt        d«       }||kD  r|| _        nt        ‰| �=  ||«       | j"                  �|j$                  sy|j                  j'                  | j"                  t        j                  d«      «      j	                  «       }|| j(                  kD  �r"|| _        | j*                  j-                  dd¬«       | j/                  ||«      }	|j0                  }
t3        |j4                  dd«      }|�-t7        |
d	«      r!t3        |
dd«      €|
j9                  d|i¬
«      }
t7        |
d«      r|
j;                  «       n|
}| j=                  |«      }| j?                  ||	«      }t        j@                  | jC                  |	||||¬«      | j*                  dz  «       tD        jG                  d||j                  «       yy# ||j                  | j                  <   w xY w)aí  Save best regular/EMA checkpoints when validation mAP improves.

        Delegates regular-model checkpoint management to the :class:`~pytorch_lightning.callbacks.ModelCheckpoint`
        parent (handles improvement detection, fast_dev_run/sanity guards, ``best_model_path`` and ``best_model_score``
        bookkeeping).  EMA is tracked independently.

        Args:
            trainer: The Lightning Trainer instance.
            pl_module: The ``RFDETRModelModule`` being trained.
        Nr   r"   Úinf)ÚdtypeÚdeviceTr˜   r›   rœ   r�   ro   rŸ   úcheckpoint_best_ema.pthz(Best EMA mAP improved to %.4f (epoch %d))$r5   r2   r   r©   r«   r3   rO   r.   Úbest_model_scorer/   r^   Útensorrµ   r¶   r#   Úon_validation_endr4   r%   r¡   rv   r'   r(   r£   rm   r¤   r]   r¥   r¦   rœ   ro   r‘   r€   r§   rZ   ri   r¬   )r6   rT   ra   rc   Úcurrent_rawÚprev_best_scoreÚoriginalÚnew_best_scoreÚema_valÚema_state_dictÚema_train_configr¯   Úema_args_dictÚema_model_nameÚema_model_config_dictr=   s                  €r>   rº   z#BestModelCallback.on_validation_end�  sq  ø€ ð #,ˆÔð !ˆØ×Ñ Ò#¨¯©¸×8PÑ8PÑ(PØ×*Ñ*¨4¯<©<Ñ8×=Ñ=Ó?ˆCØ%)×%7Ñ%7¸$×:PÑ:PÑ%PÐTWÐZ^×ZlÑZlÑTlÐpsÑSsÑ%sˆDÔ"Ø× Ñ  4×#9Ñ#9Ò9Øð �<‰<˜w×7Ñ7Ñ7Øð ×Ñ Ó#ð ),¨¡¸W×=UÑ=UÐVZ×VbÑVbÑ=c×=hÑ=hÓ=jˆKØ>B×>SÑ>SÐ>_˜d×3Ñ3×8Ñ8Ô:ÔfkÐlqÓfrÐerˆOØ×/Ñ/°·±Ñ=ˆHÜ5:·\±\Ø×&Ñ&¨h¯n©nÀXÇ_Á_ô6ˆG×$Ñ$ T§\¡\Ñ2ðBÜ‘Ñ)¨'°9Ô=à9A�×(Ñ(¨¯©Ñ6ð >B×=RÑ=RÐ=^˜T×2Ñ2×7Ñ7Ô9ÔejÐkpÓeqÐdqˆNØ Ò/Ø)4�Õ&ä‰GÑ% g¨yÔ9ð ×ÑÐ$¨G×,BÒ,BØØ×*Ñ*×.Ñ.¨t×/@Ñ/@Ä%Ç,Á,ÈsÓBSÓT×YÑYÓ[ˆØ�T—^‘^Ó#Ø$ˆDŒNØ×Ñ×"Ñ"¨4¸$Ð"Ô?Ø!×;Ñ;¸GÀYÓOˆNð  )×5Ñ5ÐÜ")¨'×*<Ñ*<¸mÈTÓ"RÐà#Ð/ÜÐ,¨lÔ;ÜÐ,¨m¸TÓBÐJà#3×#>Ñ#>À}ÐViÐFjÐ#>Ó#kÐ ä18Ð9IÈ<Ô1XÐ ×+Ñ+Ô-Ð^nð ð "×5Ñ5°iÓ@ˆNØ$(×$@Ñ$@ÀÈNÓ$[Ð!Ü�J‰JØ×.Ñ.Ø"Ø!ØØ-Ø&;ð /ó ð × Ñ Ð#<Ñ<ô	ô �K‰KØ:ØØ×%Ñ%õð; $øð :B�×(Ñ(¨¯©Ò6ús   ÆN ÎN7c                óD  — |j                   sy| j                  dkD  r| j                  }n(| j                  �| j                  j	                  «       nd}| j
                  rt        | j
                  «      nd}| j                  dz  }| j                  dz  }| j                  |kD  }|r|j                  «       r|n|}|rW|j                  «       rGt        j                  ||«       t        |«       t        j                  d|rdnd|| j                  «       | j                  �rt!        t#        |«      dd«      }	|	duxr |	t$        j&                  u}
|
rÒ|j                  «       st        j)                  d	«       yt+        j,                  |d
d¬«      }t!        |j.                  dd«      }t1        |t*        j2                  j4                  «      r|n|j.                  }|j7                  |d   d¬«       t        j                  d|«       |j9                  ||j:                  d¬«       yyy)a…  Select the overall best model and optionally run test evaluation.

        Copies the winner (regular vs EMA, strict ``>`` for EMA) to ``checkpoint_best_total.pth``, strips
        optimizer/scheduler state, then optionally runs ``trainer.test()``.

        Args:
            trainer: The Lightning Trainer instance.
            pl_module: The ``RFDETRModelModule`` being trained.
        Nr   r·   zcheckpoint_best_total.pthz<Best total checkpoint saved from %s (regular=%.4f, ema=%.4f)ÚEMAÚregularÚ	test_stepzèSkipping trainer.test() because no best checkpoint was produced. Ensure the monitored metric is logged on evaluation epochs, that evaluation runs often enough, and that skip_best_epochs is smaller than the number of training epochs.ÚcpuF)Úmap_locationÚweights_onlyr\   rE   T)Ústrictz0Loaded best weights from %s for test evaluation.)r¥   r   )r¡   r2   r4   r¸   r«   Úbest_model_pathr   r(   r'   ÚexistsÚshutilÚcopy2r   ri   r¬   r&   r]   rˆ   r   rÈ   rj   r^   ÚloadrE   r)   r_   r`   r–   Útestr¥   )r6   rT   ra   Úbest_regularÚregular_pathÚema_pathÚ
total_pathÚbest_is_emaÚ	best_pathÚcls_test_stepÚhas_test_stepÚckptrb   rc   s                 r>   Ú
on_fit_endzBestModelCallback.on_fit_endë  sÔ  € ð ×%Ò%Øð ×Ñ Ò#Ø×1Ñ1‰Là;?×;PÑ;PÐ;\˜4×0Ñ0×5Ñ5Ô7ÐbeˆLØ59×5IÒ5I”t˜D×0Ñ0Ô1ÈtˆØ×#Ñ#Ð&?Ñ?ˆØ×%Ñ%Ð(CÑCˆ
ð —n‘n |Ñ3ˆÙ!,°·±Ô1B‘HÈˆ	á˜×)Ñ)Ô+Ü�L‰L˜ JÔ/Ü˜ZÔ(Ü�K‰KØNÙ$‘¨)ØØ—‘ô	ð �>‹>ä#¤D¨£O°[À$ÓGˆMØ)°Ð5Òh¸-Ì×OhÑOhÐ:hˆMÙØ!×(Ñ(Ô*Ü—N‘Nð+ôð ä—z‘z *¸5ÈuÔU�ô   	§¡°¸dÓC�Ü)¨%´·±·±ÔA‘eÀyÇÁ�Ø×#Ñ# D¨¡M¸$Ð#Ô?Ü—‘ÐNÐPZÔ[Ø—‘˜Y°7×3EÑ3EÈu�ÕUð# ð	 r?   )úval/mAP_50_95NTr   r   )r7   r†   r8   r†   r9   ú
str | Noner:   r*   r;   r+   r<   r/   ÚreturnÚNone)NN)rR   údict[str, torch.Tensor]rS   ÚobjectrT   r   rL   rÞ   rU   zobject | Nonerß   zdict[str, object])ra   r   rß   rá   )rT   r   ra   r   rß   rá   )N)ra   r   rA   zdict[str, Any] | Nonerß   zdict[str, object] | None)ra   r   rß   rÞ   )rß   údict[str, Any])rA   rã   rß   rà   )rT   r   r­   r†   rß   rà   ©rT   r   ra   r   rß   rà   )r‰   Ú
__module__Ú__qualname__Ú__doc__ÚFILE_EXTENSIONr$   ÚstaticmethodrZ   rd   rm   r€   r‘   rA   r–   r²   rº   rÜ   Ú__classcell__©r=   s   @r>   r   r      sd  ø„ ñ,ð\ €Nð
  /Ø"&ØØ !Ø!ð+?àð+?ð ð+?ð  ð	+?ð
 ð+?ð ð+?ð ð+?ð 
õ+?ðZ ð
 "&Ø+/ð5Ø1ð5àð5ð ð5ð ð	5ð
 )ð5ð 
ò5ó ð5ðn ò ó ð ð ð Øð à"ð ð 
!ò ó ð ð6 àHLð(Ø"ð(Ø0Eð(à	!ò(ó ð(ðT òó ðõ:õ"'ó0=
õ~Z÷x@Vr?   r   c                  ón   ‡ — e Zd ZU dZdZded<   	 	 	 	 	 	 	 d	 	 	 	 	 	 	 	 	 	 	 	 	 	 	 dˆ fd„Zd	ˆ fd„Zˆ xZS )
ÚRFDETREarlyStoppinguM  Early stopping callback monitoring validation mAP for RF-DETR.

    Extends :class:`pytorch_lightning.callbacks.EarlyStopping` with dual-metric
    monitoring: by default it monitors ``max(regular_mAP, ema_mAP)`` (legacy
    behaviour); set ``use_ema=True`` to monitor the EMA metric exclusively.

    The effective metric is injected into ``trainer.callback_metrics`` under a synthetic key before delegating to the
    parent's stopping logic, so all parent features are available for free: ``state_dict``/``load_state_dict`` for
    checkpoint resumption, NaN/inf guard via ``check_finite``, and ``stopping_threshold``/``divergence_threshold``.

    Early stopping evaluates only on validation epochs where the monitored metrics are logged; non-eval epochs
    (``eval_interval > 1``) are skipped automatically.

    Args:
        patience: Number of epochs with no improvement before stopping.
        min_delta: Minimum mAP improvement to reset the patience counter.
        use_ema: When ``True`` and both regular and EMA metrics are available,
            monitor only the EMA metric.  When ``False``, monitor ``max(regular, ema)``.
        monitor_regular: Metric key for the regular model mAP.
        monitor_ema: Metric key for the EMA model mAP.
        verbose: If ``True``, log early stopping status each epoch.
        skip_best_epochs: Ignore the first N epochs (0..N-1) when evaluating
            patience and best-score baselines.  Set this when fine-tuning from ``pretrain_weights`` to avoid premature
            stopping before the model adapts to the new dataset.

    Examples:
        Fine-tuning from pretrained weights â€” skip first 3 epochs:

        >>> from rfdetr.training.callbacks.best_model import RFDETREarlyStopping
        >>> cb = RFDETREarlyStopping(patience=10, skip_best_epochs=3)
        >>> cb._skip_best_epochs
        3
    Ú__rfdetr_effective_map__r†   Ú_SYNTHETIC_MONITORc                óø   •— t         ‰| �  | j                  d||d|ddd¬«	       t        |t        «      st        |t
        «      st        d«      ‚|dk  rt        d«      ‚|| _        || _	        || _
        || _        y )Nr   FT)	r   r   ÚpatienceÚ	min_deltaÚcheck_on_train_epoch_endr   Úcheck_finiterÌ   Úlog_rank_zero_onlyr    r   r!   )r#   r$   rï   r)   r*   r+   r,   r-   Ú_monitor_regularr%   Ú_use_emar.   )	r6   rñ   rò   Úuse_emar8   r9   r   r;   r=   s	           €r>   r$   zRFDETREarlyStopping.__init__S  s�   ø€ ô 	‰ÑØ×+Ñ+ØØØØ%*ØØØØ#ð 	ô 
	
ô Ð&¬Ô-´ZÐ@PÔRUÔ5VÜÐMÓNÐNØ˜aÒÜÐRÓSÐSà /ˆÔØ'ˆÔØˆŒØ!1ˆÕr?   c                óâ  •— |j                   | j                  k  ry|j                  }|j                  | j                  «      }|j                  | j
                  «      }|�|j                  «       nd}|�|j                  «       nd}|€|€y| j                  r|�|}n|�|�t        ||«      }n|�|}n|}t        j                  |«      |j                  | j                  <   t        ‰	| �5  ||«       y)aó  Compute effective mAP and delegate to parent stopping logic.

        Computes ``ema_mAP`` or ``max(regular_mAP, ema_mAP)`` depending on ``use_ema``, injects the result under the
        synthetic monitor key, then calls :meth:`EarlyStopping.on_validation_end` which handles patience,
        ``trainer.should_stop``, logging, and ``state_dict`` persistence.

        Args:
            trainer: The Lightning Trainer instance.
            pl_module: The ``RFDETRModelModule`` being trained.
        N)rO   r.   r©   rv   rö   r%   r«   r÷   r   r^   r¹   rï   r#   rº   )
r6   rT   ra   ÚmetricsÚregular_tensorÚ
ema_tensorÚregular_valr¿   Ú	effectiver=   s
            €r>   rº   z%RFDETREarlyStopping.on_validation_endr  sì   ø€ ð × Ñ  4×#9Ñ#9Ò9Øà×*Ñ*ˆØ Ÿ™ T×%:Ñ%:Ó;ˆØ—[‘[ ×!2Ñ!2Ó3ˆ
à=KÐ=W N×$7Ñ$7Ô$9Ð]aˆØ5?Ð5K 
§¡Ô 1ÐQUˆàÐ 7 ?Øà�=Š=˜WÐ0Ø‰IØÐ$¨Ð)<Ü˜K¨Ó1‰IØÐ Ø‰Ià#ˆIä<A¿L¹LÈÓ<Sˆ× Ñ  ×!8Ñ!8Ñ9Ü‰Ñ! '¨9Õ5r?   )é
   gü©ñÒMbP?FrÝ   zval/ema_mAP_50_95Tr   )rñ   r+   rò   r/   rø   r*   r8   r†   r9   r†   r   r*   r;   r+   rß   rà   rä   )	r‰   rå   ræ   rç   rï   Ú__annotations__r$   rº   rê   rë   s   @r>   rí   rí   .  sŠ   ø… ñ ðD 9Ð˜Ó8ð Ø ØØ.Ø.ØØ !ð2àð2ð ð2ð ð	2ð
 ð2ð ð2ð ð2ð ð2ð 
õ2÷>"6ñ "6r?   rí   )rç   Ú
__future__r   r0   rÏ   Úpathlibr   Útypingr   r   r^   Úpytorch_lightningr   r   r	   rQ   Úpytorch_lightning.callbacksr
   r   Úrfdetr.utilities.loggerr   Úrfdetr.utilities.packager   Úrfdetr.utilities.state_dictr   r   ri   r   rí   © r?   r>   ú<module>r
     s[   ðñ \å "ã Û Ý Ý  áÝã ß 6Ý 8ß Få .Ý 0ß Ná	‹€ôMV˜ô MVô`f6˜-õ f6r?   