
    \[fry                        d dl mZ d dlZd dlZd dlZd dlmZ d dl	mc m
Z  G d dej                        Zd Zd Zd Zd'dZd	 Zd
 Zd(dZd Z G d dej,                  j.                        Z G d dej2                        Z G d dej2                        Z G d dej8                  e      Z G d dej2                        Z G d dej2                        Z G d de      Z  G d dej2                        Z!d Z" G d dej2                        Z# G d  d!ej2                        Z$ G d" d#ej2                        Z%	 	 	 	 d)d$Z&	 	 	 	 d*d%Z'	 	 	 	 d+d&Z(y),    )abstractmethodNc                        e Zd Z fdZ xZS )GroupNorm32c                 p    t         |   |j                               j                  |j                        S N)superforwardfloattypedtype)selfx	__class__s     3/home/cameronsmith/repos/minimal-diffusion/unets.pyr	   zGroupNorm32.forward   s'    wqwwy)..qww77    )__name__
__module____qualname__r	   __classcell__r   s   @r   r   r      s    8 8r   r   c                     | dk(  rt        j                  |i |S | dk(  rt        j                  |i |S | dk(  rt        j                  |i |S t	        d|        )z4
    Create a 1D, 2D, or 3D convolution module.
             unsupported dimensions: )nnConv1dConv2dConv3d
ValueErrordimsargskwargss      r   conv_ndr%      sh     qyyy$)&))	yy$)&))	yy$)&))
/v6
77r   c                  ,    t        j                  | i |S )z!
    Create a linear module.
    )r   Linear)r#   r$   s     r   linearr(      s     99d%f%%r   c                     | dk(  rt        j                  |i |S | dk(  rt        j                  |i |S | dk(  rt        j                  |i |S t	        d|        )z8
    Create a 1D, 2D, or 3D average pooling module.
    r   r   r   r   )r   	AvgPool1d	AvgPool2d	AvgPool3dr    r!   s      r   avg_pool_ndr-   $   sh     qy||T,V,,	||T,V,,	||T,V,,
/v6
77r   c                     t        | |      D ]8  \  }}|j                         j                  |      j                  |d|z
         : y)a#  
    Update target parameters to be closer to those of source parameters using
    an exponential moving average.

    :param target_params: the target parameter sequence.
    :param source_params: the source parameter sequence.
    :param rate: the EMA rate (closer to 1 means slower).
    r   )alphaN)zipdetachmul_add_)target_paramssource_paramsratetargsrcs        r   
update_emar9   1   sF     6 ;	c4 %%cT%:;r   c                 l    | j                         D ]   }|j                         j                          " | S )z<
    Zero out the parameters of a module and return it.
    )
parametersr1   zero_)moduleps     r   zero_moduler?   >   s3       	
Mr   c                     t        d|       S )z
    Make a standard normalization layer.

    :param channels: number of input channels.
    :return: an nn.Module for normalization.
        )r   )channelss    r   normalizationrC   G   s     r8$$r   c           	         |dz  }t        j                  t        j                  |       t        j                  d|t         j
                        z  |z        j                  | j                        }| dddf   j                         |d   z  }t        j                  t        j                  |      t        j                  |      gd      }|dz  r5t        j                  |t        j                  |ddddf         gd      }|S )	aY  
    Create sinusoidal timestep embeddings.

    :param timesteps: a 1-D Tensor of N indices, one per batch element.
                      These may be fractional.
    :param dim: the dimension of the output.
    :param max_period: controls the minimum frequency of the embeddings.
    :return: an [N x dim] Tensor of positional embeddings.
    r   r   )startendr   )deviceNdimr   )thexpmathlogarangefloat32torG   r
   catcossin
zeros_like)	timestepsrJ   
max_periodhalffreqsr#   	embeddings          r   timestep_embeddingr[   Q   s     !8DFF	*			t2:: NNQUUb	  b! 
 QW##%d3DtbffTl3<I
QwFFIr}}Yq"1"u5E'FGRP	r   c                 ~    |r7t        |      t        |      z   }t        j                  | t        |      g| S  | | S )a  
    Evaluate a function without caching intermediate activations, allowing for
    reduced memory at the expense of extra compute in the backward pass.

    :param func: the function to evaluate.
    :param inputs: the argument sequence to pass to `func`.
    :param params: a sequence of parameters `func` depends on but does not
                   explicitly take as arguments.
    :param flag: if False, disable gradient checkpointing.
    )tupleCheckpointFunctionapplylen)funcinputsparamsflagr#   s        r   
checkpointre   f   s?     V}uV},!''c&kADAAV}r   c                   ,    e Zd Zed        Zed        Zy)r^   c                     || _         t        |d |       | _        t        ||d        | _        t	        j
                         5   | j                   | j                   }d d d        |S # 1 sw Y   S xY wr   )run_functionlistinput_tensorsinput_paramsrK   no_grad)ctxrh   lengthr#   output_tensorss        r   r	   zCheckpointFunction.forwardy   sp    ' gv/VW.ZZ\ 	B-S--s/@/@AN	B	Bs   A&&A0c                    | j                   D cg c]!  }|j                         j                  d      # c}| _         t        j                         5  | j                   D cg c]  }|j                  |       }} | j                  | }d d d        t        j                  j                  | j                   | j                  z   |d      }| ` | `	~d|z   S c c}w c c}w # 1 sw Y   WxY w)NT)allow_unused)NN)
rj   r1   requires_grad_rK   enable_gradview_asrh   autogradgradrk   )rm   output_gradsr   shallow_copiesro   input_gradss         r   backwardzCheckpointFunction.backward   s    FIFWFWXQXXZ66t<X^^ 	? 584E4EFqaiilFNF-S--~>N	? kk&& 0 00	 ' 
 k))! Y
 G		? 	?s#   &CC C8CCC(N)r   r   r   staticmethodr	   rz    r   r   r^   r^   x   s(      * *r   r^   c            	       >     e Zd ZdZ	 ddedededef fdZd Z xZS )	AttentionPool2dzS
    Adapted from CLIP: https://github.com/openai/CLIP/blob/main/clip/model.py
    spacial_dim	embed_dimnum_heads_channels
output_dimc                 8   t         |           t        j                  t	        j
                  ||dz  dz         |dz  z        | _        t        d|d|z  d      | _        t        d||xs |d      | _	        ||z  | _
        t        | j                        | _        y )Nr   r   g      ?r   )r   __init__r   	ParameterrK   randnpositional_embeddingr%   qkv_projc_proj	num_headsQKVAttention	attention)r   r   r   r   r   r   s        r   r   zAttentionPool2d.__init__   s     	$&LLHHYq 01 45	S8HH%
!  9a)mQ?aJ,C)QG"&88%dnn5r   c                 |   |j                   ^}}}|j                  ||d      }t        j                  |j	                  dd      |gd      }|| j
                  d d d d d f   j                  |j                        z   }| j                  |      }| j                  |      }| j                  |      }|d d d d df   S )NrH   T)rJ   keepdimrI   r   )shapereshaperK   rR   meanr   rQ   r   r   r   r   )r   r   bc_spatials        r   r	   zAttentionPool2d.forward   s    ''1xIIaBFFAFFr4F0!4"=))$1*588AAMM!NN1KKNAqzr   r   )r   r   r   __doc__intr   r	   r   r   s   @r   r~   r~      s=     66 6  	6
 6 r   r~   c                        e Zd ZdZed        Zy)TimestepBlockzT
    Any module where forward() takes timestep embeddings as a second argument.
    c                      y)zJ
        Apply the module to `x` given `emb` timestep embeddings.
        Nr|   r   r   embs      r   r	   zTimestepBlock.forward   s    r   N)r   r   r   r   r   r	   r|   r   r   r   r      s      r   r   c                       e Zd ZdZd Zy)TimestepEmbedSequentialzt
    A sequential module that passes timestep embeddings to the children that
    support it as an extra input.
    c                 X    | D ]$  }t        |t              r
 |||      } ||      }& |S r   )
isinstancer   )r   r   r   layers       r   r	   zTimestepEmbedSequential.forward   s6     	E%/!SM!H		
 r   N)r   r   r   r   r	   r|   r   r   r   r      s    
r   r   c                   *     e Zd ZdZd fd	Zd Z xZS )UpsampleaA  
    An upsampling layer with an optional convolution.
    :param channels: channels in the inputs and outputs.
    :param use_conv: a bool determining if a convolution is applied.
    :param dims: determines if the signal is 1D, 2D, or 3D. If 3D, then
                 upsampling occurs in the inner-two dimensions.
    c                     t         |           || _        |xs || _        || _        || _        |r*t        || j                  | j                  dd      | _        y y )Nr   r   padding)r   r   rB   out_channelsuse_convr"   r%   conv)r   rB   r   r"   r   r   s        r   r   zUpsample.__init__   sW     (4H 	dmmT5F5FSTUDI r   c                    |j                   d   | j                  k(  sJ | j                  dk(  rIt        j                  ||j                   d   |j                   d   dz  |j                   d   dz  fd      }nt        j                  |dd      }|j                   d   |j                   d	   cxk(  rdk(  rn nt        j
                  |d
      }| j                  r| j                  |      }|S )Nr   r   r      nearest)mode)scale_factorr   rH   )r   r   r   r   )r   rB   r"   Finterpolatepadr   r   )r   r   outs      r   r	   zUpsample.forward   s    wwqzT]]**99>--AGGAJ
Q
Q?iC --	BC772;!''"+**%%\*C==))C.C
r   r   Nr   r   r   r   r   r	   r   r   s   @r   r   r      s    Vr   r   c                   *     e Zd ZdZd fd	Zd Z xZS )
DownsampleaD  
    A downsampling layer with an optional convolution.
    :param channels: channels in the inputs and outputs.
    :param use_conv: a bool determining if a convolution is applied.
    :param dims: determines if the signal is 1D, 2D, or 3D. If 3D, then
                 downsampling occurs in the inner-two dimensions.
    c                 *   t         |           || _        |xs || _        || _        || _        |dk7  rdnd}|r+t        || j                  | j                  d|d      | _        y | j                  | j                  k(  sJ t        |||      | _        y )Nr   r   )r   r   r   r   )strider   )kernel_sizer   )	r   r   rB   r   r   r"   r%   opr-   )r   rB   r   r"   r   r   r   s         r   r   zDownsample.__init__   s     (4H 	aiYdmmT%6%6&RSDG ==D$5$555!$F6JDGr   c                 `    |j                   d   | j                  k(  sJ | j                  |      S )Nr   )r   rB   r   r   r   s     r   r	   zDownsample.forward  s'    wwqzT]]**wwqzr   r   r   r   s   @r   r   r      s    Kr   r   c                   >     e Zd ZdZ	 	 	 	 	 	 	 d fd	Zd Zd Z xZS )ResBlocka  
    A residual block that can optionally change the number of channels.
    :param channels: the number of input channels.
    :param emb_channels: the number of timestep embedding channels.
    :param dropout: the rate of dropout.
    :param out_channels: if specified, the number of out channels.
    :param use_conv: if True and out_channels is specified, use a spatial
        convolution instead of a smaller 1x1 convolution to change the
        channels in the skip connection.
    :param dims: determines if the signal is 1D, 2D, or 3D.
    :param use_checkpoint: if True, use gradient checkpointing on this module.
    :param up: if True, use this block for upsampling.
    :param down: if True, use this block for downsampling.
    c                    t         |           || _        || _        || _        |xs || _        || _        || _        || _        t        j                  t        |      t        j                         t        ||| j
                  dd            | _        |	xs |
| _        |	r%t!        |d|      | _        t!        |d|      | _        nG|
r%t'        |d|      | _        t'        |d|      | _        n t        j(                         x| _        | _        t        j                  t        j                         t+        ||rd| j
                  z  n| j
                              | _        t        j                  t        | j
                        t        j                         t        j.                  |      t1        t        || j
                  | j
                  dd                  | _        | j
                  |k(  rt        j(                         | _        y |r t        ||| j
                  dd      | _        y t        ||| j
                  d      | _        y )Nr   r   r   Fr   )r>   )r   r   rB   emb_channelsdropoutr   r   use_checkpointuse_scale_shift_normr   
SequentialrC   SiLUr%   	in_layersupdownr   h_updx_updr   Identityr(   
emb_layersDropoutr?   
out_layersskip_connection)r   rB   r   r   r   r   r   r"   r   updownr   s              r   r   zResBlock.__init__!  s    	 ((4H ,$8!(#GGID(D$5$5q!D
 jD!(E48DJ!(E48DJ#HeT:DJ#HeT:DJ&(kkm3DJ--GGI)=D%%%4CTCT
 --$++,GGIJJ!d//1B1BAqQ	
 (#%;;=D #*h 1 11a$D  $+44;L;La#PD r   c                 f    t        | j                  ||f| j                         | j                        S )a  
        Apply the block to a Tensor, conditioned on a timestep embedding.
        :param x: an [N x C x ...] Tensor of features.
        :param emb: an [N x emb_channels] Tensor of timestep embeddings.
        :return: an [N x C x ...] Tensor of outputs.
        )re   _forwardr;   r   r   s      r   r	   zResBlock.forwarda  s/     MMAs8T__%68K8K
 	
r   c                    | j                   rQ| j                  d d | j                  d   }} ||      }| j                  |      }| j                  |      } ||      }n| j                  |      }| j	                  |      j                  |j                        }t        |j                        t        |j                        k  r1|d   }t        |j                        t        |j                        k  r1| j                  rS| j                  d   | j                  dd  }}t        j                  |dd      \  }	}
 ||      d|	z   z  |
z   } ||      }n||z   }| j                  |      }| j                  |      |z   S )NrH   ).Nr   r   r   rI   )r   r   r   r   r   r   r   r`   r   r   r   rK   chunkr   )r   r   r   in_restin_convhemb_outout_normout_restscaleshifts              r   r   zResBlock._forwardl  sD   ;;#~~cr2DNN24FWG
A

1A

1A
Aq!A//#&++AGG4'-- 3qww</i(G '-- 3qww</$$!%!3T__QR5HhH88GQA6LE5q5y)E1AAGA"A##A&**r   )NFFr   FFFr   r   r   r   r   r	   r   r   r   s   @r   r   r     s0    ( ">Q@	
+r   r   c                   8     e Zd ZdZ	 	 	 	 d fd	Zd Zd Z xZS )AttentionBlocka  
    An attention block that allows spatial positions to attend to each other.
    Originally ported from here, but adapted to the N-d case.
    https://github.com/hojonathanho/diffusion/blob/1e0dceb3b3495bbe19116a5e1b3596cd0706c543/diffusion_tf/models/unet.py#L66.
    c                    t         |           || _        |dk(  r|| _        n||z  dk(  sJ d| d|        ||z  | _        || _        t        |      | _        t        d||dz  d      | _        |rt        | j                        | _
        nt        | j                        | _
        t        t        d||d            | _        y )NrH   r   zq,k,v channels z' is not divisible by num_head_channels r   r   )r   r   rB   r   r   rC   normr%   qkvr   r   QKVAttentionLegacyr?   proj_out)r   rB   r   num_head_channelsr   use_new_attention_orderr   s         r   r   zAttentionBlock.__init__  s     	 "&DN ,,1f 
*QRcQdef &)::DN,!(+	1h1a8")$..9DN 0?DN#GAx1$EFr   c                 P    t        | j                  |f| j                         d      S )NT)re   r   r;   r   s     r   r	   zAttentionBlock.forward  s     $--!t/@$GGr   c                     |j                   ^}}}|j                  ||d      }| j                  | j                  |            }| j	                  |      }| j                  |      } ||z   j                  ||g| S )NrH   )r   r   r   r   r   r   )r   r   r   r   spatialr   r   s          r   r   zAttentionBlock._forward  sq    1wIIaBhhtyy|$NN3MM!Aq!.g..r   )r   rH   FFr   r   s   @r   r   r     s'      %G:H/r   r   c                     |d   j                   ^}}}t        t        j                  |            }d|z  |dz  z  |z  }| xj                  t        j                  |g      z  c_        y)a(  
    A counter for the `thop` package to count the operations in an
    attention operation.
    Meant to be used like:
        macs, params = thop.profile(
            model,
            inputs=(inputs, timestamps),
            custom_ops={QKVAttention: QKVAttention.count_flops},
        )
    r   r   N)r   r   npprod	total_opsrK   DoubleTensor)model_xyr   r   r   num_spatial
matmul_opss           r   count_flops_attnr     s]     qTZZNAq7bggg&'K Q+*+a/J	OOr
|44Or   c                   8     e Zd ZdZ fdZd Zed        Z xZS )r   zh
    A module which performs QKV attention. Matches legacy QKVAttention + input/ouput heads shaping
    c                 0    t         |           || _        y r   r   r   n_headsr   r   r   s     r   r   zQKVAttentionLegacy.__init__      r   c                 D   |j                   \  }}}|d| j                  z  z  dk(  sJ |d| j                  z  z  }|j                  || j                  z  |dz  |      j                  |d      \  }}}dt	        j
                  t	        j
                  |            z  }	t        j                  d||	z  ||	z        }
t        j                  |
j                         d      j                  |
j                        }
t        j                  d|
|      }|j                  |d|      S )z
        Apply QKV attention.
        :param qkv: an [N x (H * 3 * C) x T] tensor of Qs, Ks, and Vs.
        :return: an [N x (H * C) x T] tensor after attention.
        r   r   r   rI   bct,bcs->btsrH   bts,bcs->bct)r   r   r   splitrM   sqrtrK   einsumsoftmaxr
   r   r   r   r   bswidthrn   chqkvr   weightas               r   r	   zQKVAttentionLegacy.forward  s      IIE6DLL()Q..q4<<'(++b4<</a@FFrqFQ1aDIIdiim,,AIq5y
 FLLN388FIInfa0yyR((r   c                     t        | ||      S r   r   r   r   r   s      r   count_flopszQKVAttentionLegacy.count_flops      r1--r   	r   r   r   r   r   r	   r{   r  r   r   s   @r   r   r     s&    )$ . .r   r   c                   8     e Zd ZdZ fdZd Zed        Z xZS )r   zP
    A module which performs QKV attention and splits in a different order.
    c                 0    t         |           || _        y r   r   r   s     r   r   zQKVAttention.__init__  r   r   c           	         |j                   \  }}}|d| j                  z  z  dk(  sJ |d| j                  z  z  }|j                  dd      \  }}}dt        j                  t        j                  |            z  }	t        j                  d||	z  j                  || j                  z  ||      ||	z  j                  || j                  z  ||            }
t        j                  |
j                         d      j                  |
j                        }
t        j                  d|
|j                  || j                  z  ||            }|j                  |d|      S )z
        Apply QKV attention.
        :param qkv: an [N x (3 * H * C) x T] tensor of Qs, Ks, and Vs.
        :return: an [N x (H * C) x T] tensor after attention.
        r   r   r   rI   r   rH   r   )r   r   r   rM   r   rK   r   viewr  r
   r   r   r   r  s               r   r	   zQKVAttention.forward  s$     IIE6DLL()Q..q4<<'())A1)%1aDIIdiim,,YR$,,.F;YR$,,.F;

 FLLN388FIInfaiiT\\8I2v.VWyyR((r   c                     t        | ||      S r   r  r  s      r   r  zQKVAttention.count_flops  r  r   r  r   s   @r   r   r     s&    )( . .r   r   c                   H     e Zd ZdZ	 	 	 	 	 	 	 	 	 	 	 	 	 	 d fd	ZddZ xZS )	UNetModela  
    The full UNet model with attention and timestep embedding.
    :param in_channels: channels in the input Tensor.
    :param emb_dim: base dimension of timestep embedding.
    :param model_channels: base channel count for the model.
    :param out_channels: channels in the output Tensor.
    :param num_res_blocks: number of residual blocks per downsample.
    :param attention_resolutions: a collection of downsample rates at which
        attention will take place. May be a set, list, or tuple.
        For example, if this contains 4, then at 4x downsampling, attention
        will be used.
    :param dropout: the dropout probability.
    :param channel_mult: channel multiplier for each level of the UNet.
    :param conv_resample: if True, use learned convolutions for upsampling and
        downsampling.
    :param dims: determines if the signal is 1D, 2D, or 3D.
    :param num_classes: if specified (as an int), then this model will be
        class-conditional with `num_classes` classes.
    :param use_checkpoint: use gradient checkpointing to reduce memory usage.
    :param num_heads: the number of attention heads in each attention layer.
    :param num_heads_channels: if specified, ignore num_heads and instead use
                               a fixed channel width per attention head.
    :param num_heads_upsample: works with num_heads to set a different number
                               of heads for upsampling. Deprecated.
    :param use_scale_shift_norm: use a FiLM-like conditioning mechanism.
    :param resblock_updown: use residual blocks for up/downsampling.
    :param use_new_attention_order: use a different attention pattern for potentially
                                    increased efficiency.
    c                    t         !|           |dk(  r|}|| _        || _        || _        || _        || _        || _        || _        |	| _	        |
| _
        || _        || _        |rt        j                  nt        j                  | _        || _        || _        || _        ||z  }t)        j*                  t-        ||      t)        j.                         t-        ||            | _        | j                  t)        j2                  ||      | _        t7        |	d   |z        x}}t)        j8                  t;        t=        |||dd            g      | _        || _         |g}d}tC        |	      D ]4  \  }}tE        |      D ]  }tG        |||t7        ||z        |||      g}t7        ||z        }||v r|jI                  tK        |||||             | j>                  jI                  t;        |        | xj@                  |z  c_         |jI                  |        |tM        |	      dz
  k7  s|}| j>                  jI                  t;        |rtG        |||||||d	      ntO        ||
||
                   |}|jI                  |       |dz  }| xj@                  |z  c_         7 t;        tG        ||||||      tK        |||||      tG        ||||||            | _(        | xj@                  |z  c_         t)        j8                  g       | _)        tU        tC        |	            d d d   D ]  \  }}tE        |dz         D ]  }|jW                         } tG        || z   ||t7        ||z        |||      g}t7        ||z        }||v r|jI                  tK        |||||             |r?||k(  r:|}|jI                  |rtG        |||||||d      ntY        ||
||
             |dz  }| jR                  jI                  t;        |        | xj@                  |z  c_           t)        j*                  t[        |      t)        j.                         t]        t=        |||dd                  | _/        y )NrH   r   r   r   r   )r   r"   r   r   )r   r   r   r   T)r   r"   r   r   r   )r"   r   r   )r"   r   r   )r   r"   r   r   r   )0r   r   
image_sizein_channelsmodel_channelsr   num_res_blocksattention_resolutionsr   channel_multconv_resamplenum_classesr   rK   float16rP   r   r   r   num_heads_upsampler   r   r(   r   
time_embed	Embedding	label_embr   
ModuleListr   r%   input_blocks_feature_size	enumerateranger   appendr   r`   r   middle_blockoutput_blocksri   popr   rC   r?   r   )"r   r  r  r  r   r  r  time_emb_factorr   r  r  r"   r   r   use_fp16r   r   r"  r   resblock_updownr   time_embed_dimr  input_chinput_block_chansdslevelmult_layersout_chiichr   s"                                    r   r   zUNetModel.__init__(  s   . 	#!*$&,(,%:"(*&,#+RZZ
"!2"4'/9-->>2GGI>>2
 '\\+~FDNLOn<==XMM$WT;Aq%QRS
  D$\2 2	)KE4>* -&%()>%?!'5-A
 ./..MM&+9&/.?4K !!(()@&)IJ""b("!((,3-4 L)A--!!((+ + !*#)/!%+91E!%	 (Dv$ !((,a""b("e2	)h 4-%9 -#"3(? -%9!
2 	b ]]2.	, 782> +	)KE4>A-. *)'++-S&%($)>%?!'5-A
 $./..MM&+9&8.?4K Q.0FMM + !*#)/!%+91E#	 &b-dQWX 1HB""))*A6*JK""b("U*)+	)Z =="GGIhaKL
r   c                    |du| j                   duk(  sJ d       g }| j                  t        || j                              }| j                   3|j                  |j                  d   fk(  sJ || j                  |      z   }|j                  | j                        }| j                  D ]  } |||      }|j                  |        | j                  ||      }| j                  D ]2  }t        j                  ||j                         gd      } |||      }4 |j                  |j                        }| j                  |      S )a  
        Apply the model to an input batch.
        :param x: an [N x C x ...] Tensor of inputs.
        :param timesteps: a 1-D batch of timesteps.
        :param y: an [N] Tensor of labels, if class-conditional.
        :return: an [N x C x ...] Tensor of outputs.
        Nz<must specify y if and only if the model is class-conditionalr   r   rI   )r   r#  r[   r  r   r%  r   r   r'  r+  r,  r-  rK   rR   r.  r   )r   r   rV   r   hsr   r   r=   s           r   r	   zUNetModel.forward  s4    D(
 	JI	J oo0D<O<OPQ'77qwwqzm++q))CFF4::'' 	Fq#AIIaL	 a%(( 	F2668}!,Aq#A	 FF177Oxx{r   )r   r   )r   r   r      Tr   NFFr   rH   rH   FFFr   r   r   s   @r   r  r  	  sA    L !" %+~
@r   r  c                 f   | dk(  rd}n&| dk(  rd}n| dk(  rd}n| dk(  rd}nt        d|        g }| dk(  rd	}nd
}|j                  d      D ]  }|j                  | t        |      z         ! t	        d#i d| d|d|ddd|dt        |      ddd|d|dddddddddddd d!d d"d S )$N   r   r   r   r   r   @   r   r   r   r   rA   r   r   r   r      unsupported image size: 28,14,732,16,8,r  r  r   r  r   r  r  r   皙?r  r   r   Fr0  r   r   r   r"  rH   r   Tr1  r   r|   r    r   r+  r   r  r]   	r  r  r   
base_widthr   r  attention_dsr  ress	            r   UNetBigrQ    sO    S&	r	#	r	#	r	#3J<@AALR ) )$**3/ 4J#c(234   " 	
 " $L1  "        "  !" !%# r   c                 f   | dk(  rd}n&| dk(  rd}n| dk(  rd}n| dk(  rd}nt        d|        g }| dk(  rd	}nd
}|j                  d      D ]  }|j                  | t        |      z         ! t	        d#i d| d|d|d|dddt        |      ddd|d|dddddddddddd d!d d"d S )$NrA  rB  rC  rD  rA   rE  rF  rG  rH  rI  rJ  r  r  r  r   r  r   r  r   rK  r  r   r   Fr0  r   r   r   r"  rH   r   Tr1  r   r|   rL  rM  s	            r   UNetrS  5  sO    S&	r	#	r	#	r	#3J<@AALR ) )$**3/ 4J#c(234   " "	
  $L1  "        "  !" !%# r   c                 l   | dk(  rd}n&| dk(  rd}n| dk(  rd}n| dk(  rd}nt        d|        g }| dk(  rd	}nd
}|j                  d      D ]  }|j                  | t        |      z         ! t	        d$i d| d|d|d|dddt        |      ddddd|d|ddddddddddd d!d"d!d#d!S )%NrA  rB  rC  rD  rA   rE  rF  rG  rH  rI  rJ  r  r  r  r   r  r   r  r/  r   rK  r  r   r   Fr0  r   r   r   r"  rH   r   Tr1  r   r|   rL  rM  s	            r   	UNetSmallrU  d  sY    S&	r	#	r	#	r	#3J<@AALR ) )$**3/ 4J#c(234   " "	
  $L1   "         "!" #$ !%% r   )gGz?)i'  )r   r      N)r   r   rC  N)r   r   rA   N))abcr   rM   numpyr   torchrK   torch.nnr   torch.nn.functional
functionalr   	GroupNormr   r%   r(   r-   r9   r?   rC   r[   re   ru   Functionr^   Moduler~   r   r   r   r   r   r   r   r   r   r   r  rQ  rS  rU  r|   r   r   <module>r`     sQ         8",, 8

8&
8
;%*$*-- *>bii @	BII 	bmm] ryy D :o+} o+d-/RYY -/`5(. .@.299 .Dz		 z~ ,b ,b -r   