Source code for ipa.data_loader.log

import logging
import functools
from datetime import datetime
from pathlib import Path
import inspect
import sys

def setup_simple_logger(func_name, log_dir="logs", console_output=False):
    """
    Quick setup for logger with timestamped file output.
    
    Creates a logger that writes to a timestamped file in the specified directory.
    The logger is configured with INFO level and UTF-8 encoding for international
    character support.
    
    Args:
        func_name (str): Name of the function or analysis, used in log filename
        log_dir (str or Path): Directory to store log files. Defaults to "logs"
        console_output (bool): Whether to also print logs to console. Defaults to False.
    
    Returns:
        logging.Logger: Configured logger instance with file handler
        
    Example:
        >>> logger = setup_simple_logger("data_analysis", "analysis_logs")
        >>> logger.info("Starting analysis")
        # Creates: analysis_logs/data_analysis_20240115_143025.log
    """
    log_dir = Path(log_dir)
    log_dir.mkdir(exist_ok=True)
    
    timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
    log_file = log_dir / f"{func_name}_{timestamp}.log"
    
    logger = logging.getLogger(f"{func_name}_{timestamp}")
    logger.setLevel(logging.INFO)
    
    # Clear existing handlers to avoid duplicates if called multiple times
    logger.handlers.clear()
    
    # File Handler
    file_handler = logging.FileHandler(log_file, encoding='utf-8')
    file_formatter = logging.Formatter('%(asctime)s - %(levelname)s - %(message)s')
    file_handler.setFormatter(file_formatter)
    logger.addHandler(file_handler)
    
    # Console Handler (Optional)
    if console_output:
        console_handler = logging.StreamHandler(sys.stdout)
        console_formatter = logging.Formatter('%(levelname)s: %(message)s')
        console_handler.setFormatter(console_formatter)
        logger.addHandler(console_handler)
    
    return logger

[docs] def log_analysis(log_dir="logs"): """ Decorator: Automatically log function execution process. This decorator provides automatic logging for data analysis functions. It logs function start/completion, automatically detects and logs file paths from function parameters, handles exceptions, and logs output files. Args: log_dir (str or Path): Directory to store log files. Defaults to "logs" Returns: function: Decorated function with automatic logging capabilities """ def decorator(func): @functools.wraps(func) def wrapper(*args, **kwargs): # Setup logger logger = setup_simple_logger(func.__name__, log_dir) # Start logging logger.info(f"Starting execution: {func.__name__}") # Log parameters (if file paths exist) sig = inspect.signature(func) bound_args = sig.bind(*args, **kwargs) bound_args.apply_defaults() for param_name, param_value in bound_args.arguments.items(): if isinstance(param_value, (str, Path)) and ('path' in param_name.lower() or 'file' in param_name.lower()): logger.info(f"Input path: {param_value}") elif param_name in ['output_dir', 'save_dir', 'result_path']: logger.info(f"Output path: {param_value}") try: # Execute function result = func(*args, **kwargs) logger.info(f"Completed execution: {func.__name__}") # If result contains file paths, log them if isinstance(result, (str, Path)): logger.info(f"Generated file: {result}") elif isinstance(result, (list, tuple)) and result and isinstance(result[0], (str, Path)): for file_path in result: logger.info(f"Generated file: {file_path}") return result except Exception as e: logger.error(f"Execution failed: {func.__name__} - {str(e)}") raise return wrapper return decorator
# Simpler version - manual logging
[docs] class QuickLogger: """ Simple interface for step-by-step logging in data analysis workflows. Provides predefined methods for common logging scenarios including analysis steps, input/output files, and error handling. Creates timestamped log files automatically. Args: name (str): Logger name, used in log filename. Defaults to "analysis" log_dir (str or Path): Directory to store log files. Defaults to "logs" console_output (bool): Whether to print logs to console. Defaults to True. Attributes: logger (logging.Logger): Internal logger instance """ def __init__(self, name="analysis", log_dir="logs", console_output=True): self.logger = setup_simple_logger(name, log_dir, console_output=console_output)
[docs] def step(self, message): """ Log analysis step or general information. Args: message (str): Step description or information message Example: >>> logger.step("Loading mask data...") >>> logger.step(f"Processing dataset: {dataid}") """ self.logger.info(message)
[docs] def file_in(self, file_path): """ Log input file path. Args: file_path (str or Path): Path to input file Example: >>> logger.file_in("/data/images/sample.tif") >>> logger.file_in(mask_pm_path) """ self.logger.info(f"Input file: {file_path}")
[docs] def file_out(self, file_path): """ Log output file path. Args: file_path (str or Path): Path to generated output file Example: >>> logger.file_out("/results/processed.tif") >>> logger.file_out(xvg_path) """ self.logger.info(f"Output file: {file_path}")
[docs] def error(self, message): """ Log error message. Args: message (str): Error description Example: >>> logger.error("Failed to load input file") >>> logger.error(f"Processing failed: {str(e)}") """ self.logger.error(message)