Skip to content

Loguru logging - #113

Closed
Hendrik-code wants to merge 761 commits into
mainfrom
loguru-logging
Closed

Hendrik-code wants to merge 761 commits into
mainfrom
loguru-logging

Conversation

@Hendrik-code

@Hendrik-code Hendrik-code commented Jun 29, 2026 •

Copy link
Copy Markdown
Owner

Summary

Migrates the TPTBox.logger emission layer to Loguru while keeping the public API and terminal color coding unchanged. This is a Loguru-backed facade: every public class, method signature, Log_Type, verbose semantic,
sub-logger, String_Logger, Reflection_Logger, the global log, the logging alias, on_*/print_error/log_statistic, .prefix/.default_verbose, and create_from_bids are preserved.
Loguru replaces only the two emission primitives (the terminal write and the Logger file write), all isolated behind a new TPTBox/logger/_loguru_backend.py (the only module that imports loguru).

Backwards compatibility & color coding

  • Each Log_Type maps to a custom TPTBOX_* Loguru level whose color markup reproduces the exact original ANSI (<light-cyan>→\033[96m, <bg blue>→\033[44m, <italic>, <underline>, …).
  • A new regression test (unit_tests/test_logger.py, 10 tests) locks the contract against type2bcolors. Verified: 28/28 golden cases render identically (only invisible reset-code differences) and all 15 non-default Log_Types emit the exact color code.
  • end="\r" progress lines are preserved (the terminal sink honors end instead of Loguru's forced newline), WARNING_THROW still routes to warnings.warn, and verbose=False still suppresses.
  • File output stays ANSI-free with the exact filename scheme, header, and duration lines; multiple Loggers stay isolated.
  • Full suite: 405 passed / 4 skipped (395 prior + 10 new logger tests). The logger is imported package-wide, so this is the integration proof.

New capabilities (all opt-in, no behavior change by default)

  1. Thread/process-safe writes (verified: 3200 concurrent lines, zero interleaving). enqueue=True for multiprocessing.
  2. File rotation & retention: Logger(..., rotation="20 MB", retention="10 days", enqueue=True).
  3. User sinks / JSON / level filtering: from TPTBox.logger import loguru_logger; loguru_logger.add("run.jsonl", serialize=True, level="TPTBOX_WARNING").
  4. Exception capture: print_error emits a structured record to user sinks; opt-in install_excepthook() routes uncaught exceptions through Loguru.

Notes for reviewers

  • Global take-over: TPTBox configures the global Loguru logger at import (drops Loguru's default handler). Opt out with TPTBOX_LOGGER_TAKEOVER=0 set before importing TPTBox.
    Configuring eagerly at import (rather than lazily) is deliberate — it ensures user sinks added afterwards are never wiped by the take-over logger.remove().
  • Adds loguru = "^0.7.2" to pyproject.toml.
  • Coloring is now Loguru-native (level-driven) rather than hand-rolled ANSI, so terminal output is visually identical but not byte-identical (it differs only by redundant reset codes) — this matches the agreed "Loguru-native coloring" choice.

robert-graf and others added 30 commits July 15, 2025 10:59
robert-graf and others added 22 commits May 29, 2026 09:09
All sliding-window tiles share the same patch_size shape, so cuDNN can
autotune the fastest conv algorithms once and reuse them across tiles and
images. TF32 accelerates fp32 matmul/conv on Ampere+ GPUs with negligible
accuracy impact. Gated behind a new fast_perf flag (default True, CUDA only).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…erence

inference_mode disables autograd view/version tracking entirely, so it is
slightly faster and uses less memory than no_grad. All tensors here are pure
inference outputs (moved to CPU / converted to numpy downstream), so the
stricter inference-tensor semantics are safe.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
predict_sliding_window_return_logits runs once per fold; calling
torch.cuda.empty_cache() at its start and end returned allocator blocks to
the driver right before the next fold reallocated them (slow cudaMalloc +
sync). The pool is still cleared once per image after fold averaging, and all
OOM-recovery empty_cache() calls are untouched.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
initialize_from_trained_model_folder built loaded_networks by appending the
same self.network object once per fold, so every entry ended up holding the
LAST fold's weights. predict_logits_from_preprocessed_data then ran that one
weight set N times and averaged it, silently collapsing the N-fold ensemble to
a single fold while still paying Nx compute. Separately, cache_state_dicts=False
left loaded_networks as [] (not None), causing an IndexError in the predict
loop.

Now loaded_networks is None unless exactly one fold is present (preloaded for
zero per-prediction reloads). For >1 fold it stays None and the predict loop
swaps weights per fold via load_state_dict, restoring a correct ensemble using
a single network's worth of GPU memory. Device-availability warnings now fire
once regardless of fold count.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Every run_inference_on_file call previously reloaded the predictor from disk
and re-uploaded weights to the GPU. With cache_model=True the loaded predictor
is kept in a process-wide cache keyed by model path + folds + device/runtime
settings, so a loop over many files reuses the in-memory model. When caching,
the end-of-call del/empty_cache is skipped so the CUDA allocator pool stays
warm between images. Default is False to preserve current memory semantics; the
flag forwards through run_VibeSeg/run_vibeseg/run_nnunet via **kwargs.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
_run_sub processed one tile per forward pass, leaving the GPU underutilised for
small patches. Tiles all share patch_size, so they batch densely: with
tile_batch_size>1 they are stacked into a (B, C, *patch) tensor and run in one
pass, then scattered back per tile. Mirroring/gaussian/accumulation are
unchanged. tile_batch_size=1 (default) takes the original view-based path
verbatim, so behaviour and memory are unchanged unless opted in. Threaded
through nnUNetPredictor, load_inf_model and run_inference_on_file.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Adds benchmarks/ with a phase-resolved timing tool for run_inference_on_file
(load / preprocess / sliding-window predict / postprocess), using CUDA
synchronisation, warmup, repeats and peak-memory tracking. It instruments the
pipeline by monkeypatching (no library changes) and signature-filters its kwargs
so the same file runs against every commit in the optimisation range.

- benchmark_nnunet_inference.py: run/compare subcommands; synthetic or real input.
- bench_across_commits.sh: replays one config across baseline+each commit and
  prints per-commit deltas (isolates the always-on changes; the fold fix shows up
  as the fold_status column flipping from DUPLICATED to lazy-per-fold/distinct).
- bench_flag_sweep.sh: sweeps the opt-in flags at HEAD (cache_model needs >1 call,
  tile_batch_size, max_folds, step_size).
- README.md: usage, which tool measures which commit, and caveats.

pyproject: exempt benchmarks/ from docstring rules, mirroring the test dirs.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…vels)

Add loguru dep and a new TPTBox/logger/_loguru_backend.py: each Log_Type maps to
a custom TPTBOX_* Loguru level whose color markup reproduces the exact ANSI of
type2bcolors (light-cyan->96, bg blue->44, ...). print_to_terminal now emits via
a colorized Loguru function-sink (writing to the live sys.stdout, honoring end so
end='\r' progress lines are intact). WARNING_THROW still routes to warnings.warn.

Public API/classes/verbose semantics unchanged. Verified: 28/28 golden cases
render identically (only invisible reset-code differences) and all 15 non-default
Log_Types emit the exact expected color code.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…on/retention)

Logger now writes via a Loguru file sink instead of raw file.write. Default
keeps its own handle behind a Loguru function-sink (flush() works, 'end'
honored, ANSI-free, atexit-safe duration line). New rotation=/retention=/enqueue
kwargs switch to a Loguru-owned path sink for rotation & retention. Per-instance
record filtering keeps multiple Loggers' files isolated.

Verified: exact filename scheme + header/duration lines, no ANSI in files,
rotation produces multiple files, two-logger isolation, and the duration line is
still written at interpreter exit for unclosed loggers.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…r sinks

print_error now also emits a structured Loguru record (opt(exception=True), bound
to an 'exception' channel the default sinks ignore) so user sinks capture the
traceback; the human-readable text output is unchanged. Add install_excepthook()
to route uncaught exceptions through Loguru (opt-in). Re-export configure,
install_excepthook, and the configured loguru_logger from TPTBox.logger so callers
can attach their own sinks (JSON via serialize=True, level filtering on TPTBOX_*).

Configure now runs eagerly at import so the take-over logger.remove() only drops
Loguru's own default handler and never wipes user sinks added afterwards.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Add unit_tests/test_logger.py (10 tests) asserting the backwards-compat contract:
per-Log_Type terminal coloring matches type2bcolors, carriage-return end
preserved, WARNING_THROW->warnings.warn, verbose gating, ANSI-free + isolated
file output, and structured exception capture into user sinks. Document the
Loguru backend, TPTBOX_* levels, take-over opt-out, rotation/retention, user
sinks, and exception capture in the logger README.

Full unit suite: 405 passed / 4 skipped; thread safety verified (3200 concurrent
lines, no interleaving).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings June 29, 2026 12:49

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@Hendrik-code
Hendrik-code requested a review from robert-graf June 29, 2026 12:55
@Hendrik-code Hendrik-code linked an issue Jun 29, 2026 that may be closed by this pull request
@robert-graf

Copy link
Copy Markdown
Collaborator

Dont care

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Use Loguru

4 participants