Ë
    ëÓ^jÆŽ  ã            
      ó  — U d Z ddlmZ ddlZddlZddlZddlmZmZm	Z	m
Z
 ddlZddlmc m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mZ dd
lmZmZm Z  ddl!m"Z" ddl#m$Z$  e$«       Z%ddddddddddœ	Z&de'd<    G d„ de«      Z(y)z4LightningModule for RF-DETR training and validation.é    )ÚannotationsN)ÚAnyÚDictÚOptionalÚTuple)ÚLightningModuleÚseed_everything)Ú_namespace_from_configs)ÚModelConfigÚTrainConfig)Úcompute_multi_scale_scales)Úbuild_criterion_from_configÚbuild_model_from_config)Ú
apply_loraÚinterpolate_position_embeddingsÚload_pretrain_weights)Úget_param_dict)Ú
get_loggerÚloss_clsÚloss_boxÚ	loss_giouÚmask_ceÚ	mask_diceÚkp_l1Úkp_findÚkp_visÚkp_nll)	Úloss_ceÚ	loss_bboxr   Úloss_mask_ceÚloss_mask_diceÚloss_keypoints_l1Úloss_keypoints_findableÚloss_keypoints_visibleÚloss_keypoints_nllzdict[str, str]Ú_TRAIN_PROGRESS_LOSS_ALIASESc                  ó2  ‡ — e Zd ZdZdˆ fd„Zdd„Zdd„Zdd„Zdd„Z	 	 	 	 	 	 dd„Z		 	 	 	 	 	 dd„Z
dd	„Zdd
„Zd d„Zdd„Zed!d„«       Z	 	 	 	 	 	 	 	 d"d„Z	 	 	 	 	 	 	 	 d"d„Zd#d„Zed$d„«       Zd%d„Z	 	 d&	 	 	 	 	 	 	 d'ˆ fd„Zd#d„Zd(d)d„Zd*d„Zd+d„Zˆ xZS ),ÚRFDETRModelModulez¼LightningModule wrapping the RF-DETR model and training loop.

    Args:
        model_config: Architecture configuration.
        train_config: Training hyperparameter configuration.
    c                ó,  •— t         ‰| �  «        || _        || _        t	        t        |dd«      «      | _        | j                   | _        d | _        d| _	        t        ||«      | _        |j                  �jt        | j                  | j                  «       |j                  r>t        | j                  dd «      }t        |«      r |«        t         j#                  d«       |j$                  rt'        | j                  «       t)        | j                  | j                  «      \  | _        | _        ddlm} t3        |j4                  «      j7                  «       }|dv }|j8                  xr |dk(  xr |xr |j:                   }|j8                  r!|j:                  rt         j#                  d	«       |red
t<        j>                  j@                  _!        d
t<        j>                  j@                  _"        t=        j8                  | j                  d
¬«      | _        y y )NÚuse_grouppose_keypointsFÚ"reset_keypoint_gaussian_parameterszVReset keypoint Gaussian precision outputs to unit values after pretrained weight load.r   )ÚDEVICE>   ÚgpuÚautoÚcudar/   zQDisabling torch.compile because multi_scale=True introduces dynamic input shapes.T)Údynamic)#ÚsuperÚ__init__Úmodel_configÚtrain_configÚboolÚgetattrÚ_use_manual_optimizationÚautomatic_optimizationÚ_accumulated_box_normalizerÚstrict_loadingr   ÚmodelÚpretrain_weightsr   r*   ÚcallableÚloggerÚinfoÚbackbone_lorar   r   Ú	criterionÚpostprocessÚrfdetr.configr,   ÚstrÚacceleratorÚlowerÚcompileÚmulti_scaleÚtorchÚ_dynamoÚconfigÚsuppress_errorsÚcapture_scalar_outputs)	Úselfr3   r4   r+   r,   rE   Úuses_cuda_acceleratorÚcompile_enabledÚ	__class__s	           €úg/var/www/ramen.bs-engineer-server.com/venv/lib/python3.12/site-packages/rfdetr/training/module_model.pyr2   zRFDETRModelModule.__init__2   sÁ  ø€ Ü‰ÑÔØ(ˆÔØ(ˆÔô /3´7¸<ÐIbÐdiÓ3jÓ.kˆÔ%Ø*.×*GÑ*GÐ&GˆÔ#Ø@DˆÔ(ð $ˆÔô -¨\¸<ÓHˆŒ
Ø×(Ñ(Ð4ô " $§*¡*¨d×.?Ñ.?Ô@Ø×3Ò3ä5<¸T¿Z¹ZÐImÐosÓ5tÐ2ÜÐ>Ô?Ù6Ô8Ü—K‘KØpôð ×%Ò%Ü�t—z‘zÔ"ô ,GÀt×GXÑGXÐZ^×ZkÑZkÓ+lÑ(ˆŒ˜Ô(õ 	)ä˜,×2Ñ2Ó3×9Ñ9Ó;ˆØ +Ð/FÐ FÐà× Ñ Òp V¨vÑ%5ÒpÐ:OÒpÐXd×XpÑXpÐTpð 	ð ×Ò L×$<Ò$<Ü�K‰KÐkÔlÙð 48ŒE�M‰M× Ñ Ô0Ø:>ŒE�M‰M× Ñ Ô7ÜŸ™ t§z¡z¸4Ô@ˆD�Jð ó    c                óŽ   — | j                   j                  �/t        | j                   j                  | j                  z   d¬«       yy)zÛSeed RNGs at fit start when ``TrainConfig.seed`` is set.

        This avoids hidden global side-effects in ``build_trainer`` while still preserving deterministic training
        behaviour for actual fit runs.
        NT)Úworkers)r4   Úseedr	   Úglobal_rank©rN   s    rR   Úon_fit_startzRFDETRModelModule.on_fit_startw   s<   € ð ×Ñ×!Ñ!Ð-Ü˜D×-Ñ-×2Ñ2°T×5EÑ5EÑEÈtÖTð .rS   c                óÆ  — | j                   }| j                  }|j                  �r0|j                  �s"|\  }}t	        |j
                  |j                  |j                  |j                  «      }| j                  j                  }t        j                  |«       t        j                  |«      }	t        j                  «       5  t!        j"                  |j$                  |	dd¬«      |_        t!        j"                  |j&                  j)                  d«      j+                  «       |	d¬«      j-                  d«      j/                  «       |_        ddd«       yyy# 1 sw Y   yxY w)an  Apply optional multi-scale resize to the incoming batch.

        Modifications to ``batch`` (in-place on ``NestedTensor``) are visible in ``training_step`` because they share
        the same object.

        Args:
            batch: Tuple of (NestedTensor samples, list of target dicts).
            batch_idx: Index of the current batch within the epoch.
        ÚbilinearF)ÚsizeÚmodeÚalign_cornersé   Únearest)r\   r]   N)r4   r3   rH   Údo_random_resize_via_paddingr   Ú
resolutionÚexpanded_scalesÚ
patch_sizeÚnum_windowsÚtrainerÚglobal_stepÚrandomrV   ÚchoicerI   Úno_gradÚFÚinterpolateÚtensorsÚmaskÚ	unsqueezeÚfloatÚsqueezer5   )
rN   ÚbatchÚ	batch_idxÚtcÚmcÚsamplesÚ_ÚscalesÚstepÚscales
             rR   Úon_train_batch_startz&RFDETRModelModule.on_train_batch_start€   s  € ð ×ÑˆØ×Ñˆà�>‹> "×"AÓ"AØ‰JˆG�QÜ/°·±¸r×?QÑ?QÐSU×S`ÑS`Ðbd×bpÑbpÓqˆFØ—<‘<×+Ñ+ˆDÜ�K‰K˜ÔÜ—M‘M &Ó)ˆEÜ—‘“ñ Ü"#§-¡-°·±ÀeÐR\ÐlqÔ"r�”ä—M‘M '§,¡,×"8Ñ"8¸Ó";×"AÑ"AÓ"CÈ%ÐV_Ô`×hÑhÐijÓk×pÑpÓrð ”÷ð ð #Bˆ>÷ð ús   ÃB
EÅE c                óÞ   — | j                   �D	 | j                  «       }t        |t        «      r|n|gD ]  }|j	                  «        Œ 	 d| _         yd| _         y# t
        $ r
 Y d| _         yw xY w)ay  Reset the accumulated box normalizer at the start of every training epoch.

        Lightning may reuse the module across epochs without calling ``_step_optimizer`` at the boundary (for example
        when an epoch ends mid-accumulation window with a non-divisible batch count). Clearing the accumulator here
        guarantees the manual-optimization path always starts each epoch from a known state, so the first microbatch's
        gradients are scaled by its own box count and not by a stale previous-epoch denominator.

        This is a no-op for non-keypoint models because they use Lightning's automatic optimization path and never
        populate ``self._accumulated_box_normalizer``.

        Note: on finite datasets the final-batch fallback in ``_should_step_optimizer`` always flushes a partial
        trailing window, so this reset is the only change needed.  On IterableDatasets (infinite
        ``num_training_batches``) a partial window may survive epoch end with un-stepped gradients; those are
        discarded here and the optimizer is zeroed so the first microbatch of the new epoch starts from a clean state.
        N)r9   Ú
optimizersÚ
isinstanceÚlistÚ	zero_gradÚRuntimeError)rN   ÚoptsÚopts      rR   Úon_train_epoch_startz&RFDETRModelModule.on_train_epoch_start™   ss   € ð  ×+Ñ+Ð7ðØ—‘Ó(�Ü#-¨d´DÔ#9™4À¸vò $�CØ—M‘M•Oñ$ð ,0ˆÕ(¨4ˆÕ(øô  ò ØØ+/ˆÕ(ðús   Ž:A Á	A,Á+A,c           
     óV  ‡‡— |\  }}t        |«      }| j                  ||«      }| j                  r)| j                  ||«      \  Š}}| j	                  ||«      }	n| j                  ||«      Šd}	| j
                  j                  Št        ˆˆfd„‰D «       «      }
t        dt        | j                  j                  «      «      }| j                  r|
n|
|z  }t        | j                  j                  «      }t        | j                  j                  «      }| j!                  ‰j#                  «       D ��ci c]  \  }}d|› �|“Œ c}}|d||¬«       | j%                  d|
d|d||¬	«       | j'                  |
‰|¬
«       | j)                  «       }t+        |t,        «      r|d   }|j.                  D �cg c]  }d|v sŒ|d   ‘Œ }}|r]|d   }t1        |«      }t        |«      }| j%                  d|ddd¬«       | j%                  d|ddd¬«       | j%                  d|ddd¬«       | j                  r3| j3                  |	«       | j5                  |«      r| j7                  |«       | j                  j8                  r÷t;        j<                  «       5  t;        j>                  |D �cg c]  }|d   ‘Œ	 c}«      }| j@                  jB                  }|j#                  «       D ��ci c]@  \  }}|dv r7t+        |t:        jD                  «      r||jF                  dk\  r|dd…d|…f   n|“ŒB }}}| jI                  ||«      }ddd«       | j                  r|jK                  «       n|| jM                  «      |dœS | j                  r|jK                  «       S |S c c}}w c c}w c c}w c c}}w # 1 sw Y   ŒnxY w)a  Compute loss for one training step and log metrics.

        PTL handles AMP (``precision``) without a manual ``GradScaler``. Keypoint models perform manual optimization so
        box-count loss normalization is based on the full accumulated effective batch rather than each microbatch
        independently; detection and segmentation models keep Lightning's automatic optimization path.

        Args:
            batch: Tuple of (NestedTensor samples, list of target dicts).
            batch_idx: Batch index within the epoch.

        Returns:
            Scalar loss tensor by default. When ``compute_train_metrics=True``,
            returns a Lightning-compatible dict containing ``loss`` plus
            detached postprocessed predictions for train mAP logging.
        Nc              3  ó>   •K  — | ]  }|‰v sŒ‰|   ‰|   z  –— Œ y ­w©N© ©Ú.0ÚkÚ	loss_dictÚweight_dicts     €€rR   ú	<genexpr>z2RFDETRModelModule.training_step.<locals>.<genexpr>Î   s%   øè ø€ ÒX°QÀqÈKÒGW�9˜Q‘< +¨a¡.Õ0ÑXùó   ƒ	�r_   ztrain/T©Úon_stepÚon_epochÚ	sync_distÚ
batch_sizez
train/lossF)Úprog_barr‘   r’   r“   r”   ©r”   r   Úlrztrain/lr)r•   r‘   r’   ztrain/lr_minztrain/lr_maxÚ	orig_size)Úpred_logitsÚ
pred_boxesÚ
pred_masksÚpred_keypointsé   )ÚlossÚresultsÚtargets)'Úlenr;   r7   Ú_compute_train_lossesÚ_scale_loss_for_accumulationrA   r�   ÚsumÚmaxÚintrf   Úaccumulate_grad_batchesr5   r4   Útrain_log_sync_distÚtrain_log_on_stepÚlog_dictÚitemsÚlogÚ_log_train_progress_metricsr}   r~   r   Úparam_groupsÚminÚmanual_backwardÚ_should_step_optimizerÚ_step_optimizerÚcompute_train_metricsrI   rj   Ústackr3   Únum_queriesÚTensorÚndimrB   ÚdetachÚ_detach_results)rN   rr   rs   rv   r    r”   ÚoutputsÚraw_lossÚ
normalizerÚloss_for_backwardrž   r§   Úloss_for_returnr¨   r©   r‹   ÚvÚ	optimizerÚpgÚ	group_lrsÚbase_lrÚmin_lrÚmax_lrÚtÚ
orig_sizesÚnqÚinference_outputsrŸ   rŒ   r�   s                               @@rR   Útraining_stepzRFDETRModelModule.training_step´   s‹  ù€ ð  !Ñˆ�Ü˜“\ˆ
Ø—*‘*˜W gÓ.ˆØ×(Ò(Ø.2×.HÑ.HÈÐRYÓ.ZÑ+ˆI�x Ø $× AÑ AÀ(ÈJÓ WÑàŸ™ w°Ó8ˆIØ $ÐØ—n‘n×0Ñ0ˆÜÔX¸)ÔXÓXˆô #& a¬¨T¯\©\×-QÑ-QÓ)RÓ"SÐØ"&×"?Ò"?™$ÀTÐLcÑEcˆÜ" 4×#4Ñ#4×#HÑ#HÓIÐÜ  ×!2Ñ!2×!DÑ!DÓEÐØ�‰Ø)2¯©Ó):×;¡  Aˆv�a�Sˆ\˜1‰_Ó;Ø%ØØ)Ø!ð 	ô 	
ð 	�‰ØØØØ%ØØ)Ø!ð 	ô 	
ð 	×(Ñ(¨¨yÀZÐ(ÔPØ—O‘OÓ%ˆ	Ü�i¤Ô&Ø! !™ˆIð )2×(>Ñ(>ÖM "À$È"Â*�R˜“XÐMˆ	ÐMÙØ ‘lˆGÜ˜“^ˆFÜ˜“^ˆFØ�H‰H�Z °5À$ÐQVˆHÔWØ�H‰H�^ V°eÀTÐTYˆHÔZØ�H‰H�^ V°eÀTÐTYˆHÔZØ×(Ò(Ø× Ñ Ð!2Ô3Ø×*Ñ*¨9Ô5Ø×$Ñ$ YÔ/Ø×Ñ×2Ò2Ü—‘“ñ JÜ"Ÿ[™[À'Ö)J¸Q¨!¨K«.Ò)JÓK�
ð ×&Ñ&×2Ñ2�ð
 !(§¡£÷%á˜˜1ØÐYÑYÜ" 1¤e§l¡lÔ3ð  A§F¡F¨a¢K�qš˜C˜R˜C˜’y°QÑ6ð%Ð!ñ %ð ×*Ñ*Ð+<¸jÓI�÷!Jð$ 59×4QÒ4Q˜×.Ñ.Ô0ÐWfØ×/Ñ/°Ó8Ø"ñð ð
 ,0×+HÒ+Hˆ×%Ñ%Ó'Ð]ÈoÐ]ùós <ùò, Nùò *Kùó%÷Jð Jús=   Ä1N	
Æ-	NÆ7NÊNÊN
Ê(0NËANÌNÎNÎN(c                óÔ  ‡‡	— | j                   j                  Š	t        | j                   dd«      s+t        t	        | j                   «      j
                  › d�«      ‚| j                   j                  ||«      }| j                  ||t        j                  |«      ¬«      Š‰j                  «       D ��ci c]  \  }}||‰	v r||z  n|“Œ }}}t        ˆˆ	fd„‰D «       «      }|||fS c c}}w )aN  Compute normalized losses for logging and raw weighted loss for backward.

        Args:
            outputs: Model output dictionary.
            targets: Target dictionaries for the current batch.

        Returns:
            A tuple of normalized loss dictionary, unnormalized weighted loss numerator, and box normalizer.
        Ú!supports_loss_normalizer_overrideFa  .supports_loss_normalizer_override is False; manual optimization (keypoint models) requires a criterion that accepts a num_boxes keyword argument. Set supports_loss_normalizer_override = True on your criterion subclass and implement the num_boxes parameter in forward().)Ú	num_boxesc              3  ó>   •K  — | ]  }|‰v sŒ‰|   ‰|   z  –— Œ y ­wr‡   rˆ   )rŠ   r‹   Únumerator_loss_dictr�   s     €€rR   rŽ   z:RFDETRModelModule._compute_train_losses.<locals>.<genexpr>4  s)   øè ø€ ÒpÀ1Ð_`ÐdoÒ_oÐ*¨1Ñ-°¸A±Õ>Ñpùr�   )rA   r�   r6   Ú
ValueErrorÚtypeÚ__name__Únum_boxes_for_targetsrI   Ú	ones_liker«   r¤   )
rN   rº   r    r¼   ÚkeyÚvaluerŒ   r»   rÏ   r�   s
           @@rR   r¢   z'RFDETRModelModule._compute_train_losses  sí   ù€ ð —n‘n×0Ñ0ˆÜ�t—~‘~Ð'JÈEÔRÜÜ˜Ÿ™Ó'×0Ñ0Ð1ð 2^ð ^óð ð —^‘^×9Ñ9¸'À7ÓKˆ
Ø"Ÿn™n¨W°gÌÏÉÐYcÓId˜nÓeÐð Xk×WpÑWpÓWr÷
ÙISÈÈeˆC s¨kÑ'9�˜Ò#¸uÑDð
ˆ	ñ 
ô ÔpÐH[ÔpÓpˆØ˜( JÐ.Ð.ùó	
s   Â1C$c                ó¬   — |j                  «       }| j                  }|€|n||z   }|�| j                  ||z  «       |j                  «       | _        ||z  S )a$  Scale the current numerator loss by the accumulated box denominator.

        Args:
            raw_loss: Current microbatch weighted loss numerator.
            normalizer: Current microbatch box denominator.

        Returns:
            Loss scalar to pass to ``manual_backward``.
        )r¸   r9   Ú_rescale_accumulated_gradients)rN   r»   r¼   Úprevious_normalizerÚaccumulated_normalizers        rR   r£   z.RFDETRModelModule._scale_loss_for_accumulation7  sj   € ð  ×&Ñ&Ó(ˆ
Ø"×>Ñ>ÐØ/BÐ/J¡ÐPcÐfpÑPpÐØÐ*Ø×/Ñ/Ð0CÐF\Ñ0\Ô]Ø+A×+HÑ+HÓ+JˆÔ(ØÐ0Ñ0Ð0rS   c                óð   — | j                  «       D ]c  }|j                  €Œ|j                  j                  |j                  |j                  j                  |j                  j
                  ¬«      «       Œe y)zÑRescale gradients already accumulated in the current optimizer window.

        Args:
            scale: Multiplicative factor that converts previous gradients from the old denominator to the new one.
        N)ÚdeviceÚdtype)Ú
parametersÚgradÚmul_ÚtorÜ   rÝ   )rN   rz   Ú	parameters      rR   rØ   z0RFDETRModelModule._rescale_accumulated_gradientsM  s\   € ð Ÿ™Ó*ò 	hˆIØ�~‰~Ñ)Ø—‘×#Ñ# E§H¡H°I·N±N×4IÑ4IÐQZ×Q_ÑQ_×QeÑQe HÓ$fÕgñ	hrS   c                ó  — t        dt        | j                  j                  «      «      }|dz   |z  dk(  ryt	        | j
                  dd«      }t        |t        t        f«      xr t        j                  |«      xr |dz   |k\  S )u�  Return whether the current batch closes an optimizer accumulation window.

        The optimizer steps when either:

        - The current batch closes a complete ``grad_accum_steps`` window
          (``(batch_idx + 1) % grad_accum_steps == 0``), or
        - This is the final batch of the epoch and a partial accumulation window
          is still open, so the trailing microbatches are not silently dropped.

        Lightning's ``Trainer.num_training_batches`` may be reported as ``float('inf')``
        for iterable / streaming datasets where the epoch length is unknown. In that case
        only the modulo path can ever close the window â€” the final-batch fallback is
        skipped because ``batch_idx + 1`` can never reach infinity.

        Args:
            batch_idx: Batch index within the epoch.

        Returns:
            ``True`` when the optimizer should step after this batch.
        r_   r   TÚnum_training_batchesN)
r¥   r¦   r4   Úgrad_accum_stepsr6   rf   r~   rp   ÚmathÚisfinite)rN   rs   Úaccum_stepsrä   s       rR   r±   z(RFDETRModelModule._should_step_optimizerW  s�   € ô* ˜!œS ×!2Ñ!2×!CÑ!CÓDÓEˆØ˜‰M˜[Ñ(¨AÒ-ØÜ& t§|¡|Ð5KÈTÓRÐäÐ+¬c´5¨\Ó:ò 6Ü—‘Ð2Ó3ò6à˜A‘Ð!5Ñ5ð	
rS   c                ó�  — t        | j                  dd«      }|€| j                  j                  }nt	        |t
        t        f«      r|}nd}t        | j                  dd«      }t	        |t        «      sd}|�|dkD  r| j                  |||¬«       |j                  «        |j                  «        | j                  «        d| _        y)zœClip gradients, step optimizer and scheduler, then reset accumulation state.

        Args:
            optimizer: Optimizer returned by Lightning.
        Úgradient_clip_valNÚgradient_clip_algorithmr   ©rê   rë   )r6   rf   r4   Úclip_max_normr~   r¦   rp   rD   Úclip_gradientsry   r€   Ú_step_lr_schedulerr9   )rN   rÀ   Útrainer_gradient_clip_valrê   rë   s        rR   r²   z!RFDETRModelModule._step_optimizerv  sÇ   € ô %,¨D¯L©LÐ:MÈtÓ$TÐ!Ø$Ð,Ø $× 1Ñ 1× ?Ñ ?ÑÜÐ1´C¼°<Ô@Ø 9Ñà $ÐÜ")¨$¯,©,Ð8QÐSWÓ"XÐÜÐ1´3Ô7Ø&*Ð#ØÐ(Ð->ÀÒ-BØ×ÑØØ"3Ø(?ð  ô ð
 	�‰ÔØ×ÑÔØ×ÑÔ!Ø+/ˆÕ(rS   c                ó®   — 	 | j                  «       }|€yt        |t        «      r|n|g}|D ]  }|j                  «        Œ y# t        t        f$ r Y yw xY w)z9Step Lightning's scheduler object when one is configured.N)Úlr_schedulersÚAttributeErrorr�   r~   r   ry   )rN   Ú	schedulerÚ
schedulersÚscheduler_items       rR   rï   z$RFDETRModelModule._step_lr_scheduler‘  sf   € ð	Ø×*Ñ*Ó,ˆIð ÐØÜ",¨Y¼Ô"=‘YÀIÀ;ˆ
Ø(ò 	"ˆNØ×ÑÕ!ñ	"øô ¤Ð-ò 	Ùð	ús   ‚A ÁAÁAc                óÒ   — | D ���cg c]K  }|j                  «       D ��ci c]-  \  }}|t        j                  |«      r|j                  «       n|“Œ/ c}}‘ŒM c}}}S c c}}w c c}}}w )a  Detach postprocessed result tensors before handing them to callbacks.

        Args:
            results: Per-image postprocessed prediction dictionaries.

        Returns:
            Per-image dictionaries with tensor values detached from the graph.
        )r«   rI   Ú	is_tensorr¸   )rŸ   ÚresultrÕ   rÖ   s       rR   r¹   z!RFDETRModelModule._detach_results�  s^   € ð "÷
ð 
àð Y_×XdÑXdÓXf×gÉ*È#ÈuˆS¤E§O¡O°EÔ$:�%—,‘,”.ÀÑEÕgô
ð 	
ùÛgùô
s   ‡A"Ÿ2AÁA"ÁA"c          
     óÄ   — | j                  d|dddd|¬«       t        j                  «       D ]1  \  }}|j                  |«      }|€Œ| j                  ||dddd|¬«       Œ3 y)a!  Log compact per-step convergence metrics for the progress bar only.

        Args:
            loss: Unscaled aggregate training loss.
            loss_dict: Raw criterion loss dictionary.
            batch_size: Current batch size used by Lightning for metric reduction metadata.
        rž   TF)r•   r>   r‘   r’   r”   N)r¬   r&   r«   Úget)rN   rž   rŒ   r”   Ú	loss_nameÚprogress_namerÖ   s          rR   r­   z-RFDETRModelModule._log_train_progress_metrics¬  s†   € ð 	�‰ØØØØØØØ!ð 	ô 	
ô )E×(JÑ(JÓ(Lò 	Ñ$ˆI�}Ø—M‘M )Ó,ˆEØˆ}ØØ�H‰HØØØØØØØ%ð õ ñ		rS   c               ó´   — | j                  |j                  «       D ��ci c]  \  }}d|› �|“Œ c}}ddd|¬«       | j                  d|ddd|¬«       yc c}}w )a  Log aggregate and component validation losses.

        Args:
            loss: Aggregate weighted validation loss.
            loss_dict: Raw criterion loss dictionary.
            batch_size: Current batch size used by Lightning for metric reduction metadata.
        zval/FTr�   zval/loss)r•   r’   r“   r”   N)rª   r«   r¬   )rN   rž   rŒ   r”   r‹   r¿   s         rR   Ú_log_val_loss_metricsz'RFDETRModelModule._log_val_loss_metricsÑ  sd   € ð 	�‰Ø'0§¡Ó'8×9™t˜q !ˆt�A�3ˆZ˜‰]Ó9ØØØØ!ð 	ô 	
ð 	�‰�˜T¨D¸4È4Ð\fˆÕgùó :s   ŸA
c                ó–  ‡
‡— |\  }}| j                  |«      }| j                  j                  rZ| j                  ||«      Š
| j                  j                  Št        ˆ
ˆfd„‰
D «       «      }| j                  |‰
t        |«      ¬«       t        j                  |D �cg c]  }|d   ‘Œ	 c}«      }| j                  ||«      }	|	|dœS c c}w )aË  Run forward pass and postprocess for one validation step.

        Returns raw results and targets so ``COCOEvalCallback`` can accumulate them across the epoch via
        ``on_validation_batch_end``.

        Args:
            batch: Tuple of (NestedTensor samples, list of target dicts).
            batch_idx: Batch index within the validation epoch.

        Returns:
            Dict with ``results`` (postprocessed predictions) and ``targets``.
        c              3  ó>   •K  — | ]  }|‰v sŒ‰|   ‰|   z  –— Œ y ­wr‡   rˆ   r‰   s     €€rR   rŽ   z4RFDETRModelModule.validation_step.<locals>.<genexpr>ú  ó&   øè ø€ Ò\¸È1ÐP[ÒK[�y ‘| k°!¡nÕ4Ñ\ùr�   r–   r˜   ©rŸ   r    )r;   r4   Úcompute_val_lossrA   r�   r¤   rÿ   r¡   rI   r´   rB   ©rN   rr   rs   rv   r    rº   rž   rÆ   rÇ   rŸ   rŒ   r�   s             @@rR   Úvalidation_stepz!RFDETRModelModule.validation_stepè  s´   ù€ ð !Ñˆ�Ø—*‘*˜WÓ%ˆØ×Ñ×-Ò-ØŸ™ w°Ó8ˆIØŸ.™.×4Ñ4ˆKÜÔ\¸iÔ\Ó\ˆDØ×&Ñ& t¨YÄ3ÀwÃ<Ð&ÔPä—[‘[¸'Ö!B°Q ! K£.Ò!BÓCˆ
Ø×"Ñ" 7¨JÓ7ˆØ"¨wÑ7Ð7ùò "Cs   ÂCc                óô   — | j                   j                  xra t        j                  j	                  «       xrA t        j                  j                  «       xr! t        | j                  j                  «      dv S )aú  Return whether fused AdamW should be used for the current training configuration.

        Fused AdamW is only safe when the trainer's actual precision is a BF16 variant.  Checking GPU capability alone
        (``is_bf16_supported()``) is
        insufficient: on Ampere+ hardware that flag is always ``True`` even when
        the trainer is configured for ``32-true``, which causes a ``params, grads, exp_avgs, and exp_avg_sqs must have
        same dtype, device, and layout`` crash in DDP because gradient bucket views have non-matching strides in FP32.

        Returns:
            ``True`` when fused AdamW is both requested and safe to use.

        Examples:
            >>> from unittest.mock import patch
            >>> module = RFDETRModelModule.__new__(RFDETRModelModule)
            >>> module.model_config = type("Cfg", (), {"fused_optimizer": True})()
            >>> with patch("torch.cuda.is_available", return_value=False):
            ...     module._use_fused_optimizer
            False
        >   ú	bf16-trueú
bf16-mixedÚbf16)	r3   Úfused_optimizerrI   r/   Úis_availableÚis_bf16_supportedrD   rf   Ú	precisionrX   s    rR   Ú_use_fused_optimizerz&RFDETRModelModule._use_fused_optimizer  sd   € ð, ×Ñ×-Ñ-ò SÜ—
‘
×'Ñ'Ó)òSä—
‘
×,Ñ,Ó.òSô �D—L‘L×*Ñ*Ó+Ð/RÐRð		
rS   c                ó(  ‡
‡‡‡— | j                   Št        | j                  ‰«      }t        | j                  d| j                  «      }t        ||«      }|D �cg c]  }|d   j                  sŒ|‘Œ }}t        j                  j                  |‰j                  ‰j                  | j                  ¬«      }t        dt        ‰j                  «      «      }t        | j                   j"                  «      }| j$                  r"t        dt'        j(                  ||z  «      «      n|Št        d‰‰j*                  z  «      Š
t        ‰
‰j,                  z  «      Šd
ˆ
ˆˆˆfd„}t        j                  j.                  j1                  ||¬«      }	||	ddœd	œS c c}w )ak  Build AdamW optimizer with layer-wise LR decay and LambdaLR scheduler.

        Uses ``trainer.estimated_stepping_batches`` for total step count so cosine annealing covers the full training
        run regardless of dataset size or accumulation settings.

        Returns:
            PTL optimizer config dict with optimizer and step-interval scheduler.
        Ú	_orig_modÚparams)r—   Úweight_decayÚfusedr_   c                óv  •— | ‰k  r!t        | «      t        t        d‰«      «      z  S ‰j                  dk(  rpt        | ‰z
  «      t        t        d‰‰z
  «      «      z  }‰j                  d‰j                  z
  dz  dt	        j
                  t        j                  |z  «      z   z  z   S | ‰j                  ‰z  k  ryy)Nr_   Úcosineg      à?g      ð?gš™™™™™¹?)rp   r¥   Úlr_schedulerÚlr_min_factorræ   ÚcosÚpiÚlr_drop)Úcurrent_stepÚprogressÚsteps_per_epochrt   Útotal_stepsÚwarmup_stepss     €€€€rR   Ú	lr_lambdaz9RFDETRModelModule.configure_optimizers.<locals>.lr_lambdaK  s±   ø€ Ø˜lÒ*Ü˜\Ó*¬U´3°q¸,Ó3GÓ-HÑHÐHØ�‰ (Ò*Ü  °Ñ!<Ó=ÄÄcÈ!È[Ð[gÑMgÓFhÓ@iÑi�Ø×'Ñ'¨1¨r×/?Ñ/?Ñ+?À3Ñ*FÈ!ÌdÏhÉhÔW[×W^ÑW^ÐaiÑWiÓNjÑJjÑ*kÑkÐkà˜bŸj™j¨?Ñ:Ò:ØØrS   )r!  ry   )rô   Úinterval)rÀ   r  )r  r¦   Úreturnrp   )r4   r
   r3   r6   r;   r   Úrequires_gradrI   ÚoptimÚAdamWr—   r  r  r¥   r¦   rå   rf   Úestimated_stepping_batchesr7   ræ   ÚceilÚepochsÚwarmup_epochsr  ÚLambdaLR)rN   ÚnsÚmodel_for_paramsÚparam_dictsÚprÀ   rå   Úmicrobatchesr!  rô   r  rt   r  r   s             @@@@rR   Úconfigure_optimizersz&RFDETRModelModule.configure_optimizers  sj  û€ ð ×ÑˆÜ$ T×%6Ñ%6¸Ó;ˆô
 # 4§:¡:¨{¸D¿J¹JÓGÐÜ$ RÐ)9Ó:ˆØ"-ÖK˜Q°°8±×1JÓ1J’qÐKˆÐKÜ—K‘K×%Ñ%ØØ�u‰uØŸ™Ø×+Ñ+ð	 &ó 
ˆ	ô  ˜q¤# b×&9Ñ&9Ó":Ó;ÐÜ˜4Ÿ<™<×BÑBÓCˆð CG×B_ÒB_ŒC�”4—9‘9˜\Ð,<Ñ<Ó=Ô>Ðeqð 	ô ˜a °·	±	Ñ!9Ó:ˆÜ˜?¨R×-=Ñ-=Ñ=Ó>ˆ÷		ð 		ô —K‘K×,Ñ,×5Ñ5°iÈ9Ð5ÓUˆ	ð #Ø*3ÀÑHñ
ð 	
ùòU Ls   ÁFÁ-Fc                óÆ   •— | j                   rB|r?|dkD  r9t        j                  j                  j	                  | j                  «       |«       yyyt        ‰| �  |||¬«       y)a‹  Override PTL gradient clipping to support fused AdamW.

        PTL's AMP precision plugin refuses to clip gradients when the optimizer declares it handles unscaling internally
        (fused=True).  When fused is active we are on BF16 (no GradScaler) so ``clip_grad_norm_`` is correct.  For the
        non-fused path (FP16 + GradScaler or FP32) we delegate to ``super()`` to preserve scaler-aware unscaling.

        Args:
            optimizer: The current optimizer.
            gradient_clip_val: Maximum gradient norm.
            gradient_clip_algorithm: Clipping algorithm; forwarded to super()
                for the non-fused path.
        r   rì   N)r  rI   ÚnnÚutilsÚclip_grad_norm_rÞ   r1   rî   )rN   rÀ   rê   rë   rQ   s       €rR   rî   z RFDETRModelModule.clip_gradients]  s^   ø€ ð$ ×$Ò$Ù Ð%6¸Ò%:Ü—‘—‘×.Ñ.¨t¯©Ó/@ÐBSÕTð &;Ð ô ‰GÑ"ØØ"3Ø(?ð #õ rS   c                ó˜  ‡
‡— |\  }}| j                  |«      }| j                  j                  r[| j                  ||«      Š
| j                  j                  Št        ˆ
ˆfd„‰
D «       «      }| j                  d|dt        |«      ¬«       t        j                  |D �cg c]  }|d   ‘Œ	 c}«      }| j                  ||«      }	|	|dœS c c}w )a*  Run forward pass and postprocess for one test step.

        Mirrors :meth:`validation_step` so ``COCOEvalCallback`` can accumulate results via ``on_test_batch_end`` when
        ``trainer.test()`` is called (e.g. from :class:`~rfdetr.training.callbacks.BestModelCallback` at end of
        training).

        Args:
            batch: Tuple of (NestedTensor samples, list of target dicts).
            batch_idx: Batch index within the test epoch.

        Returns:
            Dict with ``results`` (postprocessed predictions) and ``targets``.
        c              3  ó>   •K  — | ]  }|‰v sŒ‰|   ‰|   z  –— Œ y ­wr‡   rˆ   r‰   s     €€rR   rŽ   z.RFDETRModelModule.test_step.<locals>.<genexpr>Œ  r  r�   z	test/lossT)r“   r”   r˜   r  )r;   r4   Úcompute_test_lossrA   r�   r¤   r¬   r¡   rI   r´   rB   r  s             @@rR   Ú	test_stepzRFDETRModelModule.test_stepy  s³   ù€ ð !Ñˆ�Ø—*‘*˜WÓ%ˆØ×Ñ×.Ò.ØŸ™ w°Ó8ˆIØŸ.™.×4Ñ4ˆKÜÔ\¸iÔ\Ó\ˆDØ�H‰H�[ $°$Ä3ÀwÃ<ˆHÔPä—[‘[¸'Ö!B°Q ! K£.Ò!BÓCˆ
Ø×"Ñ" 7¨JÓ7ˆØ"¨wÑ7Ð7ùò "Cs   ÂCc                óú   — |\  }}t        j                  «       5  | j                  |«      }ddd«       t        j                  |D �cg c]  }|d   ‘Œ	 c}«      }| j	                  |«      S # 1 sw Y   ŒAxY wc c}w )a^  Run inference on a preprocessed batch and return postprocessed results.

        Args:
            batch: Tuple of (NestedTensor samples, list of target dicts).
            batch_idx: Batch index.
            dataloader_idx: Index of the predict dataloader.

        Returns:
            Postprocessed detection results from ``PostProcess``.
        Nr˜   )rI   rj   r;   r´   rB   )	rN   rr   rs   Údataloader_idxrv   r    rº   rÆ   rÇ   s	            rR   Úpredict_stepzRFDETRModelModule.predict_step“  sl   € ð !Ñˆ�Ü�]‰]‹_ñ 	*Ø—j‘j Ó)ˆG÷	*ä—[‘[¸'Ö!B°Q ! K£.Ò!BÓCˆ
Ø×Ñ ¨Ó4Ð4÷	*ð 	*üâ!Bs   šA,ÁA8Á,A5c                ó  — d|v r1d|vr-|d   j                  «       D ��ci c]  \  }}d|z   |“Œ c}}|d<   d|v r#t        |d   | j                  j                  «       d|v r'|d   | _        t        j                  dt        d¬«       yyc c}}w )	u™  Auto-detect legacy formats and reconcile PE shapes at checkpoint load time.

        PTL calls this hook before applying ``checkpoint["state_dict"]`` to the module.  Three normalisation steps are
        applied in order:

        1. **Raw legacy format** â€” a ``*.pth`` file loaded directly by
           ``Trainer`` (e.g. via ``ckpt_path=``).  Recognised by the presence of ``"model"`` without ``"state_dict"``.
           The state dict is rewritten in-place with the ``"model."`` prefix so PTL can apply it normally.

        2. **Positional-embedding interpolation** â€” when the checkpoint was
           saved at a different image resolution than the current model, the DINOv2 ``position_embeddings`` tensor shape
           will mismatch. :func:`~rfdetr.models.weights.interpolate_position_embeddings` is called to bicubic-resize the
           PE to ``model_config.positional_encoding_size`` before PTL applies the state dict.  Regression fix for
           :issue:`998`.

        3. **Converted format** â€” a file produced by
           :func:`~rfdetr.training.checkpoint.convert_legacy_checkpoint` that already has ``"state_dict"`` but also
           carries ``"legacy_ema_state_dict"``.  The EMA weights are stashed on ``self._pending_legacy_ema_state`` for
           optional restoration by :class:`~rfdetr.training.callbacks.ema.RFDETREMACallback`.

        Note:
            This hook only fires on ``Trainer(ckpt_path=...)`` resume paths. Fresh-train bootstrap from a
            ``pretrain_weights`` checkpoint runs through :func:`~rfdetr.models.weights.load_pretrain_weights` during
            ``__init__`` instead â€” that helper performs its own PTL ``.ckpt`` normalisation (``state_dict`` â†’ ``model``
            key, ``_orig_mod`` strip) and PE interpolation, so the two code paths intentionally do not share state.

        Args:
            checkpoint: Checkpoint dict passed in by PTL (mutated in-place).
        r;   Ú
state_dictzmodel.Úlegacy_ema_state_dictz²Checkpoint contains legacy EMA weights (`legacy_ema_state_dict`). Add RFDETREMACallback to your trainer callbacks to restore them; without it the stashed weights will be ignored.r�   )Ú
stacklevelN)r«   r   r3   Úpositional_encoding_sizeÚ_pending_legacy_ema_stateÚwarningsÚwarnÚUserWarning)rN   Ú
checkpointr‹   r¿   s       rR   Úon_load_checkpointz$RFDETRModelModule.on_load_checkpoint¤  s¨   € ð> �jÑ  \¸Ñ%CØDNÈwÑDW×D]ÑD]ÓD_×'`¹D¸A¸q¨°1©°a©Ó'`ˆJ�|Ñ$ð ˜:Ñ%Ü+Ø˜<Ñ(Ø×!Ñ!×:Ñ:ôð # jÑ0Ø-7Ð8OÑ-PˆDÔ*Ü�M‰MðBô Øöð 1ùó (as   ŸB	c                ó:   — | j                   j                  |«       y)z•Reinitialize the detection head for a new class count.

        Args:
            num_classes: New number of classes (excluding background).
        N)r;   Úreinitialize_detection_head)rN   Únum_classess     rR   rI  z-RFDETRModelModule.reinitialize_detection_headÜ  s   € ð 	�
‰
×.Ñ.¨{Õ;rS   )r3   r   r4   r   r#  ÚNone)r#  rK  )rr   r   rs   r¦   r#  rK  )rr   r   rs   r¦   r#  ztorch.Tensor | dict[str, Any])rº   údict[str, torch.Tensor]r    úlist[dict[str, torch.Tensor]]r#  z:tuple[dict[str, torch.Tensor], torch.Tensor, torch.Tensor])r»   útorch.Tensorr¼   rN  r#  rN  )rz   rN  r#  rK  )rs   r¦   r#  r5   )rÀ   útorch.optim.Optimizerr#  rK  )rŸ   rM  r#  rM  )rž   rN  rŒ   rL  r”   r¦   r#  rK  )rr   r   rs   r¦   r#  úDict[str, Any])r#  r5   )r#  rP  )NN)rÀ   rO  rê   zOptional[float]rë   zOptional[str]r#  rK  )r   )rr   r   rs   r¦   r;  r¦   r#  r   )rF  zdict[str, Any]r#  rK  )rJ  r¦   r#  rK  )rÒ   Ú
__module__Ú__qualname__Ú__doc__r2   rY   r{   r„   rÊ   r¢   r£   rØ   r±   r²   rï   Ústaticmethodr¹   r­   rÿ   r  Úpropertyr  r1  rî   r9  r<  rG  rI  Ú__classcell__)rQ   s   @rR   r(   r(   *   sW  ø„ ñõ?AóJUóó20ó6\^ð|#/à(ð#/ð /ð#/ð 
Dó	#/ðJ1àð1ð !ð1ð 
ó	1ó,hó
ó>0ó6
"ð ò
ó ð
ð#àð#ð +ð#ð
 ð#ð 
ó#ðJhàðhð +ðhð
 ðhð 
óhó.8ð2 ò
ó ð
ó6>
ðF .2Ø15ð	à(ðð +ðð "/ð	ð
 
õó88ô45ó"6÷p<rS   r(   ))rS  Ú
__future__r   ræ   rh   rC  Útypingr   r   r   r   rI   Útorch.nn.functionalr3  Ú
functionalrk   Úpytorch_lightningr   r	   Úrfdetr._namespacer
   rC   r   r   Úrfdetr.datasets.cocor   Úrfdetr.models.lwdetrr   r   Úrfdetr.models.weightsr   r   r   Úrfdetr.training.param_groupsr   Úrfdetr.utilities.loggerr   r>   r&   Ú__annotations__r(   rˆ   rS   rR   ú<module>rc     s�   ðò ;å "ã Û Û ß -Ó -ã ß Ð ß >å 5ß 2Ý ;ß Uß dÑ dÝ 7Ý .á	‹€ð ØØØØ!Ø Ø(Ø&Ø"ñ
0Ð ˜nó 
ôx
<˜õ x
<rS   