U
    Ph<                     @  sR  d Z ddlm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mZmZ dd	d
dddddgZG dd deZdd ZedddZedddZedddZedddZedddZedddZedd d!d"d#d$Zed%e	j ed&d d'd"d(d)Zed*d d+d"d,d-Zed.d/d0 Zed1e	j  ed2e	j! ed3e	j" ed4e	j# ed5e	j$j% ed6e	j$j& ed7e	j$j' ed8e	j$j( ed9e	j$j) ed:e	j$j* ed;e	j$j+ ed<e	j$j, ed=e	j$j- ed>e	j$j. ed?e	j$j/ ed@e	j$j0 edAdBdC Z1edDdEdF Z2edGdHdI Z3edJdKdL Z4edMd dNd"dOdPZ5edQd dRd"dSdTZ6edUd dVd"dWdXZ7edYd dZd"d[d\Z8ed]d d^d"d_d`Z9edad dbd"dcddZ:eded dfd"dgdhZ;edid djd"dkdlZ<dS )ma*  
Defines factories for creating layers in generic, extensible, and dimensionally independent ways. A separate factory
object is created for each type of layer, and factory functions keyed to names are added to these objects. Whenever
a layer is requested the factory name and any necessary arguments are passed to the factory object. The return value
is typically a type but can be any callable producing a layer object.

The factory objects contain functions keyed to names converted to upper case, these names can be referred to as members
of the factory so that they can function as constant identifiers. eg. instance normalization is named `Norm.INSTANCE`.

For example, to get a transpose convolution layer the name is needed and then a dimension argument is provided which is
passed to the factory function:

.. code-block:: python

    dimension = 3
    name = Conv.CONVTRANS
    conv = Conv[name, dimension]

This allows the `dimension` value to be set in the constructor, for example so that the dimensionality of a network is
parameterizable. Not all factories require arguments after the name, the caller must be aware which are required.

Defining new factories involves creating the object then associating it with factory functions:

.. code-block:: python

    fact = LayerFactory()

    @fact.factory_function('test')
    def make_something(x, y):
        # do something with x and y to choose which layer type to return
        return SomeLayerType
    ...

    # request object from factory TEST with 1 and 2 as values for x and y
    layer = fact[fact.TEST, 1, 2]

Typically the caller of a factory would know what arguments to pass (ie. the dimensionality of the requested type) but
can be parameterized with the factory name and the arguments to pass to the created type at instantiation time:

.. code-block:: python

    def use_factory(fact_args):
        fact_name, type_args = split_args
        layer_type = fact[fact_name, 1, 2]
        return layer_type(**type_args)
    ...

    kw_args = {'arg0':0, 'arg1':True}
    layer = use_factory( (fact.TEST, kwargs) )
    )annotationsN)Callable)Any)has_nvfuser_instance_norm)ComponentStorelook_up_optionoptional_importLayerFactoryDropoutNormActConvPoolPad
split_argsc                      s   e Zd ZdZdddd fddZdddd	dd
ddZdddd	ddddZdddddZdddddZddddZ	 fddZ
  ZS )r	   z
    Factory object for creating layers, this uses given factory functions to actually produce the types or constructing
    callables. These functions are referred to by name and can be added at any time.
    strNone)namedescriptionreturnc                   s2   t  || d| d| d d d | _d S )NzLayer Factory 'z': 
zU
Please see :py:class:`monai.networks.layers.split_args` for additional args parsing.z

The supported members are:)super__init__strip__doc__)selfr   r   	__class__ T/home/dell461/cl/sdc2/HISourceFinder-master-l/src/monai/networks/layers/factories.pyr   R   s    zLayerFactory.__init__Nr   z
str | None)r   funcdescr   c                 C  s^   |p|j pd}| | || | j dk	s.t|  j t| jdkrFdnd d| d7  _ dS )zj
        Add the factory function to this object under the given name, with optional description.
         N   z,  z``)r   addupperAssertionErrorlennames)r   r   r    r!   r   r   r   r   add_factory_callableZ   s    z!LayerFactory.add_factory_callabletype)r   clsr!   r   c                   s   |  |d fdd	| dS )z{
        Adds a factory function which returns the supplied class under the given name, with optional description.
        Nc                   s    S Nr   )xr,   r   r   <lambda>h       z0LayerFactory.add_factory_class.<locals>.<lambda>)Nr*   )r   r   r,   r!   r   r/   r   add_factory_classd   s    zLayerFactory.add_factory_class)r   r   c                   s   ddd fdd}|S )zN
        Decorator for adding a factory function with the given name.
        r   )r    r   c                   s     |  | S r-   r2   )r    r   r   r   r   _addo   s    z+LayerFactory.factory_function.<locals>._addr   )r   r   r5   r   r4   r   factory_functionj   s    zLayerFactory.factory_functionr   )factory_namer   c                 G  s:   t |ts tdt|j dt| | j}|j| S )z
        Get the constructor for the given factory name and arguments.

        Raises:
            TypeError: When ``factory_name`` is not a ``str``.

        zfactory_name must a str but is .)	
isinstancer   	TypeErrorr+   __name__r   r&   
componentsvalue)r   r7   args	componentr   r   r   get_constructoru   s    	
zLayerFactory.get_constructor)r   c                 C  s:   t |r|S t|tr"|d }}n|^}}| j|f| S )z
        Get the given name or name/arguments pair. If `args` is a callable it is assumed to be the constructor
        itself and is returned, otherwise it should be the factory name or a pair containing the name and arguments.
        r   )callabler9   r   r@   )r   r>   name_objr   r   r   __getitem__   s    
zLayerFactory.__getitem__c                   s   || j kr|S t |S )z
        If `key` is a factory name, return it, otherwise behave as inherited. This allows referring to factory names
        as if they were constants, eg. `Fact.FOO` for a factory Fact with factory function foo.
        )r<   r   __getattribute__)r   keyr   r   r   __getattr__   s    
zLayerFactory.__getattr__)N)N)r;   
__module____qualname__r   r   r*   r3   r6   r@   rC   rF   __classcell__r   r   r   r   r	   L   s   
c                 C  sJ   t | tr| i fS | \}}t |ts,t|r6t |tsBd}t|||fS )a  
    Split arguments in a way to be suitable for using with the factory types. If `args` is a string it's interpreted as
    the type name.

    Args:
        args (str or a tuple of object name and kwarg dict): input arguments to be parsed.

    Raises:
        TypeError: When ``args`` type is not in ``Union[str, Tuple[Union[str, Callable], dict]]``.

    Examples::

        >>> act_type, args = split_args("PRELU")
        >>> monai.networks.layers.Act[act_type]
        <class 'torch.nn.modules.activation.PReLU'>

        >>> act_type, args = split_args(("PRELU", {"num_parameters": 1, "init": 0.25}))
        >>> monai.networks.layers.Act[act_type](**args)
        PReLU(num_parameters=1)

    z_Layer specifiers must be single strings or pairs of the form (name/object-types, argument dict))r9   r   rA   dictr:   )r>   rB   Z	name_argsmsgr   r   r   r      s    
zDropout layersz$Factory for creating dropout layers.)r   r   zNormalization layersz*Factory for creating normalization layers.zActivation layersz'Factory for creating activation layers.zConvolution layersz(Factory for creating convolution layers.zPooling layersz$Factory for creating pooling layers.zPadding layersz$Factory for creating padding layers.dropoutintz.type[nn.Dropout | nn.Dropout2d | nn.Dropout3d])dimr   c                 C  s   t jt jt jf}|| d  S )z
    Dropout layers in 1,2,3 dimensions.

    Args:
        dim: desired dimension of the dropout layer

    Returns:
        Dropout[dim]d
    r#   )nnr
   	Dropout2d	Dropout3drN   typesr   r   r   dropout_factory   s    rT   Zalphadropoutinstancez?type[nn.InstanceNorm1d | nn.InstanceNorm2d | nn.InstanceNorm3d]c                 C  s   t jt jt jf}|| d  S )z
    Instance normalization layers in 1,2,3 dimensions.

    Args:
        dim: desired dimension of the instance normalization layer

    Returns:
        InstanceNorm[dim]d
    r#   )rO   InstanceNorm1dInstanceNorm2dInstanceNorm3drR   r   r   r   instance_factory   s    rY   batchz6type[nn.BatchNorm1d | nn.BatchNorm2d | nn.BatchNorm3d]c                 C  s   t jt jt jf}|| d  S )z
    Batch normalization layers in 1,2,3 dimensions.

    Args:
        dim: desired dimension of the batch normalization layer

    Returns:
        BatchNorm[dim]d
    r#   )rO   BatchNorm1dBatchNorm2dBatchNorm3drR   r   r   r   batch_factory   s    r^   Zinstance_nvfuserc                 C  s`   | dkr:t jt jf}td|| d   d || d  S t sPtd t jS tdddd	 S )
a  
    `InstanceNorm3dNVFuser` is a faster version of InstanceNorm layer and implemented in `apex`.
    It only supports 3d tensors as the input. It also requires to use with CUDA and non-Windows OS.
    In this function, if the required library `apex.normalization.InstanceNorm3dNVFuser` does not exist,
    `nn.InstanceNorm3d` will be returned instead.
    This layer is based on a customized autograd function, which is not supported in TorchScript currently.
    Please switch to use `nn.InstanceNorm3d` if TorchScript is necessary.

    Please check the following link for more details about how to install `apex`:
    https://github.com/NVIDIA/apex#installation

       z4`InstanceNorm3dNVFuser` only supports 3d cases, use r#   z	 instead.zd`apex.normalization.InstanceNorm3dNVFuser` is not installed properly, use nn.InstanceNorm3d instead.zapex.normalizationInstanceNorm3dNVFuser)r   r   )rO   rV   rW   warningswarnr   rX   r   rR   r   r   r   instance_nvfuser_factory   s    rc   grouplayerZlocalresponseZ	syncbatchelureluZ	leakyreluprelurelu6selucelugelusigmoidtanhsoftmaxZ
logsoftmaxZswishc                  C  s   ddl m}  | S )z=
    Swish activation layer.

    Returns:
        Swish
    r   Swish) monai.networks.blocks.activationrq   rp   r   r   r   swish_factory-  s    rs   Zmemswishc                  C  s   ddl m}  | S )z]
    Memory efficient swish activation layer.

    Returns:
        MemoryEfficientSwish
    r   MemoryEfficientSwish)rr   ru   rt   r   r   r   memswish_factory:  s    rv   mishc                  C  s   ddl m}  | S )z;
    Mish activation layer.

    Returns:
        Mish
    r   Mish)rr   ry   rx   r   r   r   mish_factoryG  s    rz   Zgegluc                  C  s   ddl m}  | S )z=
    GEGLU activation layer.

    Returns:
        GEGLU
    r   GEGLU)rr   r|   r{   r   r   r   geglu_factoryT  s    r}   convz'type[nn.Conv1d | nn.Conv2d | nn.Conv3d]c                 C  s   t jt jt jf}|| d  S )z
    Convolutional layers in 1,2,3 dimensions.

    Args:
        dim: desired dimension of the convolutional layer

    Returns:
        Conv[dim]d
    r#   )rO   Conv1dConv2dConv3drR   r   r   r   conv_factorya  s    r   Z	convtranszBtype[nn.ConvTranspose1d | nn.ConvTranspose2d | nn.ConvTranspose3d]c                 C  s   t jt jt jf}|| d  S )z
    Transposed convolutional layers in 1,2,3 dimensions.

    Args:
        dim: desired dimension of the transposed convolutional layer

    Returns:
        ConvTranspose[dim]d
    r#   )rO   ConvTranspose1dConvTranspose2dConvTranspose3drR   r   r   r   convtrans_factoryp  s    r   maxz0type[nn.MaxPool1d | nn.MaxPool2d | nn.MaxPool3d]c                 C  s   t jt jt jf}|| d  S )z
    Max pooling layers in 1,2,3 dimensions.

    Args:
        dim: desired dimension of the max pooling layer

    Returns:
        MaxPool[dim]d
    r#   )rO   	MaxPool1d	MaxPool2d	MaxPool3drR   r   r   r   maxpooling_factory  s    r   ZadaptivemaxzHtype[nn.AdaptiveMaxPool1d | nn.AdaptiveMaxPool2d | nn.AdaptiveMaxPool3d]c                 C  s   t jt jt jf}|| d  S )z
    Adaptive max pooling layers in 1,2,3 dimensions.

    Args:
        dim: desired dimension of the adaptive max pooling layer

    Returns:
        AdaptiveMaxPool[dim]d
    r#   )rO   AdaptiveMaxPool1dAdaptiveMaxPool2dAdaptiveMaxPool3drR   r   r   r   adaptive_maxpooling_factory  s    r   avgz0type[nn.AvgPool1d | nn.AvgPool2d | nn.AvgPool3d]c                 C  s   t jt jt jf}|| d  S )z
    Average pooling layers in 1,2,3 dimensions.

    Args:
        dim: desired dimension of the average pooling layer

    Returns:
        AvgPool[dim]d
    r#   )rO   	AvgPool1d	AvgPool2d	AvgPool3drR   r   r   r   avgpooling_factory  s    r   ZadaptiveavgzHtype[nn.AdaptiveAvgPool1d | nn.AdaptiveAvgPool2d | nn.AdaptiveAvgPool3d]c                 C  s   t jt jt jf}|| d  S )z
    Adaptive average pooling layers in 1,2,3 dimensions.

    Args:
        dim: desired dimension of the adaptive average pooling layer

    Returns:
        AdaptiveAvgPool[dim]d
    r#   )rO   AdaptiveAvgPool1dAdaptiveAvgPool2dAdaptiveAvgPool3drR   r   r   r   adaptive_avgpooling_factory  s    r   ZreplicationpadzEtype[nn.ReplicationPad1d | nn.ReplicationPad2d | nn.ReplicationPad3d]c                 C  s   t jt jt jf}|| d  S )z
    Replication padding layers in 1,2,3 dimensions.

    Args:
        dim: desired dimension of the replication padding layer

    Returns:
        ReplicationPad[dim]d
    r#   )rO   ReplicationPad1dReplicationPad2dReplicationPad3drR   r   r   r   replication_pad_factory  s    r   Zconstantpadz<type[nn.ConstantPad1d | nn.ConstantPad2d | nn.ConstantPad3d]c                 C  s   t jt jt jf}|| d  S )z
    Constant padding layers in 1,2,3 dimensions.

    Args:
        dim: desired dimension of the constant padding layer

    Returns:
        ConstantPad[dim]d
    r#   )rO   ConstantPad1dConstantPad2dConstantPad3drR   r   r   r   constant_pad_factory  s    r   )=r   
__future__r   ra   collections.abcr   typingr   torch.nnrO   monai.networks.utilsr   monai.utilsr   r   r   __all__r	   r   r
   r   r   r   r   r   r6   rT   r3   AlphaDropoutrY   r^   rc   	GroupNorm	LayerNormLocalResponseNormSyncBatchNormmodulesELUReLU	LeakyReLUPReLUReLU6SELUCELUGELUSigmoidTanhSoftmax
LogSoftmaxrs   rv   rz   r}   r   r   r   r   r   r   r   r   r   r   r   r   <module>   s   3W#




