
    
i                    Z    S r SSKJr  SSKJrJr  SSKrSSKJr   " S S5      r	\	" 5       r
g)u  Lazy loader for ``pytorch_wavelets`` DWT1D modules used by DCW.

Splitting this out keeps :mod:`acestep.models.common.dcw_correction` under
the project's 200-LOC module cap.

We import ``pytorch_wavelets`` lazily so the dependency stays optional —
DCW is opt-in, and users who don't enable it never touch this code path.
If the import fails when DCW *is* enabled, we log a single warning and
return ``None`` so callers can short-circuit to a no-op.
    )annotations)OptionalTupleN)loggerc                  B    \ rS rSrSrSS jrS r        S	S jrSrg)
_LazyWavelet   zLazy loader for ``pytorch_wavelets`` DWT1D modules.

We cache one ``DWT1DForward`` / ``DWT1DInverse`` pair per
``(device, dtype, wavelet)`` triple so repeated sampler steps don't
keep rebuilding the filter banks.
c                     0 U l         SU l        g )NF_cache_import_failed)selfs    W/mnt/workspace/acestep.cpp/tests/../../ACE-Step-1.5/acestep/models/common/dcw_loader.py__init___LazyWavelet.__init__   s    #    c                    U R                   (       a  g  SSKJnJn  X4$ ! [         a     SU l         [
        R                  " S5         g f = f)Nr   )DWT1DForwardDWT1DInverseTzDCW is enabled but 'pytorch_wavelets' is not installed. Install with `pip install pytorch_wavelets PyWavelets` to use Differential Correction in Wavelet domain. Falling back to no-op for this generation.)r   pytorch_waveletsr   r   ImportErrorr   warning)r   r   r   s      r   _try_import_LazyWavelet._try_import    sP    
	C ))  	"&DNN5 	s    'A	A	c           	     $   U R                  5       nUc  gUu  pV[        U5      [        U5      U4nU R                  R                  U5      nUb  U$ U" SSUS9R	                  U[
        R                  S9n	U" SUS9R	                  U[
        R                  S9n
X4U R                  U'    [        U	SS5      nUb  [        UR                  S   5      OSn[        R                  " S	X<[        U5      [        U5      5        X4$ ! [         a    Sn N<f = f)
u   Return ``(dwt, iwt)`` for the requested device/dtype/wavelet.

Returns ``None`` when ``pytorch_wavelets`` is missing — callers
must treat this as a "skip the correction" signal.
N   zero)Jmodewave)devicedtype)r   r    h0zR[DCW] Built DWT1D for wavelet={!r} (low-pass filter taps={}, device={}, dtype={}).)r   strr   gettotorchfloat32getattrintshape	Exceptionr   info)r   r!   r"   waveletmodulesr   r   keycacheddwtiwtr#   ntaps                r   r&   _LazyWavelet.get0   s    ""$?%,"6{CJ0%M QV':==VSXS`S`=aW588emm8\:C
	 dD)B(*3rxx|$BD 	`3v;E
	
 x  	D	s   (*D   DDr   N)returnNone)r!   ztorch.devicer"   ztorch.dtyper/   r%   r7   z5Optional[Tuple['torch.nn.Module', 'torch.nn.Module']])	__name__
__module____qualname____firstlineno____doc__r   r   r&   __static_attributes__ r   r   r   r      s<    $* (( ( 	(
 
?(r   r   )r=   
__future__r   typingr   r   r(   logurur   r   WAVELET_CACHEr?   r   r   <module>rD      s.   	 # "  D DP r   