Skip to content

Copying and Moving Containers

The Flywheel SDK provides dedicated methods for copying containers at every level of the hierarchy, plus a bulk operation for moving sessions. This page explains the difference between copy and move, covers each copy method and its input model, describes how to filter what gets included in a copy, and shows a workaround for copying a single file.

See Core Concepts: Containers and Core Concepts: Hierarchy for background on the container model.

Copy vs. move

Copy creates a linked reference of the source container in the destination. The original remains intact and continues to exist in its source location. A copy does not duplicate the underlying file data — it only creates a new reference, so the copy does not consume additional storage space.

Note

After a copy is created, the source and the copy are independent. Modifying a file on the copy will increment that file's version on the copy only — it will not affect the original. Metadata (info, tags, notes) is copied at the time of the operation but is not synced afterward. Changes to metadata on the original will not appear on the copy, and vice versa.

Move relocates the source container to a new parent. The original is removed from its source location. Use move when reorganizing data — for example, reassigning sessions to different subjects after a labeling correction.

The SDK exposes these as separate operations:

  • Copy: fw.session_copy(), fw.subject_copy(), fw.acquisition_copy(), fw.project_copy()
  • Move: fw.bulk_move_sessions() (sessions only; bulk operation)

Copy methods

Every copy method takes two arguments: the ID of the container to copy, and a *CopyInput model that specifies the destination and optional new label.

All copy methods except fw.project_copy() are synchronous and return the new container directly. fw.project_copy() is asynchronous and returns a ProjectCopyOutput with a task_id you use to track progress.

No container can be copied unless the parent project is copyable. Copying can be enabled via the UI under Projects -> Settings -> Copying or the SDK:

Enable copying
fw.modify_project(project.id, {"copyable": True})

Copy a session

Copy a session to a destination project
--8 < --"test_docs_core_concepts.py:copy_session"

SessionCopyInput fields:

Field Type Description
dst_project_id str Destination project. The copy lands under a new or matched subject in this project.
dst_subject_id str Destination subject. Use this instead of dst_project_id to place the session under a specific subject.
dst_session_label str Label for the copied session. If omitted, the original label is used.
filter CopyFilter Controls what is excluded from the copy. See CopyFilter below.

Copy a subject

Copy a subject to a destination project
--8 < --"test_docs_core_concepts.py:copy_subject"

SubjectCopyInput fields:

Field Type Description
dst_project_id str Destination project.
dst_subject_label str Label for the copied subject.
filter CopyFilter Controls what is excluded from the copy.

Copy an acquisition

Acquisitions copy into a destination session rather than a project.

Copy an acquisition to a destination session
--8 < --"test_docs_core_concepts.py:copy_acquisition"

AcquisitionCopyInput fields:

Field Type Description
dst_session_id str Destination session.
label str Label for the copied acquisition.
filter CopyFilter Controls what is excluded from the copy.

Copy a project (asynchronous)

Project copy is asynchronous. The call returns immediately with a ProjectCopyOutput that contains a task_id. You must poll separately to determine when the copy has finished.

Copy a project asynchronously
--8 < --"test_docs_core_concepts.py:copy_project"

ProjectCopyInput fields:

Field Type Description
group_id str Destination group.
project_label str Label for the copied project.
snapshot_id str Optional. Copy from a specific snapshot rather than the live project.
filter CopyFilter Controls what is excluded from the copy.

ProjectCopyOutput fields:

Field Type Description
task_id str ID of the background task running the copy. Poll this to track progress.
project_id str ID of the newly created project.
snapshot_id str ID of the snapshot used for the copy, if applicable.

CopyFilter

Every *CopyInput model accepts an optional filter field of type CopyFilter. When omitted, the copy includes everything. Use CopyFilter to exclude specific content categories or to restrict which files are included using file name patterns.

Copy a session with a CopyFilter
--8 < --"test_docs_core_concepts.py:copy_session_with_filter"

CopyFilter fields:

Field Type Default Description
exclude_analysis bool False When True, analyses are not copied.
exclude_notes bool False When True, notes are not copied.
exclude_tags bool False When True, tags are not copied.
exclude_empty_containers bool True When True, containers with no files are omitted from the copy.
include_rules list[str] None If set, only files whose names match one of these patterns are included.
exclude_rules list[str] None If set, files whose names match any of these patterns are excluded.

include_rules and exclude_rules accept file name glob patterns. When both are set, include_rules takes precedence — the SDK first applies include_rules to build the candidate set, then applies exclude_rules within that set.

Bulk move sessions

fw.bulk_move_sessions() moves multiple sessions into a single destination container in one call. Pass a BulkMoveInput that identifies the source sessions and the one destination, and choose how label conflicts are handled with conflict_mode ("dry", "skip", or "move"). The call returns a list of conflicts — an empty list means a clean move.

Bulk move sessions to a target subject
--8 < --"test_docs_core_concepts.py:bulk_move_sessions"

destinations must contain exactly one container ID — all sources move into that one target. destination_container_type describes the destination's type ("subjects" for the normal case), and remove_source should be left at its default False.

For the full walkthrough — conflict modes, previewing a move with a dry run, reading the MoveConflict report, and merging subjects — see Advanced Usage: Bulk Move Sessions.

Copying a single file

The SDK does not provide a direct file copy method. To copy one file from one acquisition to another:

  1. Copy the source acquisition with an include_rules filter that matches only the target file.
  2. The copy lands as a new temporary acquisition containing just that one file.
  3. Move the file from the temporary acquisition to the target acquisition using fw.move_file().
  4. Delete the temporary acquisition.
Copy a single file between acquisitions
--8 < --"test_docs_core_concepts.py:copy_single_file"

This approach avoids a full round-trip download and re-upload for the file. For large collections of files, consider whether a full acquisition copy is more practical.