U
    ÿî¹`Dh  ã                   @   s.  d dl Z d dlZd dlZd dlmZ d dlmZ d dlmZ d dl	m
Z
 d dlmZ d&dd„Zd'd
d„Zdd„ Zdd„ Zdd„ ZG dd„ dejƒZdd„ ZG dd„ dejƒZG dd„ dejƒZG dd„ dejƒZG dd„ dejƒZG dd„ dejƒZG d d!„ d!ejƒZG d"d#„ d#ejƒZG d$d%„ d%ejƒZdS )(é    N)Ú	Parameter)Úkaiming_uniform_)Úload_kernels)Ú	write_plyé   c                 C   s.  |dkr| | S |dkrd|   d¡} |  d|jd df¡} |  d¡}| dd| jd f¡}|  d|¡S |dkr"t| ¡ dd… ƒD ]8\}}|   |d ¡} t|  ¡ ƒ}|||d < |  |¡} q‚t| ¡ ƒ}t|  ¡ |d… ƒD ]8\}}|  || ¡}t| ¡ ƒ}|||| < | |¡}qÜ|  d|¡S tdƒ‚dS )a  
    implementation of a custom gather operation for faster backwards.
    :param x: input with shape [N, D_1, ... D_d]
    :param idx: indexing with shape [n_1, ..., n_m]
    :param method: Choice of the method
    :return: x[idx] with shape [n_1, ..., n_m, D_1, ... D_d]
    r   é   éÿÿÿÿr   NzUnkown method)	Ú	unsqueezeÚexpandÚshapeÚgatherÚ	enumerateÚsizeÚlistÚlenÚ
ValueError)ÚxÚidxÚmethodÚiÚniZnew_sÚnÚdi© r   ú+/workspace/OverlapPredator/models/blocks.pyr      s,    	


r   ç•Ö&è.>c                 C   s   t  |  d|d  |  ¡S )zÛ
    Compute a radius gaussian (gaussian of distance)
    :param sq_r: input radiuses [dn, ..., d1, d0]
    :param sig: extents of gaussians [d1, d0] or [d0] or float
    :return: gaussian of sq_r [dn, ..., d1, d0]
    r   )ÚtorchÚexp)Zsq_rÚsigÚepsr   r   r   Úradius_gaussian=   s    r    c              	   C   s<   t  | t  | dd…dd…f ¡fd¡} t| |dd…df ƒS )a	  
    Pools features from the closest neighbors. WARNING: this function assumes the neighbors are ordered.
    :param x: [n1, d] features matrix
    :param inds: [n2, max_num] Only the first column is used for pooling
    :return: [n2, d] pooled features matrix
    Nr   r   )r   ÚcatÚ
zeros_liker   )r   Úindsr   r   r   Úclosest_poolG   s    	&r$   c              	   C   sD   t  | t  | dd…dd…f ¡fd¡} t| |ƒ}t  |d¡\}}|S )z²
    Pools features with the maximum values.
    :param x: [n1, d] features matrix
    :param inds: [n2, max_num] pooling indices
    :return: [n2, d] pooled features matrix
    Nr   r   )r   r!   r"   r   Úmax)r   r#   Úpool_featuresÚmax_featuresÚ_r   r   r   Úmax_poolV   s    	&
r)   c                 C   sL   g }d}t |ƒD ]0\}}| tj| ||| … dd¡ ||7 }qt |¡S )z¼
    Block performing a global average over batch pooling
    :param x: [N, D] input features
    :param batch_lengths: [B] list of batch lengths
    :return: [B, D] averaged features
    r   ©Údim)r   Úappendr   ÚmeanÚstack)r   Zbatch_lengthsZaveraged_featuresÚi0Zb_iÚlengthr   r   r   Úglobal_averagei   s    	 
r1   c                       s>   e Zd Zd‡ fdd„	Zdd„ Zd	d
„ Zdd„ Zdd„ Z‡  ZS )ÚKPConvÚcenterÚlinearÚsumFc                    s  t t| ƒ ¡  || _|| _|| _|| _|| _|| _|| _	|| _
|	| _|
| _|| _d| _d| _d| _ttj| j||ftjddd| _|
rð|r | jd | j | _n| j| j | _t| j| j| j| j|||||	d	| _ttj| jtjddd| _nd| _d| _d| _|  ¡  |  ¡ | _dS )a  
        Initialize parameters for KPConvDeformable.
        :param kernel_size: Number of kernel points.
        :param p_dim: dimension of the point space.
        :param in_channels: dimension of input features.
        :param out_channels: dimension of output features.
        :param KP_extent: influence radius of each kernel point.
        :param radius: radius used for kernel point init. Even for deformable, use the config.conv_radius
        :param fixed_kernel_points: fix position of certain kernel points ('none', 'center' or 'verticals').
        :param KP_influence: influence function of the kernel points ('constant', 'linear', 'gaussian').
        :param aggregation_mode: choose to sum influences, or only keep the closest ('closest', 'sum').
        :param deformable: choose deformable or not
        :param modulated: choose if kernel weights are modulated in addition to deformed
        N©ÚdtypeT©Úrequires_gradr   )Úfixed_kernel_pointsÚKP_influenceÚaggregation_mode)Úsuperr2   Ú__init__ÚKÚp_dimÚin_channelsÚout_channelsÚradiusÚ	KP_extentr:   r;   r<   Ú
deformableÚ	modulatedÚmin_d2Údeformed_KPÚoffset_featuresr   r   ÚzerosÚfloat32ÚweightsZ
offset_dimÚoffset_convÚoffset_biasÚreset_parametersÚinit_KPÚkernel_points)ÚselfÚkernel_sizer@   rA   rB   rD   rC   r:   r;   r<   rE   rF   ©Ú	__class__r   r   r>   ‰   sN    ÿø	
zKPConv.__init__c                 C   s,   t | jt d¡d | jr(tj | j¡ d S )Né   )Úa)	r   rL   ÚmathÚsqrtrE   ÚnnÚinitÚzeros_rN   ©rR   r   r   r   rO   Ð   s    zKPConv.reset_parametersc                 C   s0   t | j| j| j| jd}ttj|tjdddS )zp
        Initialize the kernel point positions in a sphere
        :return: the tensor of kernel points
        )Ú	dimensionÚfixedr6   Fr8   )	r   rC   r?   r@   r:   r   r   ÚtensorrK   )rR   ZK_points_numpyr   r   r   rP   Ö   s    ýÿzKPConv.init_KPc              	   C   sÄ  | j r¢|  ||||¡| j | _| jr~| jd d …d | j| j …f }| d| j| j¡}dt 	| jd d …| j| j d …f ¡ }n| j d| j| j¡}d }|| j
 }nd }d }t |t |d d…d d …f ¡d fd¡}||d d …f }|| d¡ }| j r|| j | _| j d¡}	n| j}	| d¡ ||	 }
tj|
d dd}| j rtj|dd\| _}tj|| j
d k dd tj¡}t tj|dd¡}tj|| ¡ dd\}}|jd|dd	}| d¡ | dd| j¡}|jd|dd	}||9 }|| tj¡d t|jd d ƒ 8 }n|}| jd
kr:t  |¡}t !|dd¡}nr| jdkrttj"dt #|¡| j
  dd}t !|dd¡}n8| jdkr¤| j
d }t$||ƒ}t !|dd¡}nt%dƒ‚| j&dkrætj'|dd}|t !t(j) *|| j¡dd¡9 }n| j&dkrút%dƒ‚t |t |d d…d d …f ¡fd¡}t||ƒ}t +||¡}| j rT| jrT|| d¡9 }| ,d¡}t +|| j-¡}tj|ddd}tj|dd}tjt .|d¡dd}t |t  |¡¡}|| d¡ }|S )Nr   r   r   g    €„.Ar   é   r*   F)Úsparse_gradÚconstantr4   g        )ÚminÚgaussiang333333Ó?z5Unknown influence function type (config.KP_influence)Zclosestr5   z6Unknown convolution mode. Should be 'closest' or 'sum')r   r   r   )r+   Úkeepdim)/rE   rM   rN   rI   rF   r@   r?   Úviewr   ÚsigmoidrD   r!   r"   r	   rQ   rH   Ú
unsqueeze_r5   rd   rG   ÚanyÚtypeÚint32r%   ÚtopkÚitemr   r
   Úint64Úintr   r;   Ú	ones_likeÚ	transposeÚclamprY   r    r   r<   ÚargminrZ   Ú
functionalÚone_hotÚmatmulÚpermuterL   Úgt)rR   Úq_ptsÚs_ptsÚneighb_indsr   Zunscaled_offsetsZmodulationsÚoffsetsÚ	neighborsZdeformed_K_pointsÚdifferencesZsq_distancesr(   Úin_rangeZnew_max_neighbZneighb_row_boolZneighb_row_indsZnew_neighb_indsÚall_weightsÚsigmaZneighbors_1nnZneighb_xZweighted_featuresZkernel_outputsZoutput_featuresZneighbor_features_sumZneighbor_numr   r   r   Úforwardå   s|    **
 
(


 &

zKPConv.forwardc                 C   s   d  | j| j| j| j¡S )NzEKPConv(radius: {:.2f}, extent: {:.2f}, in_feat: {:d}, out_feat: {:d}))ÚformatrC   rD   rA   rB   r]   r   r   r   Ú__repr__x  s    þzKPConv.__repr__)r3   r4   r5   FF)	Ú__name__Ú
__module__Ú__qualname__r>   rO   rP   rƒ   r…   Ú__classcell__r   r   rT   r   r2   ‡   s           þG r2   c                 C   s´   | dkrt |||j|jƒS | dkr:t||jd |j|jƒS | dkrTt| |||||ƒS | dkrnt| |||||ƒS | dks~| dkr†t|ƒS | dkr”tƒ S | d	kr¤t	|ƒS t
d
|  ƒ‚d S )NÚunaryZ
last_unaryr   )ÚsimpleZsimple_deformableZsimple_invariantZsimple_equivariantZsimple_stridedZsimple_deformable_stridedZsimple_invariant_stridedZsimple_equivariant_strided)ZresnetbZresnetb_invariantZresnetb_equivariantZresnetb_deformableZresnetb_stridedZresnetb_deformable_stridedZresnetb_equivariant_stridedZresnetb_invariant_stridedr)   Zmax_pool_wider1   Znearest_upsamplez4Unknown block name in the architecture definition : )Ú
UnaryBlockÚuse_batch_normÚbatch_norm_momentumÚLastUnaryBlockÚfinal_feats_dimÚSimpleBlockÚResnetBottleneckBlockÚMaxPoolBlockÚGlobalAverageBlockÚNearestUpsampleBlockr   )Ú
block_namerC   Úin_dimÚout_dimÚ	layer_indÚconfigr   r   r   Úblock_deciderƒ  s    r›   c                       s4   e Zd Z‡ fdd„Zdd„ Zdd„ Zdd„ Z‡  ZS )	ÚBatchNormBlockc                    sV   t t| ƒ ¡  || _|| _|| _| jr8tj||d| _nt	t
j|t
jddd| _dS )a  
        Initialize a batch normalization block. If network does not use batch normalization, replace with biases.
        :param in_dim: dimension input features
        :param use_bn: boolean indicating if we use Batch Norm
        :param bn_momentum: Batch norm momentum
        )Úmomentumr6   Tr8   N)r=   rœ   r>   Úbn_momentumÚuse_bnr—   rZ   ÚInstanceNorm1dÚ
batch_normr   r   rJ   rK   Úbias)rR   r—   rŸ   rž   rT   r   r   r>   ³  s    zBatchNormBlock.__init__c                 C   s   t j | j¡ d S ©N)rZ   r[   r\   r¢   r]   r   r   r   rO   Å  s    zBatchNormBlock.reset_parametersc                 C   sH   | j r:| d¡}| dd¡}|  |¡}| dd¡}| ¡ S || j S d S )Nr   r   )rŸ   r	   rr   r¡   Úsqueezer¢   )rR   r   r   r   r   rƒ   È  s    

zBatchNormBlock.forwardc                 C   s   d  | j| jt| j ƒ¡S )Nz@BatchNormBlock(in_feat: {:d}, momentum: {:.3f}, only_bias: {:s}))r„   r—   rž   ÚstrrŸ   r]   r   r   r   r…   Ó  s    
þzBatchNormBlock.__repr__)r†   r‡   rˆ   r>   rO   rƒ   r…   r‰   r   r   rT   r   rœ   ±  s   rœ   c                       s0   e Zd Zd	‡ fdd„	Zd
dd„Zdd„ Z‡  ZS )rŒ   Fc                    sd   t t| ƒ ¡  || _|| _|| _|| _|| _tj	||dd| _
t|| j| jƒ| _|s`t d¡| _dS )a   
        Initialize a standard unary block with its ReLU and BatchNorm.
        :param in_dim: dimension input features
        :param out_dim: dimension input features
        :param use_bn: boolean indicating if we use Batch Norm
        :param bn_momentum: Batch norm momentum
        F©r¢   çš™™™™™¹?N)r=   rŒ   r>   rž   rŸ   Úno_relur—   r˜   rZ   ÚLinearÚmlprœ   r¡   Ú	LeakyReLUÚ
leaky_relu©rR   r—   r˜   rŸ   rž   r¨   rT   r   r   r>   Û  s    	zUnaryBlock.__init__Nc                 C   s(   |   |¡}|  |¡}| js$|  |¡}|S r£   )rª   r¡   r¨   r¬   ©rR   r   Úbatchr   r   r   rƒ   ð  s
    


zUnaryBlock.forwardc                 C   s"   d  | j| jt| jƒt| j ƒ¡S )Nz?UnaryBlock(in_feat: {:d}, out_feat: {:d}, BN: {:s}, ReLU: {:s}))r„   r—   r˜   r¥   rŸ   r¨   r]   r   r   r   r…   ÷  s
    
ýzUnaryBlock.__repr__)F)N©r†   r‡   rˆ   r>   rƒ   r…   r‰   r   r   rT   r   rŒ   Ù  s   
rŒ   c                       s0   e Zd Zd	‡ fdd„	Zd
dd„Zdd„ Z‡  ZS )r   Fc                    s0   t t| ƒ ¡  || _|| _tj||dd| _dS )a  
        Initialize a standard last_unary block without BN, ReLU.
        :param in_dim: dimension input features
        :param out_dim: dimension input features
        :param use_bn: boolean indicating if we use Batch Norm
        :param bn_momentum: Batch norm momentum
        Fr¦   N)r=   r   r>   r—   r˜   rZ   r©   rª   r­   rT   r   r   r>      s
    	zLastUnaryBlock.__init__Nc                 C   s   |   |¡}|S r£   )rª   r®   r   r   r   rƒ     s    
zLastUnaryBlock.forwardc                 C   s   d  | j| j¡S )Nz-LastUnaryBlock(in_feat: {:d}, out_feat: {:d}))r„   r—   r˜   r]   r   r   r   r…     s    ÿzLastUnaryBlock.__repr__)F)Nr°   r   r   rT   r   r   þ  s   
r   c                       s$   e Zd Z‡ fdd„Zdd„ Z‡  ZS )r‘   c                    s    t t| ƒ ¡  ||j |j }|j| _|j| _|| _	|| _
|| _|| _t|j|j||d |||j|j|jd|k|jd| _t|d | j| jƒ| _t d¡| _dS )a  
        Initialize a simple convolution block with its ReLU and BatchNorm.
        :param in_dim: dimension input features
        :param out_dim: dimension input features
        :param radius: current radius of convolution
        :param config: parameters
        r   Údeform©r:   r;   r<   rE   rF   r§   N)r=   r‘   r>   rD   Úconv_radiusrŽ   rž   r   rŸ   r™   r–   r—   r˜   r2   Únum_kernel_pointsÚin_points_dimr:   r;   r<   rF   rœ   r¡   rZ   r«   r¬   ©rR   r–   r—   r˜   rC   r™   rš   Zcurrent_extentrT   r   r   r>     s.    özSimpleBlock.__init__c                 C   s„   d| j kr:|d | jd  }|d | j }|d | j }n*|d | j }|d | j }|d | j }|  ||||¡}|  |  |¡¡S ©NÚstridedÚpointsr   Úpoolsr~   )r–   r™   r2   r¬   r¡   )rR   r   r¯   rz   r{   r|   r   r   r   rƒ   B  s    
zSimpleBlock.forward©r†   r‡   rˆ   r>   rƒ   r‰   r   r   rT   r   r‘     s   (r‘   c                       s$   e Zd Z‡ fdd„Zdd„ Z‡  ZS )r’   c                    s  t t| ƒ ¡  ||j |j }|j| _|j| _|| _	|| _
|| _|| _||d krlt||d | j| jƒ| _n
t ¡ | _t|j|j|d |d |||j|j|jd|k|jd| _t|d | j| jƒ| _t|d || j| jdd| _||krt||| j| jdd| _n
t ¡ | _t d¡| _dS )zï
        Initialize a resnet bottleneck block.
        :param in_dim: dimension input features
        :param out_dim: dimension input features
        :param radius: current radius of convolution
        :param config: parameters
        é   r±   r²   T)r¨   r§   N)r=   r’   r>   rD   r³   rŽ   rž   r   rŸ   r–   r™   r—   r˜   rŒ   Úunary1rZ   ÚIdentityr2   r´   rµ   r:   r;   r<   rF   rœ   Úbatch_norm_convÚunary2Úunary_shortcutr«   r¬   r¶   rT   r   r   r>   S  s<    
ö

zResnetBottleneckBlock.__init__c                 C   sÊ   d| j kr:|d | jd  }|d | j }|d | j }n*|d | j }|d | j }|d | j }|  |¡}|  ||||¡}|  |  |¡¡}|  |¡}d| j kr®t||ƒ}n|}|  |¡}|  || ¡S r·   )	r–   r™   r½   r2   r¬   r¿   rÀ   r)   rÁ   )rR   Úfeaturesr¯   rz   r{   r|   r   Úshortcutr   r   r   rƒ   Š  s     




zResnetBottleneckBlock.forwardr»   r   r   rT   r   r’   Q  s   7r’   c                       s$   e Zd Z‡ fdd„Zdd„ Z‡  ZS )r”   c                    s   t t| ƒ ¡  dS )zP
        Initialize a global average block with its ReLU and BatchNorm.
        N)r=   r”   r>   r]   rT   r   r   r>   «  s    zGlobalAverageBlock.__init__c                 C   s   t ||d d ƒS )NÚstack_lengthsr   )r1   r®   r   r   r   rƒ   ²  s    zGlobalAverageBlock.forwardr»   r   r   rT   r   r”   ©  s   r”   c                       s,   e Zd Z‡ fdd„Zdd„ Zdd„ Z‡  ZS )r•   c                    s   t t| ƒ ¡  || _dS )zT
        Initialize a nearest upsampling block with its ReLU and BatchNorm.
        N)r=   r•   r>   r™   ©rR   r™   rT   r   r   r>   ¸  s    zNearestUpsampleBlock.__init__c                 C   s   t ||d | jd  ƒS )NÚ	upsamplesr   )r$   r™   r®   r   r   r   rƒ   À  s    zNearestUpsampleBlock.forwardc                 C   s   d  | j| jd ¡S )Nz)NearestUpsampleBlock(layer: {:d} -> {:d})r   )r„   r™   r]   r   r   r   r…   Ã  s    ÿzNearestUpsampleBlock.__repr__r°   r   r   rT   r   r•   ¶  s   r•   c                       s$   e Zd Z‡ fdd„Zdd„ Z‡  ZS )r“   c                    s   t t| ƒ ¡  || _dS )zM
        Initialize a max pooling block with its ReLU and BatchNorm.
        N)r=   r“   r>   r™   rÅ   rT   r   r   r>   Ê  s    zMaxPoolBlock.__init__c                 C   s   t ||d | jd  ƒS )Nrº   r   )r)   r™   r®   r   r   r   rƒ   Ò  s    zMaxPoolBlock.forwardr»   r   r   rT   r   r“   È  s   r“   )r   )r   )ÚtimerX   r   Útorch.nnrZ   Ztorch.nn.parameterr   Ztorch.nn.initr   Zkernels.kernel_pointsr   Zlib.plyr   r   r    r$   r)   r1   ÚModuler2   r›   rœ   rŒ   r   r‘   r’   r”   r•   r“   r   r   r   r   Ú<module>   s.   
"

 }.(%9X