o
    f6                     @   s   d dl Z d dlZd dlZd dlm  mZ d dlmZm	Z	 dd Z
dd Zdd ZG d	d
 d
ZG dd deZG dd deZG dd deZdd ZdS )    N)tqdmtrangec                 C   s   | | }t ||}|| }	||	 }
t |
|| }|
d jdd}|jdd}tj|| ddd d d }|| }|
| jdd}|tjj| ddd }|| | 	 }| |||   }t 
|}|||fS )a  
    Proximal gradient descent optimization step for non-negative lasso

    coefficients: (b, m, l - w + 1)
    importance_scale: (b, 1, l - w + 1)
    cwms: (m, 4, w)
    contribs: (b, 4, l)
    sequences: (b, 4, l) or dummy scalar

    For details on proximal gradient descent: https://yuxinchen2020.github.io/ele520_math_data/lectures/lasso_algorithm_extension.pdf, slide 22 
    For details on duality gap computation: https://stanford.edu/~boyd/papers/pdf/l1_ls.pdf, Section III
          r   dimg      ?maxr   )ordr   )FZconv_transpose1dconv1dsumamaxtorchclamplinalgZvector_normabsZrelu)coefficientsimportance_scalecwmscontribs	sequencesalpha
step_sizesZcoef_adjZpred_unmaskedpredZ	residualsZngradnllZ	dual_normZ
dual_scaleZ
nll_scaledZ	dual_diffZl1_termdual_gapZc_next r   =/users/shouvikm/ChromBPNet/finemo_gpu/src/finemo/hitcaller.pyprox_grad_step
   s   

r    c
                 C   s^   |}
t ||| |||	|\}}}|| }|d|  }||d  }d| | ||
  }||||fS )a  
    Non-negative lasso optimizer step with momentum. 

    cwms: (m, 4, w)
    contribs: (b, 4, l)
    importance_scale: (b, 1, l - w + 1)
    sequences: (b, 4, l) or dummy scalar
    coef_inter, coef: (b, m, l - w + 1)
    i, step_sizes: (b,)

    For details on optimization algorithm: https://yuxinchen2020.github.io/ele520_math_data/lectures/lasso_algorithm_extension.pdf, slides 22, 27 
    r   g      @r   )r    )r   r   r   r   
coef_intercoefir   lr   Z	coef_prevgapr   Zmom_termr   r   r   optimizer_step4   s   
r&   c                 K   s4   | d d d d d d d f j ddtji|dS )NZmemory_format   r   )tor   Zchannels_lastsqueeze)tensorkwargsr   r   r   _to_channel_last_layoutP   s   4r,   c                   @   s$   e Zd Zdd Zdd Zdd ZdS )BatchLoaderBasec                 C   s   || _ || _|| _|| _d S N)r   r   r$   device)selfr   r   r$   r/   r   r   r   __init__U   s   
zBatchLoaderBase.__init__c                 C   sj   || }t || jjd }|||  }ddddd|f}tjtj||tjdd|fddj| j	d}||fS )Nr   )dtype)value)r/   )
minr   shaper   padr   arangeintr(   r/   )r0   startendnZoverhangpad_lensindsr   r   r   _get_inds_and_pad_lens[   s   ,z&BatchLoaderBase._get_inds_and_pad_lensc                 C   s   t r.   )NotImplementedError)r0   r:   r;   r   r   r   
load_batche   s   zBatchLoaderBase.load_batchN)__name__
__module____qualname__r1   r?   rA   r   r   r   r   r-   T   s    
r-   c                   @      e Zd Zdd ZdS )BatchLoaderCompactFmtc           	      C   s   |  ||\}}t| j||d d d f |}t|| jtjd}t| j||d d d d f |}t|| jtj	d}|d j
dd| j  }t||d d d d f  | }||||fS Nr/   r2   r   r   r   r?   r   r7   r   r,   r/   r   float32r   int8r   r$   sqrt
nan_to_num)	r0   r:   r;   r>   r=   Zcontribs_compactcontribs_batchsequences_batchglobal_scaler   r   r   rA   j   s    $ z BatchLoaderCompactFmt.load_batchNrB   rC   rD   rA   r   r   r   r   rF   i       rF   c                   @   rE   )BatchLoaderProjc           	      C   s   |  ||\}}t| j||d d d d f |}t|| jtjd}t| j||d d d d f |}t|| jtj	d}|| }|d j
dd| j  }t||d d d d f  }||||fS rG   rI   )	r0   r:   r;   r>   r=   Zcontribs_hyprO   rN   rP   r   r   r   rA   z   s   $$zBatchLoaderProj.load_batchNrQ   r   r   r   r   rS   y   rR   rS   c                   @   rE   )BatchLoaderHypc                 C   s   |  ||\}}t| j||d d d d f |}t|| jtjd}|d jdd| j	 
 }t||d d d d f  }|d||fS )NrH   r   r   r   r   )r?   r   r7   r   r,   r/   r   rJ   r   r$   rL   rM   )r0   r:   r;   r>   r=   rN   rP   r   r   r   rA      s   $zBatchLoaderHyp.load_batchNrQ   r   r   r   r   rT      rR   rT   c           O      C   st  | j \}}}|j \}}}|	}t| } t|}t|}t| |tjd} t|j dkr>|r6t||||}n%t||||}nt|j dkrS|rKtdt	||||}ntd|j  g }g }g }g }g g g g g d}tj
dd|ftj|d	}t|||| d f}t||tjd}t|}tj|ddftj|d	}tj|ddf|tj|d	}tj|fd
tj|d	}|}t|d|f} t| |tjd} |rd}!nt|d|f}!t|!|tjd}!t|d|| d f}"t|"|tjd}"tj|ftj|d	}#tj|ftj|d	}$tdd|dZ}%d}&d}'|&|k r^|dkr|'}(|(| })t|)|j d }'||(|)}*|*\}+},}-}.t|+d |d d }/|/jdd}/|+| |ddddf< |s_|,|!|ddddf< |/|"|ddddf< |-|#|< |.|$|< ||ddddf  d9  < ||ddddf  d9  < ||  d9  < |||< t| | |"|!||||||
\}}}0}1|d7 }|#dk}2t|0 |2@ }3||3ddddf  d9  < ||3ddddf  d9  < ||3  d9  < ||3ddddf  |
9  < ||k |2@ }4|4  dkr|#|4 }5|5D ]}6td|6 d| dt q	||k  |2@ }7|7  dkr?|#|7 }8|8D ]}6td|6 dt q1|0|k|4B |7B |2@ }|  }|dkrY|#| }9|$| }:||ddddf };|"|ddf }<|<d d   }=t| |ddddf | }>|>|= }?|r|;|?|k };|;! };t"|;# }@t$|@dddf |9dddf  |@dddf< |=|;# dddf d|;# dddf f }At%|;# }B|?|B }C|;& }D|0| }E|1| }F||ddf }G||ddf }H|'|@j(d
dj) |'|Dj(d
d |'|Cj(d
d |'|Aj(d
d |d '|Fj(d
d |d '|Ej(d
d |d '|Gj(d
d |d '|:j(d
d |d '|Hj(d
d |&|7 }&|%*| |&|k sW d   n	1 siw   Y  t+j,|dd}It+j,|dd}Jt+j,|dd}Kt+j,|dd}L|Idddf -t+j.|Idddf -t+j.|Idddf |J|K|Ld}Md d! |/ D }N|M|NfS )"z
    Call hits by fitting sparse linear model to contributions
    
    cwms: (m, 4, w)
    contribs: (n, 4, l) or (n, l)  
    sequences: (n, 4, l)
    rH   r'   r   z=Input regions do not contain hypothetical contribution scoresz0Input contributions array is of incorrect shape )r   r   	num_steps	step_sizerP   r      )r2   r/   TNregions)disableunittotalr   g      
   r	   zRegion z$ has not converged within max_steps=z iterations.zOptimizer failed for region .)forcer   r   rU   rP   rV   axis)peak_idmotif_id	hit_starthit_coefficienthit_correlationhit_importancec                 S   s    i | ]\}}|t j|d dqS )r   r`   )npconcatenate).0kvr   r   r   
<dictcomp>Y  s     z fit_contribs.<locals>.<dictcomp>)0r6   r   
from_numpyr,   rJ   lenrT   rS   
ValueErrorrF   oneszeros
zeros_liker9   fullboolrK   floatr   r5   rA   r   r   r   r&   isfiniter)   r   itemwarningswarnRuntimeWarningrL   Z	to_sparsecloneindicesZ	embeddingZunbindvaluesappendnumpyTupdaterh   ri   astypeuint32items)Or   r   r   Zuse_hypotheticalr   step_size_maxstep_size_minconvergence_tol	max_steps
batch_sizestep_adjustZpost_filterr/   m_wr<   r$   bZbatch_loaderZhit_idxs_lstZcoefficients_lstZcorrelation_lstZimportance_lstZqc_lstsZ
sum_filterr!   r"   r#   r   Z	convergedZnum_loadZcontribs_bufZseqs_bufZimportance_scale_bufZinds_bufZglobal_scale_bufZpbarZnum_completeZnext_indZ
load_startZload_endZ
batch_datarN   Z
seqs_batchZ
inds_batchZglobal_scale_batchZimportance_scale_batchr%   r   activeZdivergedZtimeoutsZtimeout_indsindZfailsZ	fail_indsZinds_outZglobal_scale_outZcoef_outZimportance_scale_out_denseZ
xcor_scaleZxcov_out_denseZxcor_out_denseZhit_idxs_outZimportance_outZ	ind_tupleZxcor_outZscores_out_rawZgap_outZnll_outZstep_outZstep_sizes_outZhit_idxsZscores_coefficientZscores_correlationZscores_importancehitsqcr   r   r   fit_contribs   s  	






4.

o	r   )ry   r   rh   r   Ztorch.nn.functionalnnZ
functionalr   r   r   r    r&   r,   r-   rF   rS   rT   r   r   r   r   r   <module>   s    *