
    ^jeW                        U d Z ddlmZ ddlmZ ddlmZ ddlZddlm	c m
Z ddlm	Z	 ddlmZ  e       ZdZd	ed
<   ddZ G d de	j$                        Z	 	 	 	 	 	 	 	 	 	 	 	 ddZddZ	 	 	 	 	 	 	 	 	 	 	 	 ddZg dZy)u  Keypoint helper primitives for GroupPose-style decoding.

Keypoint predictions are dense ``[N, K, KEYPOINT_PRED_DIM]`` tensors where the trailing channel layout is fixed:

================  ===========  ==========================================================
Slot index        Name         Meaning
================  ===========  ==========================================================
``0``             ``x``        Normalized x coordinate (image-relative).
``1``             ``y``        Normalized y coordinate (image-relative).
``2``             ``findable`` Logit for "annotator could find this keypoint" (``v > 0``).
``3``             ``visible``  Logit for "fully visible" (``v == 2``).
``4`` – ``6``     ``L_*``      Lower-triangular Cholesky parameters ``Lxx``, ``Lxy``, ``Lyy``.
``7``             ``class``    Per-keypoint class-logit contribution aggregated into detection-class logits.
================  ===========  ==========================================================
    )annotations)Sequence)castN)nn)
get_logger   intKEYPOINT_PRED_DIMc                    |dz   | z  |z   S )u$  Apply AdaLN modulation to a feature tensor.

    Args:
        features: Input feature map to modulate.
        scale: Per-feature scale terms.
        shift: Per-feature shift terms.

    Returns:
        Modulated features with the same shape as ``features``.

    Example:
        Apply modulation to a batch of 2 query tokens, each with 4 channels:

        .. code-block:: python

            features = torch.zeros(2, 4)          # (batch, dim)
            scale    = torch.ones(2, 4) * 0.1     # small positive scale
            shift    = torch.ones(2, 4) * (-0.5)  # constant shift

            out = modulate(features, scale, shift)
            # scale=0.1 → effective multiplier is 1.1; shift=-0.5 applied additively
            # out[0] ≈ tensor([-0.5000, -0.5000, -0.5000, -0.5000])
    g      ? )featuresscaleshifts      h/var/www/ramen.bs-engineer-server.com/venv/lib/python3.12/site-packages/rfdetr/models/heads/keypoints.pymodulater   '   s    2 CK8#e++    c                  .     e Zd ZdZdd fdZddZ xZS )ConditionalQueryInitializerzTInitialize keypoint query tokens with adaptive layer-normalization style modulation.c           	        t         |           |xs |}t        j                  t	        j
                  ||            | _        t        j                  |d      | _        t        j                  t        j                  ||      t        j                         t        j                  ||dz              | _        t        t        j                  | j                  d         }t        j                  j                  |j                   d       t        j                  j                  |j"                  d       t        j                  ||      | _        y)zCreate the initializer.

        Args:
            dim: Query conditioning dimensionality.
            num_queries: Number of query tokens to instantiate.
            out_dim: Output embedding size. Defaults to ``dim``.
        F)elementwise_affine   r   N)super__init__r   	Parametertorchrandnqueries	LayerNorm
query_norm
SequentialLinearGELUadaLN_modulationr   init	constant_weightbiasout_proj)selfdimnum_queriesout_dimada_ln_projection	__class__s        r   r   z$ConditionalQueryInitializer.__init__F   s     	.S||EKKW$EF,,w5I "IIc3GGIIIc7Q;'!

 !D,A,A",EF
+22A6
+00!4		'73r   c                2   | j                  | j                        }| j                  |j                  d            }|j	                  dd      \  }}}| j                  t        |||            |z  | j                  z   }t        t        j                  |      S )ax  Return modulated query embeddings.

        Args:
            query_features: Tensor of shape ``(B, dim)`` containing conditioning features.

        Returns:
            Tensor of shape ``(B, num_queries, out_dim)`` with initialized keypoint queries.

        Example:
            Initialize 17 keypoint queries conditioned on a batch of 2 detection embeddings:

            .. code-block:: python

                initializer = ConditionalQueryInitializer(dim=256, num_queries=17)
                query_features = torch.randn(2, 256)   # (B=2, dim=256)

                keypoint_queries = initializer(query_features)
                # keypoint_queries.shape == (2, 17, 256)
                # Each of the 17 query slots is independently modulated by the
                # per-detection conditioning vector before being passed to the
                # GroupPose keypoint decoder.
        r   r   r+   )
r    r   r$   	unsqueezechunkr)   r   r   r   Tensor)r*   query_featuresnormed_query_features
modulationr   r   gatemodulated_query_featuress           r   forwardz#ConditionalQueryInitializer.forward^   s    0 !% =#'#8#89Q9QRT9U#V
'--aR-8ud#'==:OQVX]1^#_bf#fimiuiu#u ELL":;;r   )N)r+   r	   r,   r	   r-   z
int | NonereturnNone)r6   torch.Tensorr<   r>   )__name__
__module____qualname____doc__r   r;   __classcell__)r/   s   @r   r   r   C   s    ^40<r   r   c                j   | j                   \  }}}|dk\  sJ d       t        |      }|dk(  rt        d      |dkD  rX|j                         |k\  rEt        j                  dt        |j                               |       | j                  |      }	|	|	|	|	fS ||z  }
| j                  |||
|      }|t        j                  ||j                        |f   }t        j                  ||
t        j                  |j                        }t        |      D ]  \  }}d||d	|f<    ||   }|j                  d
      j!                  |j"                        }|j!                  t        j$                        }t        j&                  |j"                        j(                  }t        j*                  |      ||kD  z  }t        j*                  |d	d	d	d	d	df         j-                  d
      t        j*                  |d	d	d	d	d	df         j-                  d
      z  }t        j*                  |d	d	d	d	df         |d	d	d	d	df   dkD  z  }||z  |z  |j/                  d      z  }|j                  d
      j!                  |j"                        }|j1                  d      }|j1                  d      j!                  |j"                        }|j3                  |      j5                         }t7        j8                  |d	d	d	d	d	df   |d	d	d	d	d	df   d      j                  d
      |j!                  |j"                        z  |j/                  d      z  }|j                  d
      |z  }t7        j:                  |d	d	d	d	df   |d	d	d	d	df   dkD  j!                  |j"                        d      |j!                  |j"                        z  j                  d
      |z  }t7        j:                  |d	d	d	d	df   |d	d	d	d	df   dkD  j!                  |j"                        d      |j!                  |j"                        z  j                  d
      |z  }|d	d	d	d	d	df   |d	d	d	d	d	df   z
  j!                  t        j$                        } | d	d	d	d	df   }!| d	d	d	d	df   }"|d	d	d	d	df   j!                  t        j$                        }#|d	d	d	d	df   j!                  t        j$                        }$|d	d	d	d	df   j!                  t        j$                        }%t        j*                  |#      t        j*                  |$      z  t        j*                  |%      z  }&|&j-                         s3t        j=                  d|& j                         j?                                ||&z  }'|#}(|$})|%}*|(jA                         }+|*jA                         },|+|!z  |)|"z  z   }-|,|"z  }.|-|-z  |.|.z  z   }/|'t        j*                  |-      z  t        j*                  |.      z  t        j*                  |/      z  }'|'j                  d
      j!                  |j"                        }0|0j1                  d      }1d|/|j3                  |      j/                  d      z  z  |(|*z   z
  }2t        jB                  |2ddt        j&                  |2j"                        jD                        }2|2jG                  |' d      }3|3j                  d
      |1z  }4|0dk  }5t        jH                  |5t        jJ                  |4      |4      }4||||4fS )uA	  Compute the keypoint loss vector per matched target.

    The tensor layout follows GroupPose-style keypoints where each target class
    defines how many valid keypoints it owns. The returned Gaussian NLL follows
    the r-flow formulation directly:
    ``0.5 * maha2 / area - (log_l11 + log_l22)``. It intentionally omits the
    normal Gaussian constant and does not clamp the precision Cholesky
    parameters, so valid losses may be negative.

    Args:
        all_pred_keypoints: Predicted keypoints with shape ``(N, K_total, >=7)``.
        target_keypoints: Ground truth keypoints with shape ``(N, K_max, 3)``.
        target_classes: Class ids per target with shape ``(N,)``.
        target_areas: Target box areas with shape ``(N,)``.
        num_keypoints_per_class: Number of keypoints per class.

    Returns:
        Tuple of location, findable BCE, visible BCE, and raw Gaussian NLL losses.
        Each tensor has shape ``(n_targets,)``.

    Example:
        Compute losses for 2 matched targets, each with 17 keypoints (COCO layout):

        .. code-block:: python

            n_targets, K, pred_dim = 2, 17, 7
            all_pred_keypoints = torch.randn(n_targets, K, pred_dim)

            # Ground truth: 17 keypoints per target, each (x, y, visibility)
            # visibility: 0=not labeled, 1=labeled but occluded, 2=fully visible
            target_keypoints = torch.rand(n_targets, K, 3)
            target_keypoints[:, :, 2] = 2.0   # mark all keypoints fully visible

            target_classes = torch.zeros(n_targets, dtype=torch.long)  # single class (person)
            target_areas   = torch.tensor([0.05, 0.12])  # normalized box areas

            loc_loss, findable_loss, visible_loss, nll_loss = compute_l1_keypoint_loss(
                all_pred_keypoints,
                target_keypoints,
                target_classes,
                target_areas,
                num_keypoints_per_class=[17],
            )
            # Each output tensor has shape (2,) — one scalar loss per matched target.
            # loc_loss:      area-normalized mean L1 distance for visible keypoints
            # findable_loss: BCE for "annotator could locate this keypoint"
            # visible_loss:  BCE for "keypoint is fully visible (v==2)"
            # nll_loss:      Gaussian NLL incorporating Cholesky uncertainty parameters
       IExpected all_pred_keypoints last dim >= 7 (x,y,2 logits + 3 chol params).r   zInum_keypoints_per_class must be non-empty when computing keypoint losses.ztarget_classes max index %d >= num_keypoints_per_class length %d; skipping keypoint loss for this batch to avoid crashing training. Check that your keypoint schema covers all annotation classes.)device)dtyperG   TNr   rH      r2      minnone)	reductionr            zGNLL loss: %d keypoint(s) with non-finite uncertainty dropped from loss.      ?        nanposinfneginf)&shapelen
ValueErrormaxloggerwarningr	   	new_zerosviewr   arangerG   zerosbool	enumeratesumtorH   float32finfoepsisfiniteallr3   clamp	clamp_minsqrtFl1_loss binary_cross_entropy_with_logitsdebugitemexp
nan_to_numrM   masked_fillwhere
zeros_like)6all_pred_keypointstarget_keypointstarget_classestarget_areasnum_keypoints_per_class	n_targetstotal_padded_num_keypointspred_dimnum_classesrb   kpadsplit_pred_keypointsselected_pred_keypointsactive_keypoints_mask	class_idxnum_keypointskeypoints_loss_maskkeypoints_per_targetareaarea_eps
valid_areavalid_xyvalid_visibilitylocation_loss_masklocation_countvalid_countdenom_keypointssafe_area_sqrtscaled_masked_l1location_lossfindable_lossvisible_lossdxdydxdyraw_log_l11raw_l21raw_log_l22finite_uncertaintygaussian_loss_masklog_l11l21log_l22l11l22u0u1maha2gaussian_countgaussian_valid_countnll_rawnll_keypointsnll_lossno_valids6                                                         r   compute_l1_keypoint_lossr   }   s   r 7I6N6N3I)8q=eee=-.Kadee1}++-<M ""$%	
 #,,Y7eUE))%4D-229k4QYZ2Y';'B'BC^S "KKTThToTop$-.E$F @ 	=;?i-78@ 0?.222699@W@]@]9^??5==)D{{4::&**H%9J~~5aBQBh?@DDDLu~~Arr"P	cbckH ~~&6q!Qw&?@DTUVXY[\U\D]`aDab,/??(JZMaMabcMdd'++B/229P9V9V2WN &&1&-K*00Q07::AXA^A^:_O^^H-224N 	
		)!Q(35EaBQBh5O[abffgij


 7 = =
>	?

"
"1
%	& 
 %((,{:M 	
**#Aq!G,aAg&*../F/L/LM	

 
 
 !8!>!>
?	@ 
c"g M 	
**#Aq!G,aAg&*../F/L/LM	

 
 
 !8!>!>
?	@ 
c"g L $Aq"1"H-0@Arr0JJNNu}}]D	aAgB	aAgB)!Q'255emmDK%aAg.11%--@G)!Q'255emmDK4u~~g7NNQVQ_Q_`kQll!!#U  %%',,.	
 ,.@@ G
CG
++-C
++-C	rC"H	B	rBGb2gE+ennR.@@5>>RTCUUX]XfXfglXmm'++B/229P9V9V2WN)//A/6UT^^H5??BBCwQXGXYGwCEKKPWP]P]D^DbDbcG'');(;SAM  $';;H"H{{8U%5%5h%?JH -x??r   c                    |j                  | j                        }t        j                  |       j	                  dd      }t        j                  | |j                               }||z
  S )z;Compute pairwise BCE-with-logits summed along the last dim.rI   rK   T)r+   keepdim)rf   rH   ro   softplusre   r   matmult)xyy_floatr   dots        r   _cdist_bce_with_logitsr   #  sS    ddd!Gzz!}  Q 5H
,,q'))+
&Cc>r   c           	     H   | j                   \  }}}}|dk\  sJ d       |j                   d   }	t        |      }
|
dk(  rt        d      |	dk(  r5t        j                  |||	f| j
                  | j                        }||||fS ||
z  }| j                  |||
||      }t        j                  |||	f| j
                  | j                        }t        j                  |||	f| j
                  | j                        }t        j                  |||	f| j
                  | j                        }t        j                  |||	f| j
                  | j                        }||z  }t        |
      D ]2  }||k(  j                         j                  d      }|j                         dk(  r:||   }|dk(  rE|dddd|d|ddf   }|j                  d|      ddd|ddf   }|j                   d   }|j                  d|      j                  t        j                        }t        j                  |j                        j                   }t        j"                  |      ||kD  z  }|ddddddf   }t        j"                  |dddddf         |dddddf   dkD  z  t        j"                  |      j%                  d	
      z  |j'                  d      z  }|j)                  d
      j                  t        j                        }|j+                  d      }|dkD  } |j-                  |      j/                         }!|ddddddddf   j1                  ||d      j                  t        j                        }"|j                  t        j                        }#|"j'                  d      |#j'                  d      z
  }$|$j3                         j)                  d	      }%|j'                  d      }&|%j5                  |& d      }%|%j)                  d	      }'|'|j'                  d      z  j7                  |!j'                  d            }(t        j8                  |(ddd      }(|(j1                  |||      j                  | j                        |dddd|f<   |dddddddf   j1                  ||      j                  t        j                        })|dddddddf   j1                  ||      j                  t        j                        }*|dddddddf   j1                  ||      j                  t        j                        }+|)},|*}-|+}.|,j;                         }/|.j;                         }0t        j"                  |"      j%                  d	
      }1|1t        j"                  |)      z  t        j"                  |*      z  t        j"                  |+      z  }2|$d   }3|$d   }4|/j'                  d      |3z  |-j'                  d      |4z  z   }5|0j'                  d      |4z  }6|5|5z  |6|6z  z   }7|&|2j'                  d      z  t        j"                  |5      z  t        j"                  |6      z  t        j"                  |7      z  }8d|7|j-                  |      j                  d|d      z  z  |,|.z   j'                  d      z
  }9t        j8                  |9ddt        j                  |9j                        j<                        }9|9j5                  |8 d      }9|9j)                  d	      }:|:|j'                  d      z  j1                  |||      };|;j?                  | j'                  d       d       |;j                  | j                        |dddd|f<   |dddddddf   j1                  ||      }<|dddddf   dkD  j                  | j                        j1                  ||      }=|dddddddf   j1                  ||      }>|dddddf   dkD  j                  | j                        j1                  ||      }?tA        |<|=      j1                  |||      tC        |      z  |dddd|f<   tA        |>|?      j1                  |||      tC        |      z  |dddd|f<   5 ||||fS )u  Compute many-to-many keypoint matching costs.

    Args:
        all_pred_keypoints: Predicted keypoints of shape ``(B, Q, K_total, >=7)``.
        target_keypoints: Ground truth keypoints with shape ``(N, Kmax, 3)``.
        target_classes: Class ids for each target with shape ``(N,)``.
        target_areas: Target box areas with shape ``(N,)``.
        num_keypoints_per_class: Number of keypoints per class.

    Returns:
        Tuple ``(cost_l1, cost_findable, cost_visible, cost_nll)`` each of shape ``(B, Q, N)``.

    Example:
        Compute matching costs for 1 image with 4 decoder queries against 2 ground-truth
        targets, each with 17 COCO keypoints:

        .. code-block:: python

            B, Q, K_total, pred_dim = 1, 4, 17, 7
            n_targets = 2

            all_pred_keypoints = torch.randn(B, Q, K_total, pred_dim)

            target_keypoints = torch.rand(n_targets, K_total, 3)
            target_keypoints[:, :, 2] = 2.0   # mark all keypoints fully visible

            target_classes = torch.zeros(n_targets, dtype=torch.long)  # single class (person)
            target_areas   = torch.tensor([0.05, 0.12])

            cost_l1, cost_findable, cost_visible, cost_nll = compute_keypoint_matching_cost(
                all_pred_keypoints,
                target_keypoints,
                target_classes,
                target_areas,
                num_keypoints_per_class=[17],
            )
            # Each output tensor has shape (1, 4, 2) — (B, Q, N).
            # cost_l1[:, q, n]  is the area-normalized L1 cost for query q against target n.
            # cost_nll[:, q, n] incorporates the Cholesky precision uncertainty.
            # These cost matrices are passed to the Hungarian matcher.
    rE   rF   r   zQnum_keypoints_per_class must be non-empty when computing keypoint matching costs.)rG   rH   rK   NrJ   r   r2   rL   rT   rU   rP   rQ   rR   ).r   ).rK   rS   r   )"rY   rZ   r[   r   rb   rG   rH   r`   rangenonzerosqueezenumelindex_selectrf   rg   rh   ri   rj   rk   r3   re   rl   rm   rn   reshapeabsrv   divru   rt   rM   masked_fill_r   float)@ry   rz   r{   r|   r}   br,   total_num_keypointsr   r~   r   rb   r   predcost_l1cost_findablecost_visiblecost_nllflat_bqr   target_indicesnum_kptspred_by_classtarget_by_classn_targets_by_classareasr   r   	target_xyvisiblevalid_per_target	nll_denomhas_visible	area_sqrtpred_xy_flattarget_xy_f32diff
per_kpt_l1visible_btk
scaled_locloc_costr   r   r   r   r   r   r   r   	finite_xyfinite_predr   r   r   r   r   keypoint_masknll_knll_summean_nllpred_findabletarget_findablepred_visibletarget_visibles@                                                                   r   compute_keypoint_matching_costr   +  sO   b 5G4L4L1A{'q=eee= &&q)I-.KalmmA~Y'%,,$**

 eUE))+-D""1k;hODkk	
K#!(( &&G
 KK	
K#!(( &&M
 ;;	
K#!(( &&L
 {{	
K#!(( &&H +oG;' q	(I5>>@HHK!Q&*95q=Q9ixi:;*77>J1ixiYZ?[,2215))!^<??N;;u{{+//^^E*eh.>?
#Aq"1"H-	NN?1a734q!Qw'!+-nnY'+++34 ""1%& 	 #;;1;-00?$**q*1	&*OOH-224	 %Q1bqb[199'8QORRSXS`S`a!U]]3 %%a(=+B+B1+EEXXZ^^B'
''*++[L#>
^^B'
!4!4Q!77<<Y=P=PQR=ST##H#c#N(0(8(8)
 "%%
&	 	1n$% $Aq!QJ/77JMMemm\1a
+33GXFII%--X#Aq!QJ/77JMMemm\kkmkkmNN<0444<	%.."==w@WWZ_ZhZhitZuu&\&\]]1"S]]1%5%::]]1"R"r'! +//22U^^B5GG%..Y[J\\_d_m_mns_tt 	 uux8==aASUVWWXg
)A,   CEKKPUP[P[D\D`D`a!!=.#6))B-i11!44==aN`a{44Q77=)15G5M5M)NA~%&%aAqj199'8LQ1W%)R"(()W" 	 %Q1aZ088(KQ1W%)R"(()W" 	 /E]Tc.d.l.l/
 (O	/aN*+
 .DLR`-a-i-i.
 (O	.Q>)*[qj M<99r   )r   r   r   )r   r>   r   r>   r   r>   r<   r>   )ry   r>   rz   r>   r{   r>   r|   r>   r}   zSequence[int]r<   z=tuple[torch.Tensor, torch.Tensor, torch.Tensor, torch.Tensor])r   r>   r   r>   r<   r>   )rB   
__future__r   collections.abcr   typingr   r   torch.nn.functionalr   
functionalro   rfdetr.utilities.loggerr   r]   r
   __annotations__r   Moduler   r   r   r   __all__r   r   r   <module>r      s     # $      .	  3 ,87<")) 7<tc@$c@"c@ !c@ 	c@
 +c@ Cc@LO:$O:"O: !O: 	O:
 +O: CO:dr   