Skip to content

Commit 5a23fc2

Browse files
committed
add checkpoint/restore guide
1 parent 8f6162a commit 5a23fc2

4 files changed

Lines changed: 123 additions & 7 deletions

File tree

docs/source/howto/backups.rst

Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
Backing up and sharing projects
2+
===============================
3+
4+
Two CLI commands help you move a project between machines or archive it for long-term storage:
5+
6+
* ``cheese3d checkpoint``: bundles a project into a single archive
7+
* ``cheese3d restore``: expands an archive back into a working project
8+
9+
This guide explains:
10+
11+
.. contents::
12+
:local:
13+
:depth: 1
14+
:backlinks: none
15+
16+
What is a checkpoint?
17+
---------------------
18+
19+
A **checkpoint** is a single ``.tar.xz`` archive that captures the state of a Cheese3D project at a point in time. Archives are written to the project's ``checkpoints/`` folder using the naming scheme:
20+
21+
.. code-block:: text
22+
23+
<project>/checkpoints/<name>_<YYYY-MM-DD-HH-MM-SS>.tar.xz
24+
25+
The timestamp is generated when the command is run, so successive checkpoints never overwrite each other.
26+
27+
Checkpoints are useful for:
28+
29+
* **Snapshotting before a destructive change.** Take a checkpoint before retraining the pose model, re-running synchronization, or editing labels. If the new run is worse, ``restore`` brings you back to the previous state.
30+
* **Sharing a project.** Hand a single ``.tar.xz`` to a collaborator or upload it to long-term storage instead of dealing with many loose files and possibly external symlinks.
31+
* **Moving a project between machines.** Use ``--portable`` (see :ref:`howto/backups:Portable archives` below) to ensure the archive is self-contained regardless of where its data originally lived.
32+
33+
What is included in a checkpoint
34+
--------------------------------
35+
36+
By default, ``cheese3d checkpoint`` includes everything inside the project folder *except* the ``checkpoints/`` subfolder itself. Concretely, that means:
37+
38+
* ``config.yaml``: always included (and possibly rewritten; see :ref:`howto/backups:Portable archives` below)
39+
* ``triangulation/``: always included
40+
* ``model/`` (the default ``model_root``): included *if* the model lives inside the project folder; externalized model directories are only included when ``--portable`` is set
41+
* ``videos/`` (the default ``video_root``): included *if* the videos live inside the project folder and ``--skip-source`` is *not* set; externalized video roots require ``--portable``
42+
* ``ephys/`` (the default ``ephys_root``): same rules as ``videos/``---included by default when ``ephys_root`` is inside the project folder, requires ``--portable`` otherwise
43+
44+
See :doc:`/guides/organizing-projects` for the project layout these ``*_root`` folders refer to.
45+
46+
.. tip::
47+
48+
Because source recordings (videos and ephys) are typically large, you can opt out of them at archive time with ``--skip-source``; the resulting archive contains the configuration, the trained model, the triangulation outputs, and any other project files, but not the raw inputs.
49+
50+
Creating a checkpoint
51+
---------------------
52+
53+
The minimal invocation, from inside a project folder:
54+
55+
.. code-block:: bash
56+
57+
cheese3d checkpoint
58+
59+
To explicitly skip source recordings (useful when you only want to share the *results* of an analysis):
60+
61+
.. code-block:: bash
62+
63+
cheese3d checkpoint --skip-source
64+
65+
See :ref:`reference/cli:checkpoint` for the full set of options.
66+
67+
Portable archives
68+
^^^^^^^^^^^^^^^^^
69+
70+
The defaults above only bundle source recordings and models that live **inside the project folder**. If your ``video_root``, ``ephys_root``, or ``model_root`` points to a shared location (e.g., a lab-wide ``dlc-projects/`` folder or an external drive), those files won't appear in a default archive---the resulting checkpoint won't be self-contained for transfer to another machine.
71+
72+
The ``--portable`` flag fixes this:
73+
74+
.. code-block:: bash
75+
76+
cheese3d checkpoint --portable
77+
78+
With ``--portable``:
79+
80+
* External directories pointed to by ``video_root``, ``ephys_root``, and ``model_root`` are copied into the archive under standard subfolders (``videos/``, ``ephys/``, and ``models/``).
81+
* Symbolic links inside source folders are resolved and the linked files are copied in directly.
82+
* The embedded ``config.yaml`` is rewritten so ``video_root``, ``ephys_root``, and ``model_root`` are set to those standard subfolders. So on restore, the project simply works without further reconfiguration.
83+
84+
``--portable`` and ``--skip-source`` are independent. Combining them produces a self-contained archive of *just* the model and analysis outputs without raw recordings:
85+
86+
.. code-block:: bash
87+
88+
cheese3d checkpoint --portable --skip-source
89+
90+
.. tip::
91+
92+
If you're handing a project off to someone who doesn't share your filesystem layout, always use ``--portable``. The archive is then guaranteed to restore into a working project on any machine.
93+
94+
Restoring a checkpoint
95+
----------------------
96+
97+
``cheese3d restore`` expands an archive back into a project on disk:
98+
99+
.. code-block:: bash
100+
101+
cheese3d restore path/to/<name>_<timestamp>.tar.xz
102+
103+
By default, the project is restored under the ``--path`` directory using the project name baked into the archive. To restore under a different name, pass it as the second argument:
104+
105+
.. code-block:: bash
106+
107+
cheese3d restore my_project_2026-05-13-09-30-00.tar.xz my_project_copy
108+
109+
You can also skip source recordings at restore time. This is useful when you have a large portable archive but only need the configuration, model, and analysis results on the target machine:
110+
111+
.. code-block:: bash
112+
113+
cheese3d restore my_project.tar.xz --skip-source
114+
115+
See :ref:`reference/cli:restore` for the full set of options.
116+
117+
.. note::
118+
119+
``restore`` will not delete files that already exist in the target directory; it only extracts files from the archive on top of what's already there. To guarantee a clean restore, point ``--path`` at an empty folder, or remove the target project directory before running ``restore``.

docs/source/index.rst

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,9 @@ If you use Cheese3D, please cite our paper:
5353
:maxdepth: 2
5454
:caption: How-to examples
5555

56-
howto/regex
5756
howto/sync
57+
howto/regex
58+
howto/backups
5859

5960
.. toctree::
6061
:maxdepth: 2

packages/cheese3d/cheese3d/cli.py

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -305,10 +305,6 @@ def restore(
305305
"--skip-source",
306306
help="Skip recording directory when extracting archive."
307307
)] = False,
308-
portable: Annotated[bool, typer.Option(
309-
"--portable",
310-
help="The archive was created with portable mode. No-op flag for API compatibility."
311-
)] = False,
312308
config_overrides: Annotated[Optional[List[str]], typer.Argument(
313309
help="Config overrides passed to Hydra (https://hydra.cc/docs/intro/)"
314310
)] = None
@@ -317,5 +313,5 @@ def restore(
317313
path = ctx.obj["path"]
318314
configs = ctx.obj["configs"]
319315
project = _build_project(path, name, configs, config_overrides)
320-
project.restore(checkpoint_file, skip_source, portable)
316+
project.restore(checkpoint_file, skip_source)
321317
rich.print("Restore complete :white_check_mark:")

packages/cheese3d/cheese3d/project.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -758,7 +758,7 @@ def _replace_root(x: tarfile.TarInfo, rel_root: Path):
758758
tarinfo.size = len(yaml_bytes)
759759
tar.addfile(tarinfo, fileobj=io.BytesIO(yaml_bytes))
760760

761-
def restore(self, checkpoint_path, skip_source=False, portable=False):
761+
def restore(self, checkpoint_path, skip_source = False):
762762
rprint("Restoring project from checkpoint (this may take several minutes)...")
763763
checkpoint_file = Path(checkpoint_path)
764764
if not checkpoint_file.exists():

0 commit comments

Comments
 (0)