def __call__(self, event_filter: Optional[Callable] = None, every: Optional[int] = None, once: Optional[int] = None): if not ((event_filter is not None) ^ (every is not None) ^ (once is not None)): raise ValueError( "Only one of the input arguments should be specified") if (event_filter is not None) and not callable(event_filter): raise TypeError("Argument event_filter should be a callable") if (every is not None) and not (isinstance(every, numbers.Integral) and every > 0): raise ValueError( "Argument every should be integer and greater than zero") if (once is not None) and not (isinstance(once, numbers.Integral) and once > 0): raise ValueError("Argument every should be integer and positive") if every is not None: if every == 1: # Just return the event itself return self event_filter = CallableEvents.every_event_filter(every) if once is not None: event_filter = CallableEvents.once_event_filter(once) # check signature: _check_signature("engine", event_filter, "event_filter", "event") return EventWithFilter(self, event_filter)
def add_event_handler(self, event_name: str, handler: Callable, *args, **kwargs): """Add an event handler to be executed when the specified event is fired. Args: event_name: An event to attach the handler to. Valid events are from :class:`~ignite.engine.Events` or any `event_name` added by :meth:`~ignite.engine.Engine.register_events`. handler (callable): the callable event handler that should be invoked *args: optional args to be passed to `handler`. **kwargs: optional keyword args to be passed to `handler`. Note: The handler function's first argument will be `self`, the :class:`~ignite.engine.Engine` object it was bound to. Note that other arguments can be passed to the handler in addition to the `*args` and `**kwargs` passed here, for example during :attr:`~ignite.engine.Events.EXCEPTION_RAISED`. Returns: :class:`~ignite.engine.RemovableEventHandler`, which can be used to remove the handler. Example usage: .. code-block:: python engine = Engine(process_function) def print_epoch(engine): print("Epoch: {}".format(engine.state.epoch)) engine.add_event_handler(Events.EPOCH_COMPLETED, print_epoch) Note: Since v0.3.0, Events become more flexible and allow to pass an event filter to the Engine. See :class:`~ignite.engine.Events` for more details. """ if isinstance(event_name, EventWithFilter): event_name, event_filter = event_name.event, event_name.filter handler = Engine._handler_wrapper(handler, event_name, event_filter) if event_name not in self._allowed_events: self.logger.error( "attempt to add event handler to an invalid event %s.", event_name) raise ValueError( "Event {} is not a valid event for this Engine.".format( event_name)) event_args = ( Exception(), ) if event_name == Events.EXCEPTION_RAISED else () _check_signature(self, handler, 'handler', *(event_args + args), **kwargs) self._event_handlers[event_name].append((handler, args, kwargs)) self.logger.debug("added handler for event %s.", event_name) return RemovableEventHandle(event_name, handler, self)
def __call__(self, event_filter: Optional[Callable] = None, every: Optional[int] = None, once: Optional[int] = None) -> Any: """ Makes the event class callable and accepts either an arbitrary callable as filter (which must take in the engine and current event value and return a boolean) or an every or once value Args: event_filter (callable, optional): a filter function to check if the event should be executed when the event type was fired every (int, optional): a value specifying how often the event should be fired once (int, optional): a value specifying when the event should be fired (if only once) Returns: CallableEventWithFilter: A new event having the same value but a different filter function """ if not ((event_filter is not None) ^ (every is not None) ^ (once is not None)): raise ValueError( "Only one of the input arguments should be specified") if (event_filter is not None) and not callable(event_filter): raise TypeError("Argument event_filter should be a callable") if (every is not None) and not (isinstance(every, numbers.Integral) and every > 0): raise ValueError( "Argument every should be integer and greater than zero") if (once is not None) and not (isinstance(once, numbers.Integral) and once > 0): raise ValueError("Argument every should be integer and positive") if every is not None: if every == 1: # Just return the event itself event_filter = None else: event_filter = self.every_event_filter(every) if once is not None: event_filter = self.once_event_filter(once) # check signature: if event_filter is not None: _check_signature("engine", event_filter, "event_filter", "event") return CallableEventWithFilter(self.value, event_filter, self.name)
def _get_args_kwargs(self, engine_: Engine, **kwargs: Any) -> Tuple[tuple, dict]: kwargs = CfgNode._eval(CfgNode(kwargs), self.global_context, self.local_context, eval_all=True) if self._needs_engine is None: try: _check_signature(self.handler, 'handler', engine_, **kwargs) self._needs_engine = True except ValueError: self._needs_engine = False args = (engine_, ) if self._needs_engine else () return args, kwargs
def __init__(self, process_function): self._event_handlers = defaultdict(list) self.logger = logging.getLogger(__name__ + "." + self.__class__.__name__) self._process_function = process_function self.last_event_name = None self.should_terminate = False self.should_terminate_single_epoch = False self.state = None self._allowed_events = [] self._dataloader_iter = None self._init_iter = [] self.register_events(*Events) if self._process_function is None: raise ValueError("Engine must be given a processing function in order to run.") _check_signature(self, process_function, 'process_function', None)
def __init__(self, process_function: Callable): self._event_handlers = defaultdict(list) # type: Dict[Any, List] self.logger = logging.getLogger(__name__ + "." + self.__class__.__name__) self._process_function = process_function self.last_event_name = None # type: Optional[Events] self.should_terminate = False self.should_terminate_single_epoch = False self.state = State() self._state_dict_user_keys = [] # type: List[str] self._allowed_events = [] # type: List[EventEnum] self._dataloader_iter = None # type: Optional[Iterator[Any]] self._init_iter = [] # type: List[int] self.register_events(*Events) if self._process_function is None: raise ValueError( "Engine must be given a processing function in order to run.") _check_signature(process_function, "process_function", self, None)
def add_event_handler(self, event_name: Any, handler: Callable, *args, **kwargs): """Add an event handler to be executed when the specified event is fired. Args: event_name: An event or a list of events to attach the handler. Valid events are from :class:`~ignite.engine.events.Events` or any ``event_name`` added by :meth:`~ignite.engine.engine.Engine.register_events`. handler (callable): the callable event handler that should be invoked. No restrictions on its signature. The first argument can be optionally `engine`, the :class:`~ignite.engine.engine.Engine` object, handler is bound to. *args: optional args to be passed to ``handler``. **kwargs: optional keyword args to be passed to ``handler``. Note: Note that other arguments can be passed to the handler in addition to the `*args` and `**kwargs` passed here, for example during :attr:`~ignite.engine.events.Events.EXCEPTION_RAISED`. Returns: :class:`~ignite.engine.RemovableEventHandle`, which can be used to remove the handler. Example usage: .. code-block:: python engine = Engine(process_function) def print_epoch(engine): print("Epoch: {}".format(engine.state.epoch)) engine.add_event_handler(Events.EPOCH_COMPLETED, print_epoch) events_list = Events.EPOCH_COMPLETED | Events.COMPLETED def execute_something(): # do some thing not related to engine pass engine.add_event_handler(events_list, execute_something) Note: Since v0.3.0, Events become more flexible and allow to pass an event filter to the Engine. See :class:`~ignite.engine.events.Events` for more details. """ if isinstance(event_name, EventsList): for e in event_name: self.add_event_handler(e, handler, *args, **kwargs) return RemovableEventHandle(event_name, handler, self) if (isinstance(event_name, CallableEventWithFilter) and event_name.filter != CallableEventWithFilter.default_event_filter): event_filter = event_name.filter handler = self._handler_wrapper(handler, event_name, event_filter) if event_name not in self._allowed_events: self.logger.error( "attempt to add event handler to an invalid event %s.", event_name) raise ValueError( "Event {} is not a valid event for this Engine.".format( event_name)) event_args = ( Exception(), ) if event_name == Events.EXCEPTION_RAISED else () try: _check_signature(handler, "handler", self, *(event_args + args), **kwargs) self._event_handlers[event_name].append( (handler, (self, ) + args, kwargs)) except ValueError: _check_signature(handler, "handler", *(event_args + args), **kwargs) self._event_handlers[event_name].append((handler, args, kwargs)) self.logger.debug("added handler for event %s.", event_name) return RemovableEventHandle(event_name, handler, self)