o
    »j`V  ã                   @  sê   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m	Z	m
Z
 ddlZddlZddlmZ ddlmZ e d¡Zd	Zd
ZdZdZeeee ƒƒeeeƒƒksSJ dƒ‚dZdZdZdZdZdZdZ ddd„Z!ddd„Z"G dd„ deƒZ#dS )u  BlendshapeDataset â€” loads (audio, cond, target) from data_pipeline.py .npz.

Each .npz contains:
  audio:  (T, 80)  log-mel features at 30 fps
  cond:   (T, 19)  16-dim emotion one-hot + 3-dim VAD per frame
  target: (T, 52)  ARKit blendshape values

Split membership is derived from the JSONL files in data/emotion/
(seed_train_final.jsonl / seed_val.jsonl / seed_test.jsonl).

For daily-split scenarios (per-turn pseudo-scenarios like `daily_007_t2`),
parent membership is checked: if the parent dialogue is in the split's JSONL,
all its per-turn splits belong to that split.

Crops:
  - Sequences longer than `crop_frames`  â†’ random window crop
  - Sequences shorter than `crop_frames` â†’ edge-pad to crop_frames + return
    `valid_length` so the trainer can mask loss to real frames only.
é    )ÚannotationsN)ÚPath)ÚListÚSetÚTuple)Úgaussian_filter1d)ÚDatasetz^(daily_.+)_t(\d+)$)é   é   é   é   é   é   é   é    é!   é"   é#   é$   é%   é&   é'   é(   é)   é*   é-   é.   é/   é0   é3   )r   é   é   é   é   é   é   é   é   é   é   é   é   é   é   é+   é,   é1   é2   )r   r    r!   r"   r#   r$   r%   r&   r'   r(   r)   )r*   r+   r,   r-   r.   r/   r0   r1   zsplit must partition EMOTIONAL)r   r   r   r   r   r   gš™™™™™Ù?r   )r    r!   r"   r	   r!   ©r   r    r!   r"   r#   ©r(   r)   ÚsidÚstrÚreturnc                 C  s6   |   d¡rdS |   d¡rdS |   d¡rd| v rdS dS )NÚlong_Úsolo_Údaily_Ú_tzdaily_-splitÚother)Ú
startswith)r4   © r=   úN/dataset/kemix-engine/package/face/animasync-face-v3/models/v3_face/dataset.pyÚ	_classifym   s   

r?   c                 C  s   t  | ¡}|r| d¡S | S )uD   Daily-split id â†’ parent dialogue id. Pass through for long_/solo_.r    )Ú	_SPLIT_REÚmatchÚgroup)r4   Úmr=   r=   r>   Ú_parent_sidw   s   
rD   c                   @  sb   e Zd Z																d.d/dd„Zd0d!d"„Zd1d$d%„Zd2d3d)d*„Zd4d,d-„ZdS )5ÚBlendshapeDatasetéð   ç      ð?Nç        Fçffffffæ?Únpz_dirr   Úsplit_jsonlÚcrop_framesÚintÚlipsync_target_gainÚfloatÚexpression_target_gainÚemotional_mouth_target_gainúfloat | NoneÚplosive_damp_targetÚsmooth_target_sigma_browÚsmooth_target_sigma_eye_squintÚsmooth_target_sigma_eye_wideÚbrow_innerup_happy_gainÚbrow_happy_gainÚbrow_target_gainÚbrow_surprise_gainÚeye_wide_maxÚ	soft_clipÚboolÚsoft_clip_kneeÚsmooth_cond_sigma_emotionc                 C  sž  t |ƒ| _t|ƒ| _t|ƒ| _t|ƒ| _|d u r|}t|ƒ| _|| _t	j
dt	jd| _tD ]}| j| j|< q-tD ]}| j| j|< q8tD ]}| j| j|< qC| jd ur^tD ]
}t| jƒ| j|< qS| jdkpx| jdkpx| jdkpx| jd uoxt| jƒdk| _|d u r€d nt|ƒ| _t|ƒ| _t|ƒ| _d| j | _t|ƒ| _t|ƒ| _t	jdtd| _tD ]}d| j|< q©t|ƒ| _t|	ƒ| _t|
ƒ| _g | _| jdkrÑ| j  d| jf¡ | jdkrß| j  d| jf¡ | jdkrí| j  d| jf¡ || _!|| _"|d u rùd nt|ƒ| _#t$ƒ }t |ƒ %¡ }|D ]}t& '|¡}| (|d	 ¡ q
W d   ƒ n	1 s%w   Y  g | _)t*| j +d
¡ƒD ]}|j,}t-|ƒ|v rK| j)  |t.|ƒf¡ q5d S )Né4   ©ÚdtyperG   TrH   r2   )r&   r'   r3   Úscenario_idz*.npz)/r   rJ   rM   rL   rO   rN   rP   rQ   rY   ÚnpÚonesÚfloat32Ú_target_gainÚPURE_LIPSYNC_CHANNELSÚEMOTIONAL_PURE_CHANNELSÚEMOTIONAL_MOUTH_CHANNELSÚBROW_CHANNELSÚ_gain_activer[   r]   r\   r^   Ú_soft_clip_one_minus_kneer_   rS   ÚzerosÚ_plosive_damp_maskÚPLOSIVE_DAMP_CHANNELSrT   rU   rV   Ú_smooth_groupsÚappendrW   rX   rZ   ÚsetÚopenÚjsonÚloadsÚaddÚentriesÚsortedÚglobÚstemrD   r?   )ÚselfrJ   rK   rL   rN   rP   rQ   rS   rT   rU   rV   rW   rX   rY   rZ   r[   r\   r^   r_   ÚchÚ	split_idsÚfÚlineÚrowÚpr4   r=   r=   r>   Ú__init__~   s„   



	


ÿþ
ü	ÿ









ÿ
þÿ€ýzBlendshapeDataset.__init__r6   c                 C  s
   t | jƒS )N)Úlenrx   )r|   r=   r=   r>   Ú__len__ý   s   
zBlendshapeDataset.__len__Úidxc              	   C  s   | j | \}}t | j|› d ¡}|d  tj¡}|d  tj¡}|d  tj¡}| jdkrHt|d d …d d…f | jddd	|d d …d d…f< | jrk| jD ]\}}	|D ]}
t|d d …|
f |	dd
|d d …|
f< qTqN| j	ry|| j
d d d …f  }t| j
t ƒ}| jd urÅ| j	rÅ|dkrÅ|d d …ttƒf jdd}t |dd¡}| jdkr®t|| jdd
}d| || j|   }|d d …tf  |9  < | jd ur| j	r|d d …ttƒf jdd}t |dd¡}| jdkrñt|| jdd
}tD ]&}
t| j
|
 ƒ}|dkrqód| || j|   }|d d …|
f  |9  < qó| jd ur^| jdkr^t |d d …df |d d …df ¡}t |d d dd¡}d|t| jƒ  }tD ]}
|d d …|
f  |9  < qN| jdkr—|d d …tf }t |t dt  dd¡}t dd| j|  ¡}|d d …| jf  |d d …d f 9  < | jd ur¼| jdk r¼tD ]}
t |d d …|
f | j¡|d d …|
f< q¥| j	sÐ| jdksÐ| jd usÐ| jr| jrú| j}| j }t !||kd|t "||  | ¡  |¡}t |d¡ tj¡}nt |dd¡ tj¡}|j#d }|| j$kr=t%tj& 'd|| j$ d ¡ƒ}|||| j$ … }|||| j$ … }|||| j$ … }| j$}n+| j$| }tj(|d|fdfdd}tj(|d|fdfdd}tj(|d|fdfdd}|}t) *|¡t) *|¡t) *|¡t)j+|t)j,d||dœS )Nz.npzÚaudioÚcondÚtargetrH   é   r   Únearest)ÚsigmaÚaxisÚmode)rŒ   rŽ   rG   r    )r   r(   r)   gš™™™™™¹?gš™™™™™É?)r   r   Úedge)rŽ   ra   )r‡   rˆ   r‰   Úvalid_lengthrc   Úcategory)-rx   rd   ÚloadrJ   Úastyperf   r_   r   rq   rl   rg   rO   ÚBROW_INNERUP_CHrW   ÚlistÚHAPPY_EMOTION_INDICESÚsumÚcliprT   rX   rk   rZ   ÚmaximumrS   ÚMOUTH_CLOSE_CHÚPLOSIVE_TRIGGERro   r[   ÚEYE_WIDE_CHANNELSÚminimumr\   r^   rm   ÚwhereÚexpÚshaperL   rM   ÚrandomÚrandintÚpadÚtorchÚ
from_numpyÚtensorÚlong)r|   r†   r4   ÚcatÚdatar‡   rˆ   r‰   ÚchsrŒ   r}   Ú	full_gainÚhappyÚadjustÚfull_gain_chÚeye_wideÚ	wide_rampÚbrow_factorÚmcÚtÚattenÚkÚone_minus_kÚTÚstartr   r£   r=   r=   r>   Ú__getitem__   s¾   
þ	ÿÿ
ÿ
þÿ
þ
	$&*ý

úzBlendshapeDataset.__getitem__ç      @Úlong_weightú
np.ndarrayc                 C  sB   t jt| jƒt jd}t| jƒD ]\}\}}|dkr|||< q|S )u  Sample weights for WeightedRandomSampler.

        Long_ scenarios get `long_weight`, everything else gets 1.0.
        Used to compensate for the 5715 daily-split + 253 solo_ vs only 363
        long_ files â€” without this, the model sees ~6% multi-emotion gradient.
        ra   r7   )rd   re   r„   rx   rf   Ú	enumerate)r|   r»   ÚweightsÚiÚ_r¨   r=   r=   r>   Úget_sample_weights¡  s   €z$BlendshapeDataset.get_sample_weightsÚdictc                 C  s,   i }| j D ]\}}| |d¡d ||< q|S )Nr   r    )rx   Úget)r|   ÚcountsrÀ   r¨   r=   r=   r>   Úcategory_counts®  s   z!BlendshapeDataset.category_counts)rF   rG   rG   NrH   rH   rH   rH   NNNNNFrI   rH   )$rJ   r   rK   r   rL   rM   rN   rO   rP   rO   rQ   rR   rS   rO   rT   rO   rU   rO   rV   rO   rW   rR   rX   rR   rY   rR   rZ   rR   r[   rR   r\   r]   r^   rO   r_   rO   )r6   rM   )r†   rM   )rº   )r»   rO   r6   r¼   )r6   rÂ   )Ú__name__Ú
__module__Ú__qualname__rƒ   r…   r¹   rÁ   rÅ   r=   r=   r=   r>   rE   }   s.    í

 "rE   )r4   r5   r6   r5   )$Ú__doc__Ú
__future__r   ru   ÚreÚpathlibr   Útypingr   r   r   Únumpyrd   r¤   Úscipy.ndimager   Útorch.utils.datar   Úcompiler@   rh   ÚEMOTIONAL_CHANNELSri   rj   Útuplery   rp   r›   rš   r–   r”   rk   rœ   r?   rD   rE   r=   r=   r=   r>   Ú<module>   s<    

ÿÿ


