o
    i@7                     @  s   d dl mZ d dlZd dlZd dlmZmZ d dlmZm	Z	 d dl
Z
d dlmZ d dlmZmZmZmZmZ edejed\ZZerId d	lmZ nedejed
dd\ZZdZdZG dd dZdS )    )annotationsN)CallableSequence)TYPE_CHECKINGAny)
get_logger)
IgniteInfoflatten_dict	is_scalarmin_versionoptional_importzignite.engineEvents)Enginer   	decorator)as_typez{}: {:.4f} Lossc                
   @  st   e Zd ZdZdddddd dd ddeef
d-ddZd.ddZd.d d!Zd.d"d#Z	d/d'd(Z
d.d)d*Zd.d+d,ZdS )0StatsHandlera  
    StatsHandler defines a set of Ignite Event-handlers for all the log printing logics.
    It can be used for any Ignite Engine(trainer, validator and evaluator).
    And it can support logging for epoch level and iteration level with pre-defined loggers.

    Note that if ``name`` is None, this class will leverage `engine.logger` as the logger, otherwise,
    ``logging.getLogger(name)`` is used. In both cases, it's important to make sure that the logging level is at least
    ``INFO``. To change the level of logging, please call ``import ignite; ignite.utils.setup_logger(name)``
    (when ``name`` is not None) or ``engine.logger = ignite.utils.setup_logger(engine.logger.name, reset=True)``
    (when ``name`` is None) before running the engine with this handler attached.

    Default behaviors:
        - When EPOCH_COMPLETED, logs ``engine.state.metrics`` using ``self.logger``.
        - When ITERATION_COMPLETED, logs
          ``self.output_transform(engine.state.output)`` using ``self.logger``.

    Usage example::

        import ignite
        import monai

        trainer = ignite.engine.Engine(lambda x, y: [0.0])  # an example trainer
        monai.handlers.StatsHandler(name="train_stats").attach(trainer)

        trainer.run(range(3), max_epochs=4)

    More details of example is available in the tutorial:
    https://github.com/Project-MONAI/tutorials/blob/master/modules/engines/unet_training_dict.py.

    TNc                 C  s   | d S )Nr    xr   r   ^/home/dell461/cl/sdc2/last_ska_mid/HISourceFinder-master-l/src/monai/handlers/stats_handler.py<lambda>J   s    zStatsHandler.<lambda>c                 C  s   | S )Nr   r   r   r   r   r   K   s    zmonai.handlers.StatsHandleriteration_log$bool | Callable[[Engine, int], bool]	epoch_logepoch_print_loggerCallable[[Engine], Any] | Noneiteration_print_loggeroutput_transformr   global_epoch_transformstate_attributesSequence[str] | Nonename
str | Nonetag_namestrkey_var_formatreturnNonec                 C  sJ   || _ || _|| _|| _|| _|| _|| _|	| _|
| _t	|| _
|| _dS )a
  

        Args:
            iteration_log: whether to log data when iteration completed, default to `True`. ``iteration_log`` can
                be also a function and it will be interpreted as an event filter
                (see https://pytorch.org/ignite/generated/ignite.engine.events.Events.html for details).
                Event filter function accepts as input engine and event value (iteration) and should return True/False.
                Event filtering can be helpful to customize iteration logging frequency.
            epoch_log: whether to log data when epoch completed, default to `True`. ``epoch_log`` can be
                also a function and it will be interpreted as an event filter. See ``iteration_log`` argument for more
                details.
            epoch_print_logger: customized callable printer for epoch level logging.
                Must accept parameter "engine", use default printer if None.
            iteration_print_logger: customized callable printer for iteration level logging.
                Must accept parameter "engine", use default printer if None.
            output_transform: a callable that is used to transform the
                ``ignite.engine.state.output`` into a scalar to print, or a dictionary of {key: scalar}.
                In the latter case, the output string will be formatted as key: value.
                By default this value logging happens when every iteration completed.
                The default behavior is to print loss from output[0] as output is a decollated list
                and we replicated loss value for every item of the decollated list.
                `engine.state` and `output_transform` inherit from the ignite concept:
                https://pytorch.org/ignite/concepts.html#state, explanation and usage example are in the tutorial:
                https://github.com/Project-MONAI/tutorials/blob/master/modules/batch_output_transform.ipynb.
            global_epoch_transform: a callable that is used to customize global epoch number.
                For example, in evaluation, the evaluator engine might want to print synced epoch number
                with the trainer engine.
            state_attributes: expected attributes from `engine.state`, if provided, will extract them
                when epoch completed.
            name: identifier of `logging.logger` to use, if None, defaulting to ``engine.logger``.
            tag_name: when iteration output is a scalar, tag_name is used to print
                tag_name: scalar_value to logger. Defaults to ``'Loss'``.
            key_var_format: a formatting string to control the output string format of key: value.

        N)r   r   r   r   r   r   r    r$   r&   r   loggerr"   )selfr   r   r   r   r   r   r    r"   r$   r&   r   r   r   __init__D   s   1

zStatsHandler.__init__enginer   c                 C  s   | j du r	|j| _| j tjkr<d| jj  d}| jj |jj kr+|d|jj  d7 }|d7 }td| jj  d|  | jr\|| j	t
js\t
j}t| jrU|| jd}||| j	 | jr||| jt
js|t
j}t| jru|| jd}||| j || jt
js|t
j| j dS dS )	z
        Register a set of Ignite Event-Handlers to a specified Ignite engine.

        Args:
            engine: Ignite Engine, it can be a trainer, validator or evaluator.

        Nz+

import ignite
ignite.utils.setup_logger('z', reset=True)z
ignite.utils.setup_logger('z

zthe effective log level of z~ is higher than INFO, StatsHandler may not output logs,
please use the following code before running the engine to enable it: )event_filter)r"   r)   getEffectiveLevelloggingINFOwarningswarnr   has_event_handleriteration_completedr   ITERATION_COMPLETEDcallableadd_event_handlerr   epoch_completedEPOCH_COMPLETEDexception_raisedEXCEPTION_RAISED)r*   r,   Z	suggestedeventr   r   r   attach   s2   


zStatsHandler.attachc                 C  &   | j dur|  | dS | | dS )a  
        Handler for train or validation/evaluation epoch completed Event.
        Print epoch level log, default values are from Ignite `engine.state.metrics` dict.

        Args:
            engine: Ignite Engine, it can be a trainer, validator or evaluator.

        N)r   _default_epoch_printr*   r,   r   r   r   r8         
	zStatsHandler.epoch_completedc                 C  r>   )a  
        Handler for train or validation/evaluation iteration completed Event.
        Print iteration level log, default values are from Ignite `engine.state.output`.

        Args:
            engine: Ignite Engine, it can be a trainer, validator or evaluator.

        N)r   _default_iteration_printr@   r   r   r   r4      rA   z StatsHandler.iteration_completed_enginee	Exceptionc                 C  s   | j d|  |)a  
        Handler for train or validation/evaluation exception raised Event.
        Print the exception information and traceback. This callback may be skipped because the logic
        with Ignite can only trigger the first attached handler for `EXCEPTION_RAISED` event.

        Args:
            _engine: Ignite Engine, unused argument.
            e: the exception caught in Ignite during engine.run().

        zException: )r)   	exception)r*   rC   rD   r   r   r   r:      s   zStatsHandler.exception_raisedc                 C  sX  |  |jj}t|jj}|durDt|dkrDd| d}t|D ]}|| }|t|r3| j	||n| dt
| 7 }q!| j| t|jdr}t|jdr}t|jdr}|jjdur}d	|jj d
}|d|jj d
7 }|d|jj 7 }| j| | jdurt| jdkrd}| jD ]}|| dt|j|d d
7 }q| j| dS dS dS )a(  
        Execute epoch level log operation.
        Default to print the values from Ignite `engine.state.metrics` dict and
        print the values of specified attributes of `engine.state`.

        Args:
            engine: Ignite Engine, it can be a trainer, validator or evaluator.

        Nr   zEpoch[z] Metrics -- z: key_metric_namebest_metricbest_metric_epochzKey metric:  zbest value: z
at epoch: zState values: )r   stateepochr	   metricslensortedr
   r&   formatr%   r)   infohasattrrG   rH   rI   r    getattr)r*   r,   current_epochZprints_dictout_strr"   valueattrr   r   r   r?      s2   
.



 z!StatsHandler._default_epoch_printc              	   C  sD  |  |jj}|du rdS d}t|trCt|D ])}|| }t|s.td	|t
| q|| j	|t|tjr=| n|7 }qn#t|r\|| j	| jt|tjrW| n|7 }n
td	t
| |sjdS |jj}|jj}|dur~|d | d }|jj}|jj}	d| d|	 d| d| d		}
| jd
|
|g dS )a  
        Execute iteration log operation based on Ignite `engine.state.output` data.
        Print the values from `self.output_transform(engine.state.output)`.
        Since `engine.state.output` is a decollated list and we replicated the loss value for every item
        of the decollated list, the default behavior is to print the loss from `output[0]`.

        Args:
            engine: Ignite Engine, it can be a trainer, validator or evaluator.

        N zignoring non-scalar output in StatsHandler, make sure `output_transform(engine.state.output)` returns a scalar or dictionary of key and scalar pairs to avoid this warning. {}:{}zignoring non-scalar output in StatsHandler, make sure `output_transform(engine.state.output)` returns a scalar or a dictionary of key and scalar pairs to avoid this warning. {}   zEpoch: /z, Iter: z --rJ   )r   rK   output
isinstancedictrO   r
   r1   r2   rP   typer&   torchTensoritemr$   epoch_length	iterationrL   
max_epochsr)   rQ   join)r*   r,   lossrU   r"   rV   num_iterationscurrent_iterationrT   Z
num_epochsbase_strr   r   r   rB      sB   
(
z%StatsHandler._default_iteration_print)r   r   r   r   r   r   r   r   r   r   r   r   r    r!   r"   r#   r$   r%   r&   r%   r'   r(   )r,   r   r'   r(   )rC   r   rD   rE   r'   r(   )__name__
__module____qualname____doc__DEFAULT_TAGDEFAULT_KEY_VAL_FORMATr+   r=   r8   r4   r:   r?   rB   r   r   r   r   r   $   s&    !
=
 


$r   )
__future__r   r/   r1   collections.abcr   r   typingr   r   r_   
monai.appsr   monai.utilsr   r	   r
   r   r   OPT_IMPORT_VERSIONr   _ignite.enginer   ro   rn   r   r   r   r   r   <module>   s"   
