Logging
Overview
SimpleITK creates debug, warning and error messages intended for display or logging. The messaging and logging are handled by a customizable class in ITK, the OutputWindow. The default implementation prints these messages to the standard error. A derived class could print the messages to standard out or adapt the output to fit within another logging framework. Errors in SimpleITK usually cause exceptions so any error message is unlikely. Warnings are more likely and are enabled globally by default, but can be disabled with the ProcessObject::SetGlobalWarningDisplay method. Debug messages are set on a per object basis with the SetDebug method. The default value for new objects is set by the ProcessObject::SetGlobalDefaultDebug method. Disabled messages are not sent to the logging handler for efficiency.
The following example illustrates how to create a custom logging handler in SimpleITK. The example derives a class from the LoggerBase class to customize the logging behavior. The custom logger is then set as the ITK global logging handler, and then the original logger is restored.
Code
""" A SimpleITK example that demonstrates how to adapt SimpleITK messages
to be handled by a Python Logger object. """
import logging
import os
import SimpleITK as sitk
class SimpleITKLogger(sitk.LoggerBase):
"""
Adapts SimpleITK messages to be handled by a Python Logger object.
Allows using the logging module to control the handling of messages coming
from ITK and SimpleTK. Messages such as debug and warnings are handled by
objects derived from sitk.LoggerBase.
The LoggerBase.SetAsGlobalITKLogger method must be called to enable
SimpleITK messages to use the logger.
The Python logger module adds a second layer of control for the logging
level in addition to the controls already in SimpleITK.
The "Debug" property of a SimpleITK object must be enabled (if
available) and the support from the Python "logging flow" hierarchy
to handle debug messages from a SimpleITK object.
Warning messages from SimpleITK are globally disabled with
ProcessObject:GlobalWarningDisplayOff.
"""
def __init__(self, logger: logging.Logger = logging.getLogger("SimpleITK")):
"""
Initializes with a Logger object to handle the messages emitted from
SimpleITK/ITK.
"""
super().__init__()
self._logger = logger
@property
def logger(self):
""" return the logger object """
return self._logger
@logger.setter
def logger(self, logger):
""" set the logger object """
self._logger = logger
def __enter__(self):
""" Set this object as the global ITK logger. """
self._old_logger = self.SetAsGlobalITKLogger()
return self
def __exit__(self, exc_type, exc_val, exc_tb):
""" Restore the previous global ITK logger. """
self._old_logger.SetAsGlobalITKLogger()
del self._old_logger
def DisplayText(self, s):
""" Display text message. """
# Remove newline endings from SimpleITK/ITK messages since the Python
# logger adds during output.
self._logger.info(s.rstrip())
def DisplayErrorText(self, s):
self._logger.error(s.rstrip())
def DisplayWarningText(self, s):
self._logger.warning(s.rstrip())
def DisplayGenericOutputText(self, s):
self._logger.info(s.rstrip())
def DisplayDebugText(self, s):
self._logger.debug(s.rstrip())
# Enable all debug messages for all ProcessObjects, and procedures
sitk.ProcessObject.GlobalDefaultDebugOn()
# Construct a SimpleITK logger to Python Logger adaptor
sitkLogger = SimpleITKLogger()
# Configure ITK to use the logger adaptor
sitkLogger.SetAsGlobalITKLogger()
# Configure the Python root logger, enabling debug and info level messages.
logging.basicConfig(format="%(name)s (%(levelname)s): %(message)s", level=logging.DEBUG)
img = sitk.GaborSource(size=[64, 64, 64], frequency=4.0 / 64)
with SimpleITKLogger(logging.getLogger("Show")) as showLogger:
print(f"Logger name: {showLogger.GetName()}")
if "SITK_NOSHOW" not in os.environ:
sitk.Show(img, debugOn=True)