Skip to content

cli

The vr-foraging-packaging command. One subcommand per pipeline function: session, batch, aggregate.


cli

The vr-foraging-packaging command: one subcommand per pipeline function.

session   --input-dir <one raw session>    --output-dir <dest>
batch     --input-dir <folder of sessions> --output-dir <dest>
aggregate --input-dir <a sessions/ tree>   --output-dir <dest>

Every flag maps onto a parameter of the function the subcommand names; the only logic here is rejecting combinations that cannot work.

SessionCommand

Bases: _ProcessingCommand

Export ONE raw session directory.

--input-dir is the session root itself, not a folder containing sessions. Outputs land directly in --output-dir (no sessions/ level), because there is only one session to keep apart.

Source code in src/aind_behavior_vr_foraging_packaging/pipeline/cli.py
class SessionCommand(_ProcessingCommand):
    """Export ONE raw session directory.

    ``--input-dir`` is the session root itself, not a folder containing sessions.
    Outputs land directly in ``--output-dir`` (no ``sessions/`` level), because
    there is only one session to keep apart.
    """

    def run(self) -> None:
        process_session(
            self.input_dir,
            self.output_dir,
            include=self.include_processors,
            exclude=self.exclude_processors,
            strict_parsing=self.strict_parsing,
            write_parquet=self.write_parquet,
            write_nwb=self.write_nwb,
        )

BatchCommand

Bases: _ProcessingCommand

Export a FOLDER of raw session directories, then aggregate.

--input-dir is scanned one level deep: every immediate subdirectory is taken to be one raw session. Per-session outputs go to --output-dir/sessions/{session_id}/, experiment-level files to --output-dir itself.

Source code in src/aind_behavior_vr_foraging_packaging/pipeline/cli.py
class BatchCommand(_ProcessingCommand):
    """Export a FOLDER of raw session directories, then aggregate.

    ``--input-dir`` is scanned one level deep: every immediate subdirectory is
    taken to be one raw session. Per-session outputs go to
    ``--output-dir/sessions/{session_id}/``, experiment-level files to
    ``--output-dir`` itself.
    """

    workers: int = 1
    """Number of parallel threads for the per-session phase. 1 = sequential."""
    clean: bool = True
    """Delete --output-dir before writing, so a re-run never mixes two invocations."""
    skip_aggregation: bool = False
    """Write only per-session outputs. Aggregate later with the `aggregate` subcommand."""

    def run(self) -> None:
        if not self.write_parquet and not self.skip_aggregation:
            raise ValueError(
                "--no-write-parquet leaves aggregation nothing to read. "
                "Pass --skip-aggregation as well, or keep parquet output on."
            )

        session_paths = sorted(p for p in self.input_dir.iterdir() if p.is_dir())
        if not session_paths:
            logger.warning("No subdirectories found under %s — nothing to do.", self.input_dir)
            return
        logger.info("  sessions found: %d", len(session_paths))

        process_sessions(
            session_paths,
            self.output_dir,
            include_processors=self.include_processors,
            exclude_processors=self.exclude_processors,
            strict_parsing=self.strict_parsing,
            max_workers=self.workers,
            clean=self.clean,
            write_parquet=self.write_parquet,
            write_nwb=self.write_nwb,
        )

        if not self.skip_aggregation:
            aggregate(self.output_dir / "sessions", self.output_dir)

workers = 1 class-attribute instance-attribute

Number of parallel threads for the per-session phase. 1 = sequential.

clean = True class-attribute instance-attribute

Delete --output-dir before writing, so a re-run never mixes two invocations.

skip_aggregation = False class-attribute instance-attribute

Write only per-session outputs. Aggregate later with the aggregate subcommand.

AggregateCommand

Bases: _Command

Concatenate already-exported sessions into experiment-level tables.

--input-dir is a sessions/ tree — one subdirectory per session, each holding the parquets a previous session or batch run wrote. Nothing is re-processed and nothing is deleted, so this is safe to re-run.

Source code in src/aind_behavior_vr_foraging_packaging/pipeline/cli.py
class AggregateCommand(_Command):
    """Concatenate already-exported sessions into experiment-level tables.

    ``--input-dir`` is a ``sessions/`` tree — one subdirectory per session, each
    holding the parquets a previous ``session`` or ``batch`` run wrote. Nothing
    is re-processed and nothing is deleted, so this is safe to re-run.
    """

    def run(self) -> None:
        aggregate(self.input_dir, self.output_dir)

Cli

Bases: BaseSettings

Root parser: dispatches to whichever subcommand was named.

Source code in src/aind_behavior_vr_foraging_packaging/pipeline/cli.py
class Cli(BaseSettings):
    """Root parser: dispatches to whichever subcommand was named."""

    model_config = SettingsConfigDict(
        cli_parse_args=True,
        cli_kebab_case=True,
        cli_implicit_flags=True,
        cli_prog_name="vr-foraging-packaging",
    )

    session: CliSubCommand[SessionCommand] = Field(description="Export one raw session directory.")
    batch: CliSubCommand[BatchCommand] = Field(
        description="Export a folder of raw session directories, then aggregate."
    )
    aggregate: CliSubCommand[AggregateCommand] = Field(
        description="Aggregate an already-exported sessions/ tree; re-processes nothing."
    )

    def cli_cmd(self) -> None:
        CliApp.run_subcommand(self)