o
    i\"                     @  sP   d Z ddlmZ ddlmZ g dZdddZdd	 Zd
d ZG dd dZ	dS )a  
How to use the adaptor function
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

The key to using 'adaptor' lies in understanding the function that want to
adapt. The 'inputs' and 'outputs' parameters take either strings, lists/tuples
of strings or a dictionary mapping strings, depending on call signature of the
function being called.

The adaptor function is written to minimise the cognitive load on the caller.
There should be a minimal number of cases where the caller has to set anything
on the input parameter, and for functions that return a single value, it is
only necessary to name the dictionary keyword to which that value is assigned.

Use of `outputs`
----------------

`outputs` can take either a string, a list/tuple of string or a dict of string
to string, depending on what the transform being adapted returns:

    - If the transform returns a single argument, then outputs can be supplied a
      string that indicates what key to assign the return value to in the
      dictionary
    - If the transform returns a list/tuple of values, then outputs can be supplied
      a list/tuple of the same length. The strings in outputs map the return value
      at the corresponding position to a key in the dictionary
    - If the transform returns a dictionary of values, then outputs must be supplied
      a dictionary that maps keys in the function's return dictionary to the
      dictionary being passed between functions

Note, the caller is free to use a more complex way of specifying the outputs
parameter than is required. The following are synonymous and will be treated
identically:

.. code-block:: python

   # single argument
   adaptor(MyTransform(), 'image')
   adaptor(MyTransform(), ['image'])
   adaptor(MyTransform(), {'image': 'image'})

   # multiple arguments
   adaptor(MyTransform(), ['image', 'label'])
   adaptor(MyTransform(), {'image': 'image', 'label': 'label'})

Use of `inputs`
---------------

`inputs` can usually be omitted when using `adaptor`. It is only required when a
the function's parameter names do not match the names in the dictionary that is
used to chain transform calls.

.. code-block:: python

    class MyTransform1:
        def __call__(self, image):
            # do stuff to image
            return image + 1


    class MyTransform2:
        def __call__(self, img_dict):
            # do stuff to image
            img_dict["image"] += 1
            return img_dict


    xform = Compose([adaptor(MyTransform1(), "image"), MyTransform2()])
    d = {"image": 1}
    print(xform(d))

    >>> {'image': 3}

.. code-block:: python

    class MyTransform3:
        def __call__(self, img_dict):
            # do stuff to image
            img_dict["image"] -= 1
            img_dict["segment"] = img_dict["image"]
            return img_dict


    class MyTransform4:
        def __call__(self, img, seg):
            # do stuff to image
            img -= 1
            seg -= 1
            return img, seg


    xform = Compose([MyTransform3(), adaptor(MyTransform4(), ["img", "seg"], {"image": "img", "segment": "seg"})])
    d = {"image": 1}
    print(xform(d))

    >>> {'image': 0, 'segment': 0, 'img': -1, 'seg': -1}

Inputs:

- dictionary in: None | Name maps
- params in (match): None | Name list | Name maps
- params in (mismatch): Name maps
- params & `**kwargs` (match) : None | Name maps
- params & `**kwargs` (mismatch) : Name maps

Outputs:

- dictionary out: None | Name maps
- list/tuple out: list/tuple
- variable out: string

    )annotations)Callable)adaptorapply_alias	to_kwargsFunctionSignatureNc                   s<   dd dd dd dd  fd	d
}|S )Nc                 S  s8   |d urt ||std|  d| dt| d S d S )N'z' must be None or one of  but is 
isinstance	TypeErrortypevariable_namevariabletypes r   [/home/dell461/cl/sdc2/last_ska_mid/HISourceFinder-master-l/src/monai/transforms/adaptors.pymust_be_types_or_none   s
   
z&adaptor.<locals>.must_be_types_or_nonec                 S  s,   t ||std|  d| dt| d S )Nr   z' must be one of r	   r
   r   r   r   r   must_be_types   s   
zadaptor.<locals>.must_be_typesc                   s    fdd|   D S )Nc                   s   i | ]
\}} |||qS r   r   .0kv	input_mapr   r   
<dictcomp>   s    z.adaptor.<locals>.map_names.<locals>.<dictcomp>itemsditemsr   r   r   r   	map_names      zadaptor.<locals>.map_namesc                   s    fdd|  D S )Nc                      i | ]	\}}| | qS r   r   r   r    r   r   r          z3adaptor.<locals>.map_only_names.<locals>.<dictcomp>r   r   r   r$   r   map_only_names   r"   zadaptor.<locals>.map_only_namesc                   s  t jrdtf d u rt|  nM|  nGfdd|  D  dttttf d u r7n-ttrNtj	dkrGt
d|  i ntttfr_ fddD  n|  di  	}ttrd|tf |d urfdd| D n]tttfrtdkrd|tttf nd|ttf t|tr|g}tt	krt
d	tt|n"d|tttf t|ttfrt|dkrt
d
|d }|it| }  D ]\}}|| |< q| S )Ninputsc                   s    i | ]\}}| j v r||qS r   )non_var_parametersr   )sigr   r   r      s     z+adaptor.<locals>._inner.<locals>.<dictcomp>   zOif 'inputs' is a string, function may only have a single non-variadic parameterc                   s   i | ]}| | qS r   r   )r   r   )dinputsr   r   r      s    outputsc                   r#   r   r   r   )retr   r   r      r%   zP'outputs' must have the same length as the number of elements that were returnedz8'outputs' must be of length one if it is a list or tupler   r   )r   found_kwargsdictr   strlisttupler   lenr(   
ValueErrorzip)r    opr   r   functionr'   r!   r&   r   r   r,   )r+   r-   r)   r   _inner   sV   





zadaptor.<locals>._innerr   )r8   r,   r'   r9   r   r7   r   r      s   @r   c                   s    fdd}|S )Nc                   sT   t | } D ]\}}||||< q |} D ]\}}||||< q|S N)r/   r   pop)dataZpre_callZ_from_toZ	post_callfnname_mapr   r   r9      s   zapply_alias.<locals>._innerr   )r?   r@   r9   r   r>   r   r      s   r   c                   s    fdd}|S )Nc                   s    di | S )Nr   r   )r<   r?   r   r   r9      s   zto_kwargs.<locals>._innerr   )r?   r9   r   rA   r   r      s   r   c                   @  s*   e Zd ZdddZddd	Zdd
dZdS )r   r8   r   returnNonec                 C  s   dd l }||}d| _d| _i | _t | _|j D ](}|j	|j
ju r'd| _|j	|j
ju r2d| _q| j|j |j|ju| j|j< qd S )Nr   FT)inspect	signature
found_argsr.   defaultssetr(   
parametersvalueskind	ParameterVAR_POSITIONALVAR_KEYWORDaddnamedefaultempty)selfr8   rD   Zsfnpr   r   r   __init__   s   
zFunctionSignature.__init__r0   c                 C  s   d}| | j| j| jS )NzG<class 'FunctionSignature': found_args={}, found_kwargs={}, defaults={})formatrF   r.   rG   )rS   sr   r   r   __repr__  s   zFunctionSignature.__repr__c                 C  s   |   S r:   )rX   )rS   r   r   r   __str__
  s   zFunctionSignature.__str__N)r8   r   rB   rC   )rB   r0   )__name__
__module____qualname__rU   rX   rY   r   r   r   r   r      s    

r   r:   )
__doc__
__future__r   typingr   __all__r   r   r   r   r   r   r   r   <module>   s   
q
T