Tracking: rebased and refactored Cotracker integration#187
Draft
C-Achard wants to merge 67 commits intocy/refactor-fix-traj-plot-y-axis-rebasedfrom
Draft
Tracking: rebased and refactored Cotracker integration#187C-Achard wants to merge 67 commits intocy/refactor-fix-traj-plot-y-axis-rebasedfrom
C-Achard wants to merge 67 commits intocy/refactor-fix-traj-plot-y-axis-rebasedfrom
Conversation
Introduce an in-memory debug recorder and helper functions for collecting diagnostics. Adds install_debug_recorder/get_debug_recorder and InMemoryDebugRecorder (bounded deque, fail-open, no I/O, safe message/exception handling) attached to the 'napari-deeplabcut' logger. Also adds collect_environment_summary, summarize_layer, summarize_viewer, and format_debug_report to produce a redact-safe diagnostic report with environment info, viewer/layer summaries, and recent plugin logs.
Introduce build_debug_report to assemble environment info, viewer summary, and recorder logs into the existing format_debug_report. It accepts a viewer, an optional InMemoryDebugRecorder and a log_limit (default 300), uses recorder.render_text when available, and falls back to a placeholder string. Also adds a top-of-file path comment.
Introduce a new debug text viewer dialog (src/napari_deeplabcut/ui/debug_window.py). Adds DebugTextWindow — a read-only, refreshable, copyable dialog using a text provider callable, with fixed-width font and optional Ctrl/Cmd-C shortcut. Also adds helper providers make_log_text_provider and make_issue_report_provider to adapt InMemoryDebugRecorder and build_debug_report for display. Handles provider exceptions gracefully and provides status feedback when copying to the clipboard.
Install a debug recorder and add a "Generate debug log" help-menu action that opens a DebugTextWindow with recent plugin logs (using make_issue_report_provider/get_debug_recorder). Move and consolidate label_mode/color_mode handlers and related multi-animal checks earlier in the file.
Rename several menu actions to include "napari-dlc" (debug log, tutorial, shortcuts) to make the plugin-specific commands explicit. Change DebugTextWindow instantiation to use self as the parent instead of viewer.window._qt_window to ensure correct parenting. Replace moveCursor call with QTextCursor.MoveOperation.Start and add the QTextCursor import for a reliable cursor move to the start. Minor comment/separator added.
Introduce logger.debug statements across KeypointControls to aid debugging of layer setup, merging, and adoption flows. Log context includes layer name/type, metadata (project, root, paths length), store counts, allowed merges, and keypoint diffs when merging. Also minor refactor to use a local md variable (layer.metadata or {}) and copy it for new_metadata.
Reduce the minimum in-memory log buffer from 10 to 1 (use max(1, int(capacity))) so callers can specify very small capacities. Also normalize _safe_tail output to POSIX-style strings by calling as_posix() on returned Path objects to ensure consistent path formatting across platforms and avoid backslashes on Windows.
Add comprehensive unit tests for the debug UI and recorder utilities. Tests cover DebugTextWindow behaviors (initial load, refresh, copy, shortcut, failure handling) and the text providers (log and issue report). Add tests for InMemoryDebugRecorder (installation idempotency, capture of messages and exceptions, bounded capacity, clear, render_text, and handling unrenderable messages). Also test helper utilities: _safe_tail, collect_environment_summary, summarize_layer, summarize_viewer, and format_debug_report. Uses qtbot for GUI tests and simple fakes/mocks for viewers/layers and recorder.
Extract plugin-related UI setup into _add_plugin_actions and consolidate repeated form builders (_form_dropdown_menus, _form_mode_radio_buttons, _form_color_mode_selector). Move help-menu actions (tutorial, shortcuts, debug log) and global keybinding installation into a single helper and remove duplicated method definitions to reduce code dispersion and improve readability. No functional changes intended.
Introduce a new core.layer_lifecycle package (manager, registry, merge types) to centralize viewer layer lifecycle handling and managed Points runtime attachments. Integrate the new LayerLifecycleManager into _widgets.py (instantiate manager, comment out direct viewer layer signal hookups) and add a debug log in on_insert. The RuntimeRegistry and ManagedPointsRuntime provide weak-ref backed registrations for managed Points layers, while MergeDecision types define merge policy primitives.
Replace KeypointControls' internal _stores usage with LayerLifecycleManager and update lifecycle wiring. KeypointControls now creates LayerLifecycleManager(owner=self), calls attach(), and defers points registration/unregistration and layer queries to the manager (new managed_points_layers/iter_managed_points/managed_points_count/has_managed_points helpers). Deprecated direct _stores access and updated TrailsController and various control paths to use the manager API. LayerLifecycleManager constructor now accepts owner, derives viewer from owner, supports QObject parenting, and adds register_managed_layer wrapper that delegates to register_managed_points_layer (with stricter type checks). Also added iteration helpers and counting convenience methods. Minor registry file: added logger setup.
Replace direct accesses to the private _stores dict with the public layer manager API in tests. Tests now call get_layer_store(...) (controls/keypoint_controls) and use register_managed_layer(...) instead of assigning into _stores, improving encapsulation and avoiding reliance on internal state. Updated test files: e2e/test_layer_coloring.py, e2e/test_overwrite_and_merge.py, e2e/test_points_layers.py, e2e/test_routing_and_provenance.py, and test_widgets.py.
Add unit tests for LayerLifecycleManager and RuntimeRegistry. Tests cover idempotent attach/detach, registering/unregistering managed points, on_insert/on_remove behavior delegating to owner methods, adopting existing layers while skipping already-managed points, resolving inserted layers from event payloads, and manager remapping/refresh calls. Also add RuntimeRegistry tests for register/get/require/unregister roundtrips, duplicate registration errors, items/layers/runtimes consistency, and purging dead weakrefs. Includes small test helpers (dummy viewer/owner/layers).
Major refactor of the layer lifecycle registry and manager to centralize layer liveness resolution and provide observable cleanup/auditing. Key changes: - RuntimeRegistry now tracks entries by stable layer_id (id(layer)) and resolves layer liveness via weakrefs; ManagedPointsRuntime stores layer_id instead of a strong layer reference. - Added diagnostic types: ClearedRegistryEntry, RegistryAuditIssue, RegistryAuditReport, and an audit() API to produce a structured report of live/dead entries and issues. - Added clear_dead_entries() to remove and return dead entries (with optional logging) so reaping is observable instead of implicit/purge-on-access. - Introduced live-focused iterators and accessors: iter_live_items(), iter_live_layers(), iter_live_runtimes(), resolve_live_layer(), get_live_runtime()/require_live_runtime(), get_store()/require_store(), and layer_ids()/contains_layer_id(). - Registry methods now validate runtime.layer_id consistency and fall back to strong storage with a logged error if an object cannot be weak-referenced. - RuntimeRegistry.assert_consistent() now uses the audit report and raises if issues exist. Manager and widget updates: - LayerLifecycleManager exposes new facade methods (resolve_live_layer, get_live_runtime, get_store, require_store, clear_dead_entries, audit_registry) and adapts registration/unregistration to accept layer objects or ids. - Iteration and counting use live-only iterators; register ensures runtime.layer_id matches the actual layer id. - KeypointControls close handler now clears dead entries and logs an audit report if issues are found. Motivation: - Centralize liveness checks and make cleanup explicit and debuggable to avoid silent resource leaks and make lifecycle bugs easier to diagnose.
Refactor and extend tests for LayerLifecycleManager and RuntimeRegistry to match updated runtime API and lifecycle behavior. Tests now import gc and exercise resolve_live_layer/get_live_runtime/get_store/require_store paths, use ManagedPointsRuntime with layer_id, and assert registry iteration helpers (iter_live_items/iter_live_layers/iter_live_runtimes) and layer_ids. Added new tests to verify reaping/clearing of dead entries, audit/reporting of stale entries, and unregister-by-layer-id behavior. Adjusted expectations and renamed several test functions to reflect the new APIs.
Import deprecation helper and mark legacy layer-handling methods as deprecated. Added from napari_deeplabcut.utils.deprecations import deprecated and applied @deprecated to _adopt_existing_layers, _adopt_layer, and on_insert with messages pointing to LayerLifecycleManager / self.layer_manager replacements, clarifying that layer adoption and direct layer management are now handled elsewhere.
Add @deprecated annotations to KeypointControls methods that belong in LayerLifecycleManager: _setup_image_layer, _wire_points_layer, and _setup_points_layer. The decorators include messages indicating these methods are still used by LayerLifecycleManager but should be moved there. No functional logic changes, only deprecation metadata to guide refactoring.
Refactor lifecycle responsibilities by moving image/points setup, wiring, removal and remap logic out of the UI widget and into LayerLifecycleManager. Key changes: - _widgets.py: switched to relative imports, removed many lifecycle implementations and replaced them with deprecated UI-facing wrappers that delegate to layer_manager; preserved small UI completion hooks used by the widget. - core/layer_lifecycle/manager.py: added lifecycle-owned methods (_setup_image_layer, _wire_points_layer, _setup_points_layer, _handle_removed_layer, _remap_frame_indices) and attach_points_layer_runtime to centralize runtime bindings (paste/add wrappers, events, keybindings), plus adoption/insert/remove handling. - core/keypoints.py: KeypointStore now supports weak refs and a resolver-based lifecycle (layer id/resolution), raises LayerUnavailableError when layer is gone, exposes add() (with a temporary _add compat wrapper), and renamed nearest-neighbor helper to find_nearest_neighbors; several safety/fallbacks added. - core/layer_lifecycle/registry.py: added PointsRuntimeResources dataclass to track non-Qt runtime attachments for managed Points layers. - Misc: logging/message tweaks, deprecated annotations for moved methods, and transitional notes to keep UI-specific behavior separated from lifecycle logic. This reorganizes ownership of runtime behavior to make lifecycle management testable and encapsulated while retaining UI-only completion in the widget.
Replace uses of internal helpers with public API (keypoints._add -> keypoints.add; keypoints._find_nearest_neighbors -> keypoints.find_nearest_neighbors) and add missing pytest import. Add tests covering layer resolver behavior (maybe_layer, LayerUnavailableError) and the store.layer setter updating layer_id and keypoints. Also add an assertion to verify store.layer_id matches id(store.layer) in test_store_labels.
Align tests with recent refactors to the layer lifecycle manager and keypoint APIs. Tests now use lightweight fakes and fixtures (FakeStore, immediate QTimer, fake runtime attachment) and a more featureful DummyOwner that exposes MagicMock hooks so assertions check behavior via those hooks instead of internal call lists. Adapted tests to renamed/updated APIs: manager parameter existing -> existing_resources, reap_dead_entries -> clear_dead_entries, and the temporary keypoints wrapper renamed to add; tests also call store.add directly where appropriate. Minor test reorganizations improve determinism and isolate lifecycle orchestration from napari internals.
Centralize lifecycle-owned image and project metadata in LayerLifecycleManager: added ImageMetadata storage, project_path, and convenience accessors (image_root, image_paths, image_name). Moved image metadata update, points→image metadata sync, and project-path caching from KeypointControls into the manager, and updated _setup_image_layer and related flows to use the manager-owned context. KeypointControls retains compatibility shims and deprecated wrappers that delegate to LayerLifecycleManager, and call sites were updated to reference layer_manager.* instead of local fields. Import and metadata helper usage was adjusted accordingly; behavior should be preserved while ownership is moved to the manager.
Add explicit DLC lifecycle metadata propagation and lifecycle handling for image/video layers. - Reader changes: build and attach a standardized dlc metadata dict for images and videos (via a new _build_dlc_layer_meta); infer project context for opened videos and labeled folders and pass dlc_meta into read_images/read_video. Non-DLC media remain supported but are marked as non-session. - IO refactor: read_images now accepts dlc_meta and uses a helper to build image layer kwargs; read_video accepts optional dlc_meta and includes it in returned metadata. - Project paths: add infer_dlc_project_from_labeled_folder, infer_dlc_project_from_video_path, and session_key_from_project_context to better infer session contexts for folders and directly opened videos. - Lifecycle manager: track the active DLC image layer id, determine/accept/reject DLC session image layers, expose active_dlc_image_layer, and add safe helpers for removing layers and setting visibility; ensure conflicting DLC layers are rejected and non-session images are ignored. - Widgets/UX: KeypointControls updated to use layer lifecycle manager to hide/show or remove placeholder layers safely, improved logic to pick visible existing layers, and a safer implementation to move image layers to bottom. Uses manager.active_dlc_image_layer instead of deprecated helper. - API note: find_relevant_image_layer is marked deprecated in favor of LayerLifecycleManager.active_dlc_image_layer. These changes let the plugin reliably identify DLC project/video sessions, attach session metadata to Napari layers, and prevent multiple conflicting DLC sessions from being opened simultaneously.
Detect and merge temporary "config placeholder" Points layers into existing managed points workflows, updating headers, presentation metadata, dropdowns, and UI state, then remove the placeholder layer. KeypointControls: added _is_config_placeholder_points_layer and rewrote _maybe_merge_config_points_layer to use a managed layer as the reference, merge header/bodypart changes, refresh menus defensively, apply colormap/face-color cycles, and remove the placeholder via QTimer. LayerLifecycleManager: made active_dlc_image_layer resolve by identity across viewer.layers (safer than resolve_live_layer) and short-circuit insertion when a placeholder layer is consumed by the widget merge. Tests updated with a helper (mark_as_dlc_session_image) and adjusted assertions to reflect the new merge/move behavior. Also adjusted a deprecation decorator parameter name in core/layers.py.
Add explicit session conflict handling and a UI notification hook. - Introduce a new Signal session_conflict_rejected(str) on LayerLifecycleManager to notify the UI when a DLC labeled-data folder conflicts with the current session. - Change the rejection flow to emit the signal and defer layer removal via QTimer.singleShot(0) instead of removing the layer synchronously (avoids Napari list-insertion/finalization issues). - Expand the rejection message to provide clearer guidance to users about loading annotations vs switching projects. - Wire the new signal into KeypointControls: attach LayerLifecycleManager, connect session_conflict_rejected to a new _on_session_conflict_detected handler, and show a QMessageBox warning when a conflict is detected. - Improve logging when deferred removal fails. This change brings better user feedback when loading several projects.
Wrap widget removal in a safe try/except. In KeypointStore, skip revalidating header metadata when the same live layer is rebound (check by id) to avoid repeated expensive reads and add a debug log. In LayerLifecycleManager add a post-remove coalescing QTimer and flush handler to batch UI refreshes after layer removals, make _update_image_meta_from_layer return a bool indicating whether the authoritative image context changed, and only sync points layers when the context actually changed. Also adjust layer setup/remap logic to only remap non-image layers when necessary and improve related logging. Overall these changes reduce unnecessary work, prevent transient exceptions, and coalesce UI updates during layer changes.
Introduce a lightweight log_timing contextmanager for scoped performance measurements and a NAPARI_DLC_LOG_TIMING flag to control sampling. Instrument several lifecycle and UI hotspots (Points/Image/Tracks removal, viewer.layers.remove, post-remove refresh, and active-layer changes) to emit timing logs when enabled. Enhance the InMemoryDebugRecorder snapshot formatting to include milli-second precision timestamps, relative elapsed ms per record, and guard the empty-record case. These changes aid low-overhead debugging and performance investigation.
Clean up KeypointControls by removing deprecated fields, methods, and comments (e.g. _on_destroyed, legacy _stores/_image_meta, and other commented-out legacy hooks). Remove the pydantic ValidationError import and change validation checks to detect an errors attribute (hasattr(res, "errors")) instead of isinstance(..., ValidationError) to avoid a hard dependency on pydantic and be more resilient to other validator return types. Adjust user-facing merge prompt to ask to hide existing keypoints when adding new ones, and tweak a timer comment for widget docking. Overall this is a refactor/cleanup to reduce legacy cruft and simplify validation handling.
Introduce a new save workflow for DeepLabCut keypoints in napari: src/napari_deeplabcut/ui/ui_dialogs/save.py and an __init__.py to expose the package. Implements PointsLayerSaveWorkflow to handle single- and multi-layer saves, promotion-to-GT checks, project association and config prompts, dataset path rewriting, overwrite preflight/confirmation, save-time metadata enrichment/provenance, scorer selection/persistence, and post-save UI state persistence for folder/trail controls. Adds helper functions and a temporary metadata context manager; includes error handling and user-facing dialogs for invalid metadata or missing project context.
Replace the large, in-class save implementation with a dedicated PointsLayerSaveWorkflow. The KeypointControls now constructs a PointsLayerSaveWorkflow in __init__ and _save_layers_dialog simply delegates saving to that workflow and updates the viewer status/last-saved label from the workflow outcome. Remove many now-unnecessary helper functions, temporary metadata/contextmanager, and a large number of imports related to project-association, promotion-to-GT, overwrite preflight, scorer prompting, and sidecar handling; those responsibilities are intended to be handled by the new save workflow. This centralizes and simplifies the saving logic and cleans up the widget implementation.
Update conftest to patch the overwrite confirmation function from the new save dialog module (napari_deeplabcut.ui.ui_dialogs.save) instead of the old dialogs module, and adjust the monkeypatch target accordingly. Also remove stale commented-out monkeypatch lines from test_writer.py that duplicated this behavior.
Add an optional full_path parameter to LayerStatusPanel.set_folder_name and use it to set the folder tooltip (falling back to a message when no project is open). Update KeypointControls to pass layer_manager.project_path into set_folder_name so the UI shows the full project path as a tooltip while preserving the existing displayed folder name behavior.
Add a guard in PointsLayerSaveWorkflow to abort saves when a points layer has no extracted-frame paths and the active image context is a video. Introduce helpers _is_video_context_layer, _is_unsupported_direct_video_label_save and _warn_unsupported_direct_video_label_save which show a rich-text QMessageBox explaining the unsupported workflow and recommended steps. Update imports (escape, Qt, is_video) used by the new warning. Make label-progress/frame-count more robust: infer_frame_count and compute_label_progress now accept fallback_n_frames so 4D video image layers can provide a frame count when no paths exist. KeypointControls now reads project_path and image_meta from layer_manager and exposes deprecated compatibility shims for the old properties. Tests: update many e2e tests to patch the actual module where PointsLayerSaveWorkflow is defined via a new save_workflow_mod fixture, and add a new test (test_direct_video_labeling_save_is_blocked_without_paths) to assert the unsupported direct-video save is blocked and warns the user. Misc: small refactors to monkeypatching and overwrite preflight capture in tests.
Tests: add @pytest.mark.usefixtures("qtbot") to test_point_resize in test_keypoints.py to ensure the qtbot fixture is applied for the point resize test.
UI: update debug message in PointsLayerSaveWorkflow.save flow to reference the "direct video + config.yaml" label-save case for clearer logging when aborting unsupported direct video label saves.
Replace reliance on a real napari viewer in the store test fixture by adding DummyDimsForStore and DummyViewerForStore to emulate the minimal dims API. Compute nsteps from points data (with fallback), instantiate KeypointStore with the dummy viewer, and wire a query_next_frame Event on points.events to connect to store._advance_step to mimic LOOP mode. Also import Event from napari.utils.events and remove the viewer parameter from the fixture.
Add two new UI test modules: test_save.py and test_singleton_widget.py. test_save.py exercises the PointsLayerSaveWorkflow save paths including dialog cancellation, selected vs. all-layer saves, image context resolution, and metadata enrichment using lightweight test doubles and monkeypatching. test_singleton_widget.py verifies ViewerSingletonWidget behavior (viewer extraction, canonicalization, instance registry, docking detection, and lifecycle cleanup). These tests increase coverage for UI workflows and singleton widget logic.
Introduce an experimental point-tracking subsystem: adds a TrackingControls UI, a background TrackingWorker, and core data/models for registering and running trackers. Implements concrete modules under tracking/core (data and abstract TrackingModel with registry), a Qt widget under tracking/_widgets.py, and a worker implementation under tracking/_worker.py. Includes tests (fixtures, widget and worker tests) and a README documenting usage and keybindings; tests register a DummyTracker for unit testing. Adds "torch" to pyproject.toml and updates tox.ini to support the new tracking tests. Co-Authored-By: Arash Sal Moslehian <57039957+arashsm79@users.noreply.github.com>
Co-Authored-By: Arash Sal Moslehian <57039957+arashsm79@users.noreply.github.com>
Introduce configurable tracking shortcuts and only enable them when the tracking widget is visible. Add TRACKING_SHORTCUTS_ENABLED (env NAPARI_DLC_TRACKING_SHORTCUTS_ENABLED, default enabled) to settings, centralize tracking key definitions in config/keybinds.py, and have iter_shortcuts yield tracking shortcuts only when enabled. Update TrackingControls to import those key configs, set an objectName/property for dock detection, and guard bound key callbacks so they only act when the tracking dock is open/visible. Enhance Shortcuts dialog to recognize the new "tracking-points-layer" scope and to hide/disable shortcuts when the tracking widget isn't open. Also update imports (KeypointStore path) and remove duplicate dataclass/keybind definitions.
Introduce an identity-preserving tracking data pipeline and create separate tracking result layers. data.py: add tracking metadata constants, convert TrackingWorkerData/Output to use DataFrame for per-query features, and add helpers (coerce_features_df, add_query_identity_columns, expand_query_features_over_time, build_tracking_result_metadata, is_tracking_result_layer) to preserve query identity and expand features over time. models.py: update Cotracker3 to avoid mutating inputs, correctly handle x/y ordering, visibility shapes, time-reversal for backward tracking, and produce flattened keypoints plus expanded per-point feature rows. _widgets.py: add UI helpers to seed query points/features, build a non-destructive tracking result Points layer (with metadata and visual tweaks), wire those into the tracking flow, improve error handling, and select the created layer in the viewer. Overall these changes ensure semantic identity of query points is preserved through inference and that results are stored in a dedicated, annotated layer.
Add helpers to place all test keypoints on a specific frame and to drive the widget reference frame (_put_all_points_on_frame, _set_current_tracking_frame). Update tests (test_backward_track, test_bothway_track) to use these helpers instead of directly mutating viewer.dims, and add assertions verifying the tracking request payload: correct reference_frame_index, sliced video length, keypoints rebased to local frame 0, original keypoint feature columns (id/name) preserved, and new tracking identity columns (tracking_query_index, tracking_query_frame) populated. Also ensure both-way tracking uses the same seed frame and that forward==reference only triggers backward tracking.
Switches several signal/slot connections to explicit Qt.QueuedConnection to ensure safe cross-thread delivery and replaces tuple/object-typed signals with primitive signatures. In TrackingControls: trackingRequested now uses Signal(object); worker connections use queued delivery; added _on_worker_started/_on_worker_finished/_on_worker_progress slots, a _request_worker_stop wrapper, and a _debug_thread helper for logging. In TrackingWorker: progress is now Signal(int,int), trackingFinished is Signal(object), track is annotated with Slot(object), and progress.emit now emits two ints; added thread debug logging. These changes improve thread-safety, clarity of signal payloads, and progress reporting.
Update tracking worker and UI to improve stop handling, logging, and error reporting. - TrackingWorker: replace boolean stop flag with threading.Event, add request_stop(), use self.thread for logging, emit trackingStarted/trackingStopped/trackingFinished and finished in appropriate places, avoid QCoreApplication.processEvents, and guard torch.cuda.empty_cache. Ensure early return when stop requested. - Tests: adapt progress signal handling to accept (current, total) args. - Widgets: use self.thread attribute in debug logs, derive reference frame index from returned features when available, catch ValueError from seed point queries and show a napari warning instead of crashing, plus small formatting fixes. These changes make worker shutdown safer across threads, improve diagnostics, and prevent main-thread operations from being performed in the worker.
Switch the CoTracker backend to the offline model and refactor run() to perform whole-clip inference. Inputs.video is converted and permuted to (1, T, C, H, W), queries are batched to (1, K, 3), inference is executed under torch.inference_mode, progress callbacks updated, and a RuntimeError is raised if no predictions are returned. Also add early-stop handling (return None). Additionally, fix visibility array handling in expand_query_features_over_time by squeezing a leading singleton channel dimension when vis.ndim == 3 and vis.shape[0] == 1.
Tweak tracking UI appearance and fix a threading/logging bug. - tracking/_widgets.py: add TODO about slider sync; change tracking layer visuals to use symbol="cross", opacity=0.85, and border_color="green" to better distinguish results. - tracking/ui/worker.py: fix logging call by using self.thread instead of self.thread() to avoid a mistaken call in the thread information.
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Use a lifecycle manager in TrackingControls and tighten viewer typing; update test helper to locate the TrackingControls dock by isinstance and add TYPE_CHECKING napari types. Fix a TYPE_CHECKING import in tracking models (correct TrackingModel import). Replace top-level torch import in the tracking worker with a lazy import and a clear ImportError message advising how to install the tracking extras, and improve CUDA cache cleanup logging. These changes reduce heavy top-level imports, improve typing correctness, and make missing-dependency errors clearer.
ca207c5 to
35e4ab4
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Rebase of #155, updated to integrate with the latest refactor.
Further update from #128
Current ongoing work:
Done
Missing