"""Command-line interface for Coord2Region.
The CLI provides dedicated sub-commands tailored to the different
capabilities exposed by the pipeline. Coordinate-focused commands can map
MNI coordinates to atlas labels, retrieve related studies, generate
summaries, render images and combine these insights. Region-based commands
resolve atlas region names to coordinates before performing the same
operations.
"""
import argparse
import json
import numbers
import os
import shlex
import sys
from collections.abc import Iterable, Sequence
from dataclasses import asdict
from importlib import metadata as importlib_metadata
import pandas as pd
import yaml
from .config import Coord2RegionConfig, ValidationError
from .fetching import AtlasFetcher
from .pipeline import run_pipeline
def _package_version() -> str:
"""Return the installed Coord2Region version string."""
try:
return importlib_metadata.version("coord2region")
except importlib_metadata.PackageNotFoundError: # pragma: no cover - dev installs
return "0+unknown"
def _print_available_atlases() -> None:
"""Print the known atlas identifiers."""
fetcher = AtlasFetcher()
for name in fetcher.list_available_atlases():
print(name)
def _parse_coord(text: str) -> list[float]:
"""Parse a coordinate string of the form 'x,y,z' or 'x y z'."""
parts = text.replace(",", " ").split()
if len(parts) != 3:
raise argparse.ArgumentTypeError("Coordinates must have three values")
try:
return [float(p) for p in parts]
except ValueError as exc: # pragma: no cover - user input
raise argparse.ArgumentTypeError(str(exc)) from exc
def _parse_coords_tokens(tokens: list[str]) -> list[list[float]]:
"""Parse a list of CLI tokens into a list of coordinate triples.
Supports both styles:
- Separate numbers: ``30 -22 50 10 0 0``
- Grouped strings: ``"30,-22,50" "10 0 0"``
"""
if not tokens:
return []
# Try numeric grouping first: len(tokens) % 3 == 0 and all castable to float
if len(tokens) % 3 == 0:
try:
vals = [float(t) for t in tokens]
return [vals[i : i + 3] for i in range(0, len(vals), 3)]
except ValueError:
pass # Fall back to per-token parsing
# Fall back to parsing each token as "x,y,z" or "x y z"
return [_parse_coord(tok) for tok in tokens]
def _load_coords_file(path: str) -> list[list[float]]:
"""Load coordinates from a CSV or Excel file.
The file is expected to contain at least three columns representing ``x``,
``y`` and ``z`` values. Any additional columns are ignored.
"""
if path.lower().endswith((".xls", ".xlsx")):
df = pd.read_excel(path)
else:
df = pd.read_csv(path)
if df.shape[1] < 3:
raise argparse.ArgumentTypeError(
"Input file must have at least three columns for x, y, z"
)
return df.iloc[:, :3].astype(float).values.tolist()
def _batch(seq: Sequence, size: int) -> Iterable[Sequence]:
"""Yield ``seq`` in chunks of ``size`` (or the full sequence if ``size`` <= 0)."""
if size <= 0 or size >= len(seq):
yield seq
else:
for i in range(0, len(seq), size):
yield seq[i : i + size]
def _atlas_source_from_value(value: str) -> dict[str, str] | None:
text = str(value).strip()
if not text:
return None
lower = text.lower()
if lower.startswith(("http://", "https://")):
return {"atlas_url": text}
if text.startswith(("~", "./", "../")):
return {"atlas_file": text}
expanded = os.path.expanduser(text)
if os.path.isabs(expanded):
return {"atlas_file": text}
if os.sep in text or (os.altsep and os.altsep in text):
return {"atlas_file": text}
if len(text) > 2 and text[1] == ":" and text[0].isalpha():
return {"atlas_file": text}
return None
def _collect_kwargs(args: argparse.Namespace) -> dict:
"""Collect keyword arguments for :func:`run_pipeline` from parsed args."""
kwargs = {}
if getattr(args, "gemini_api_key", None):
kwargs["gemini_api_key"] = args.gemini_api_key
if getattr(args, "openrouter_api_key", None):
kwargs["openrouter_api_key"] = args.openrouter_api_key
if getattr(args, "openai_api_key", None):
kwargs["openai_api_key"] = args.openai_api_key
if getattr(args, "anthropic_api_key", None):
kwargs["anthropic_api_key"] = args.anthropic_api_key
if getattr(args, "huggingface_api_key", None):
kwargs["huggingface_api_key"] = args.huggingface_api_key
if getattr(args, "image_model", None):
kwargs["image_model"] = args.image_model
if getattr(args, "image_prompt_type", None):
kwargs["image_prompt_type"] = args.image_prompt_type
if getattr(args, "image_custom_prompt", None):
kwargs["image_custom_prompt"] = args.image_custom_prompt
if getattr(args, "working_directory", None):
kwargs["working_directory"] = args.working_directory
if getattr(args, "email_for_abstracts", None):
kwargs["email_for_abstracts"] = args.email_for_abstracts
# Dataset/study sources (canonical name: sources)
sources_tokens: list[str] = []
values = getattr(args, "sources", None) or []
for item in values:
# Allow comma-separated items per token
parts = [p.strip() for p in str(item).split(",")]
sources_tokens.extend([p for p in parts if p])
if sources_tokens:
# de-duplicate while preserving order
seen = set()
ordered = []
for s in sources_tokens:
low = s # Keep original case; normalization happens later
if low not in seen:
seen.add(low)
ordered.append(s)
kwargs["sources"] = ordered
# Atlas selection
atlas_names = getattr(args, "atlas_names", None)
if atlas_names:
names: list[str] = []
atlas_configs: dict[str, dict[str, str]] = {}
for item in atlas_names:
parts = [p.strip() for p in str(item).split(",")]
for part in parts:
if not part:
continue
names.append(part)
if part not in kwargs.get("atlas_configs", {}):
source = _atlas_source_from_value(part)
if source:
atlas_configs.setdefault(part, {}).update(source)
if names:
kwargs["atlas_names"] = list(dict.fromkeys(names))
if atlas_configs:
kwargs["atlas_configs"] = atlas_configs
atlas_urls = getattr(args, "atlas_urls", None)
if atlas_urls:
configs = kwargs.setdefault("atlas_configs", {})
names = kwargs.setdefault("atlas_names", [])
for entry in atlas_urls:
if "=" not in entry:
raise argparse.ArgumentTypeError("--atlas-url expects NAME=URL entries")
name, url = entry.split("=", 1)
name = name.strip()
url = url.strip()
if not name or not url:
raise argparse.ArgumentTypeError("--atlas-url expects NAME=URL entries")
configs.setdefault(name, {})["atlas_url"] = url
if name not in names:
names.append(name)
atlas_files = getattr(args, "atlas_files", None)
if atlas_files:
configs = kwargs.setdefault("atlas_configs", {})
names = kwargs.setdefault("atlas_names", [])
for entry in atlas_files:
if "=" not in entry:
raise argparse.ArgumentTypeError(
"--atlas-file expects NAME=PATH entries"
)
name, path = entry.split("=", 1)
name = name.strip()
path = path.strip()
if not name or not path:
raise argparse.ArgumentTypeError(
"--atlas-file expects NAME=PATH entries"
)
configs.setdefault(name, {})["atlas_file"] = path
if name not in names:
names.append(name)
if "atlas_names" in kwargs:
kwargs["atlas_names"] = list(dict.fromkeys(kwargs["atlas_names"]))
return kwargs
def _print_results(results):
"""Pretty-print pipeline results as JSON."""
print(json.dumps([asdict(r) for r in results], indent=2))
def _add_coordinate_arguments(p: argparse.ArgumentParser) -> None:
p.add_argument("coords", nargs="*", help="Coordinates as x y z or x,y,z")
p.add_argument("--coords-file", help="CSV/XLSX file with coordinates")
def _add_region_arguments(p: argparse.ArgumentParser) -> None:
p.add_argument("regions", nargs="+", help="Region names")
def _add_execution_options(p: argparse.ArgumentParser) -> None:
p.add_argument(
"--output-format",
choices=["json", "pickle", "csv", "pdf", "directory"],
help="Export results to the chosen format",
)
p.add_argument(
"--output-name",
dest="output_name",
help=(
"File or directory name without path separators for exported "
"results stored under the working directory"
),
)
p.add_argument("--batch-size", type=int, default=0, help="Batch size")
p.add_argument(
"--working-directory",
dest="working_directory",
help="Base working directory for caches and outputs",
)
def _add_atlas_options(
p: argparse.ArgumentParser,
*,
allow_multiple: bool = True,
required: bool = False,
) -> None:
if allow_multiple:
atlas_help = (
"Atlas name(s) to use (repeat --atlas or use comma-separated list). "
"Defaults: harvard-oxford,juelich,aal"
)
else:
atlas_help = "Atlas name to use for region lookups"
p.add_argument(
"--atlas",
dest="atlas_names",
action="append",
required=required,
help=atlas_help,
)
p.add_argument(
"--atlas-url",
dest="atlas_urls",
action="append",
help="Associate an atlas alias with a download URL (NAME=URL)",
)
p.add_argument(
"--atlas-file",
dest="atlas_files",
action="append",
help="Associate an atlas alias with a local file path (NAME=PATH)",
)
def _add_study_options(p: argparse.ArgumentParser) -> None:
p.add_argument(
"--sources",
action="append",
help=(
"Datasets to use (repeat --sources or provide comma-separated list). "
"Examples: neurosynth,neuroquery,nidm_pain"
),
)
p.add_argument(
"--email-for-abstracts",
help="Contact email used when querying study abstracts",
)
def _add_llm_options(p: argparse.ArgumentParser) -> None:
p.add_argument("--gemini-api-key", help="API key for Google Gemini provider")
p.add_argument("--openrouter-api-key", help="API key for OpenRouter provider")
p.add_argument("--openai-api-key", help="API key for OpenAI provider")
p.add_argument("--anthropic-api-key", help="API key for Anthropic provider")
p.add_argument("--huggingface-api-key", help="API key for Hugging Face provider")
def _add_image_options(
p: argparse.ArgumentParser,
*,
default_backend: str = "ai",
include_huggingface: bool = True,
include_api_options: bool = True,
) -> None:
if include_api_options:
if include_huggingface:
p.add_argument(
"--huggingface-api-key", help="API key for Hugging Face provider"
)
p.add_argument("--openai-api-key", help="API key for OpenAI provider")
p.add_argument("--anthropic-api-key", help="API key for Anthropic provider")
p.add_argument("--image-model", default="stabilityai/stable-diffusion-2")
p.add_argument(
"--image-backend",
choices=["ai", "nilearn", "both"],
default=default_backend,
help="Image generation backend",
)
p.add_argument(
"--image-prompt-type",
choices=[
"anatomical",
"functional",
"schematic",
"artistic",
"custom",
"default",
],
help="Prompt template to use for AI image generation",
)
p.add_argument(
"--image-custom-prompt",
help="Custom image prompt template (use with --image-prompt-type custom)",
)
def _format_cli_tokens(tokens: Sequence[str]) -> str:
"""Join CLI tokens into a shell-friendly command string."""
return " ".join(shlex.quote(t) for t in tokens)
def _common_config_flags(
cfg: dict,
*,
include_api: bool,
include_sources: bool,
include_atlas: bool,
include_image_model: bool,
) -> list[str]:
"""Translate shared configuration values to CLI flags."""
flags: list[str] = []
working_dir = cfg.get("working_directory")
if working_dir:
flags.extend(["--working-directory", str(working_dir)])
if include_api:
mapping = {
"gemini_api_key": "--gemini-api-key",
"openrouter_api_key": "--openrouter-api-key",
"openai_api_key": "--openai-api-key",
"anthropic_api_key": "--anthropic-api-key",
"huggingface_api_key": "--huggingface-api-key",
}
for key, flag in mapping.items():
value = cfg.get(key)
if value:
flags.extend([flag, str(value)])
else:
# Image generation may still rely on Hugging Face
if include_image_model:
value = cfg.get("huggingface_api_key")
if value:
flags.extend(["--huggingface-api-key", str(value)])
if include_sources:
sources = cfg.get("sources") or []
if isinstance(sources, list) and sources:
flags.extend(["--sources", ",".join(str(s) for s in sources)])
email = cfg.get("email_for_abstracts")
if email:
flags.extend(["--email-for-abstracts", str(email)])
if include_atlas:
atlas_names = cfg.get("atlas_names") or []
for name in atlas_names:
flags.extend(["--atlas", str(name)])
atlas_configs = cfg.get("atlas_configs") or {}
for name, options in atlas_configs.items():
if not isinstance(options, dict):
continue
atlas_url = options.get("atlas_url")
if atlas_url and atlas_url != name:
flags.extend(["--atlas-url", f"{name}={atlas_url}"])
atlas_file = options.get("atlas_file")
if atlas_file and atlas_file != name:
flags.extend(["--atlas-file", f"{name}={atlas_file}"])
if include_image_model:
image_model = cfg.get("image_model")
if image_model:
flags.extend(["--image-model", str(image_model)])
return flags
def _inputs_to_tokens(input_type: str, inputs: Sequence) -> list[str]:
def _format_value(value) -> str:
if isinstance(value, numbers.Integral):
return str(int(value))
if isinstance(value, numbers.Real):
as_float = float(value)
if as_float.is_integer():
return str(int(as_float))
return str(as_float)
return str(value)
if input_type == "coords":
tokens: list[str] = []
for item in inputs:
if isinstance(item, list | tuple):
tokens.extend(_format_value(v) for v in item)
else:
tokens.append(_format_value(item))
return tokens
if input_type == "region_names":
return [str(item) for item in inputs]
raise ValueError(f"Dry-run not supported for input_type '{input_type}'")
def _commands_from_config(cfg: dict) -> list[str]:
input_type = str(cfg.get("input_type", "coords")).lower()
inputs = cfg.get("inputs", [])
outputs = cfg.get("outputs", []) or []
if not isinstance(outputs, list):
raise ValueError("Config 'outputs' must be a list when using dry-run")
config_section = cfg.get("config") or {}
commands: list[str] = []
base_tokens = ["coord2region"]
coord_command_map = {
frozenset(["region_labels"]): (
"coords-to-atlas",
dict(include_api=False, include_sources=False, include_image=False),
),
frozenset(["region_labels", "raw_studies"]): (
"coords-to-study",
dict(include_api=False, include_sources=True, include_image=False),
),
frozenset(["region_labels", "raw_studies", "summaries"]): (
"coords-to-summary",
dict(include_api=True, include_sources=True, include_image=False),
),
frozenset(["region_labels", "raw_studies", "images"]): (
"coords-to-image",
dict(include_api=True, include_sources=True, include_image=True),
),
frozenset(
[
"region_labels",
"raw_studies",
"summaries",
"images",
]
): (
"coords-to-insights",
dict(include_api=True, include_sources=True, include_image=True),
),
}
region_command_map = {
frozenset(["mni_coordinates"]): (
"region-to-coords",
dict(include_api=False, include_sources=False, include_image=False),
),
frozenset(["mni_coordinates", "raw_studies"]): (
"region-to-study",
dict(include_api=False, include_sources=True, include_image=False),
),
frozenset(
[
"mni_coordinates",
"raw_studies",
"summaries",
]
): (
"region-to-summary",
dict(include_api=True, include_sources=True, include_image=False),
),
frozenset(
[
"mni_coordinates",
"raw_studies",
"images",
]
): (
"region-to-image",
dict(include_api=False, include_sources=True, include_image=True),
),
frozenset(
[
"mni_coordinates",
"raw_studies",
"summaries",
"images",
]
): (
"region-to-insights",
dict(include_api=True, include_sources=True, include_image=True),
),
}
if input_type == "coords":
output_key = frozenset(str(o).lower() for o in outputs)
if not output_key:
raise ValueError("No supported outputs found for dry-run")
if output_key not in coord_command_map:
raise ValueError(
"Dry-run does not support coords commands for outputs "
f"{sorted(output_key)}"
)
command, capabilities = coord_command_map[output_key]
coord_tokens = _inputs_to_tokens("coords", inputs)
tokens = base_tokens + [command]
tokens.extend(coord_tokens)
shared_flags = _common_config_flags(
config_section,
include_api=capabilities["include_api"],
include_sources=capabilities["include_sources"],
include_atlas=True,
include_image_model=capabilities["include_image"],
)
tokens.extend(shared_flags)
if cfg.get("output_format"):
tokens.extend(["--output-format", str(cfg["output_format"])])
if cfg.get("output_name"):
tokens.extend(["--output-name", str(cfg["output_name"])])
image_backend = cfg.get("image_backend")
if capabilities["include_image"] and image_backend:
tokens.extend(["--image-backend", str(image_backend)])
if capabilities["include_image"]:
image_prompt_type = config_section.get("image_prompt_type")
if image_prompt_type:
tokens.extend(["--image-prompt-type", str(image_prompt_type)])
image_custom_prompt = config_section.get("image_custom_prompt")
if image_custom_prompt:
tokens.extend(["--image-custom-prompt", str(image_custom_prompt)])
commands.append(_format_cli_tokens(tokens))
return commands
if input_type == "region_names":
output_key = frozenset(str(o).lower() for o in outputs)
if not output_key:
raise ValueError("No supported outputs found for dry-run")
if output_key not in region_command_map:
raise ValueError(
"Dry-run does not support region commands for outputs "
f"{sorted(output_key)}"
)
command, capabilities = region_command_map[output_key]
atlas_names = config_section.get("atlas_names") or []
if isinstance(atlas_names, list) and len(atlas_names) > 1:
raise ValueError(
"Dry-run region commands require exactly one atlas name in the config"
)
region_tokens = _inputs_to_tokens("region_names", inputs)
tokens = base_tokens + [command]
tokens.extend(region_tokens)
shared_flags = _common_config_flags(
config_section,
include_api=capabilities["include_api"],
include_sources=capabilities["include_sources"],
include_atlas=True,
include_image_model=capabilities["include_image"],
)
tokens.extend(shared_flags)
if cfg.get("output_format"):
tokens.extend(["--output-format", str(cfg["output_format"])])
if cfg.get("output_name"):
tokens.extend(["--output-name", str(cfg["output_name"])])
image_backend = cfg.get("image_backend")
if capabilities["include_image"] and image_backend:
tokens.extend(["--image-backend", str(image_backend)])
if capabilities["include_image"]:
image_prompt_type = config_section.get("image_prompt_type")
if image_prompt_type:
tokens.extend(["--image-prompt-type", str(image_prompt_type)])
image_custom_prompt = config_section.get("image_custom_prompt")
if image_custom_prompt:
tokens.extend(["--image-custom-prompt", str(image_custom_prompt)])
commands.append(_format_cli_tokens(tokens))
return commands
raise ValueError(f"Dry-run not supported for input_type '{input_type}'")
[docs]
def run_from_config(path: str, *, dry_run: bool = False) -> None:
"""Execute the pipeline using a YAML configuration file."""
with open(path, encoding="utf8") as f:
raw_cfg = yaml.safe_load(f) or {}
try:
cfg = Coord2RegionConfig.model_validate(raw_cfg)
except ValidationError as exc:
for err in exc.errors():
loc = "->".join(str(p) for p in err.get("loc", ()))
msg = err.get("msg", "Invalid configuration value")
print(f"Config error at {loc or '<root>'}: {msg}", file=sys.stderr)
raise SystemExit(1) from exc
inputs = cfg.collect_inputs(load_coords_file=_load_coords_file)
runtime = cfg.to_pipeline_runtime(inputs)
if dry_run:
commands = _commands_from_config(runtime)
for cmd in commands:
print(cmd)
return
res = run_pipeline(**runtime)
_print_results(res)
[docs]
def create_parser() -> argparse.ArgumentParser:
"""Create the top-level argument parser for the CLI."""
parser = argparse.ArgumentParser(prog="coord2region")
parser.add_argument(
"--version",
action="version",
version=f"%(prog)s {_package_version()}",
help="Show the installed coord2region version and exit",
)
parser.add_argument(
"--list-atlases",
action="store_true",
help="List bundled atlas identifiers and exit",
)
subparsers = parser.add_subparsers(dest="command")
p_run = subparsers.add_parser(
"run", help="Execute a pipeline described in a YAML config file"
)
p_run.add_argument("--config", required=True, help="YAML configuration file")
p_run.add_argument(
"--dry-run",
action="store_true",
help="Print equivalent CLI commands without executing",
)
# Coordinate commands
p_atlas = subparsers.add_parser(
"coords-to-atlas", help="Map coordinates to atlas regions"
)
_add_coordinate_arguments(p_atlas)
_add_execution_options(p_atlas)
_add_atlas_options(p_atlas)
p_study = subparsers.add_parser(
"coords-to-study", help="Retrieve studies for coordinates"
)
_add_coordinate_arguments(p_study)
_add_execution_options(p_study)
_add_atlas_options(p_study)
_add_study_options(p_study)
p_sum = subparsers.add_parser(
"coords-to-summary",
help="Generate summaries alongside atlas labels and studies",
)
_add_coordinate_arguments(p_sum)
_add_execution_options(p_sum)
_add_atlas_options(p_sum)
_add_study_options(p_sum)
_add_llm_options(p_sum)
p_img = subparsers.add_parser(
"coords-to-image", help="Generate images informed by studies"
)
_add_coordinate_arguments(p_img)
_add_execution_options(p_img)
_add_atlas_options(p_img)
_add_study_options(p_img)
_add_image_options(p_img, default_backend="nilearn")
p_insights = subparsers.add_parser(
"coords-to-insights", help="Produce labels, studies, summaries and images"
)
_add_coordinate_arguments(p_insights)
_add_execution_options(p_insights)
_add_atlas_options(p_insights)
_add_study_options(p_insights)
_add_llm_options(p_insights)
_add_image_options(
p_insights,
default_backend="nilearn",
include_huggingface=False,
include_api_options=False,
)
# Region commands
p_rtc = subparsers.add_parser(
"region-to-coords", help="Convert region names to coordinates"
)
_add_region_arguments(p_rtc)
_add_execution_options(p_rtc)
_add_atlas_options(p_rtc, allow_multiple=False, required=True)
p_rts = subparsers.add_parser(
"region-to-study", help="Retrieve studies for regions"
)
_add_region_arguments(p_rts)
_add_execution_options(p_rts)
_add_atlas_options(p_rts, allow_multiple=False, required=True)
_add_study_options(p_rts)
p_rtsum = subparsers.add_parser(
"region-to-summary",
help="Generate summaries for regions based on related studies",
)
_add_region_arguments(p_rtsum)
_add_execution_options(p_rtsum)
_add_atlas_options(p_rtsum, allow_multiple=False, required=True)
_add_study_options(p_rtsum)
_add_llm_options(p_rtsum)
p_rtimg = subparsers.add_parser(
"region-to-image", help="Generate images for regions"
)
_add_region_arguments(p_rtimg)
_add_execution_options(p_rtimg)
_add_atlas_options(p_rtimg, allow_multiple=False, required=True)
_add_study_options(p_rtimg)
_add_image_options(p_rtimg, default_backend="nilearn")
p_rtinsights = subparsers.add_parser(
"region-to-insights", help="Combine coordinates, studies, summaries and images"
)
_add_region_arguments(p_rtinsights)
_add_execution_options(p_rtinsights)
_add_atlas_options(p_rtinsights, allow_multiple=False, required=True)
_add_study_options(p_rtinsights)
_add_llm_options(p_rtinsights)
_add_image_options(
p_rtinsights,
default_backend="nilearn",
include_huggingface=False,
include_api_options=False,
)
return parser
[docs]
def main(argv: Sequence[str] | None = None) -> None:
"""Entry point for the ``coord2region`` console script."""
parser = create_parser()
args = parser.parse_args(argv)
if getattr(args, "list_atlases", False):
_print_available_atlases()
return
if not args.command:
parser.print_help()
return
if args.command == "run":
run_from_config(args.config, dry_run=getattr(args, "dry_run", False))
return
kwargs = _collect_kwargs(args)
def _resolve_coords() -> list[list[float]]:
coords: list[list[float]] = []
coords_file = getattr(args, "coords_file", None)
if coords_file:
coords.extend(_load_coords_file(coords_file))
coords.extend(_parse_coords_tokens(getattr(args, "coords", [])))
if not coords:
parser.error("No coordinates provided")
return coords
def _resolve_regions() -> list[str]:
names = list(getattr(args, "regions", []) or [])
if not names:
parser.error("No region names provided")
return names
def _ensure_single_atlas(command_name: str) -> None:
atlas_names = kwargs.get("atlas_names") or []
if len(atlas_names) != 1:
parser.error(
f"{command_name} requires exactly one atlas specified via --atlas"
)
if args.command == "coords-to-atlas":
coords = _resolve_coords()
for batch in _batch(coords, args.batch_size):
res = run_pipeline(
batch,
"coords",
["region_labels"],
args.output_format,
args.output_name,
config=kwargs,
)
_print_results(res)
elif args.command == "coords-to-study":
coords = _resolve_coords()
for batch in _batch(coords, args.batch_size):
res = run_pipeline(
batch,
"coords",
["region_labels", "raw_studies"],
args.output_format,
args.output_name,
config=kwargs,
)
_print_results(res)
elif args.command == "coords-to-summary":
coords = _resolve_coords()
for batch in _batch(coords, args.batch_size):
res = run_pipeline(
batch,
"coords",
["region_labels", "raw_studies", "summaries"],
args.output_format,
args.output_name,
config=kwargs,
)
_print_results(res)
elif args.command == "coords-to-image":
coords = _resolve_coords()
backend = getattr(args, "image_backend", "nilearn")
for batch in _batch(coords, args.batch_size):
res = run_pipeline(
batch,
"coords",
["region_labels", "raw_studies", "images"],
args.output_format,
args.output_name,
image_backend=backend,
config=kwargs,
)
_print_results(res)
elif args.command == "coords-to-insights":
coords = _resolve_coords()
backend = getattr(args, "image_backend", "nilearn")
for batch in _batch(coords, args.batch_size):
res = run_pipeline(
batch,
"coords",
["region_labels", "raw_studies", "summaries", "images"],
args.output_format,
args.output_name,
image_backend=backend,
config=kwargs,
)
_print_results(res)
elif args.command == "region-to-coords":
_ensure_single_atlas("region-to-coords")
names = _resolve_regions()
for batch in _batch(names, args.batch_size):
res = run_pipeline(
batch,
"region_names",
["mni_coordinates"],
args.output_format,
args.output_name,
config=kwargs,
)
_print_results(res)
elif args.command == "region-to-study":
_ensure_single_atlas("region-to-study")
names = _resolve_regions()
for batch in _batch(names, args.batch_size):
res = run_pipeline(
batch,
"region_names",
["mni_coordinates", "raw_studies"],
args.output_format,
args.output_name,
config=kwargs,
)
_print_results(res)
elif args.command == "region-to-summary":
_ensure_single_atlas("region-to-summary")
names = _resolve_regions()
for batch in _batch(names, args.batch_size):
res = run_pipeline(
batch,
"region_names",
["mni_coordinates", "raw_studies", "summaries"],
args.output_format,
args.output_name,
config=kwargs,
)
_print_results(res)
elif args.command == "region-to-image":
_ensure_single_atlas("region-to-image")
names = _resolve_regions()
backend = getattr(args, "image_backend", "nilearn")
for batch in _batch(names, args.batch_size):
res = run_pipeline(
batch,
"region_names",
["mni_coordinates", "raw_studies", "images"],
args.output_format,
args.output_name,
image_backend=backend,
config=kwargs,
)
_print_results(res)
elif args.command == "region-to-insights":
_ensure_single_atlas("region-to-insights")
names = _resolve_regions()
backend = getattr(args, "image_backend", "nilearn")
for batch in _batch(names, args.batch_size):
res = run_pipeline(
batch,
"region_names",
["mni_coordinates", "raw_studies", "summaries", "images"],
args.output_format,
args.output_name,
image_backend=backend,
config=kwargs,
)
_print_results(res)
if __name__ == "__main__": # pragma: no cover
main()