Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2,151 changes: 1,013 additions & 1,138 deletions pixi.lock

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ platforms = ["linux-64"]

[tool.pixi.feature.runtime.dependencies]
snakemake = ">=9.5.1,<10"
snakebids = ">=0.14.0,<0.15"
snakebids = ">=0.15.0,<0.16"
snakemake-storage-plugin-s3 = ">=0.3.3,<0.4"
snakemake-storage-plugin-gcs = ">=1.1.4,<2"
gcsfs = ">=2025.5.1,<2026"
Expand Down
70 changes: 36 additions & 34 deletions spimquant/workflow/Snakefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,15 @@ import os
from zarrnii import ZarrNii
from snakemake.utils import format
from snakebids import bids, generate_inputs, get_wildcard_constraints, set_bids_spec
Copy link

Copilot AI Mar 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

get_wildcard_constraints and set_bids_spec are imported here but not used (the code calls snakebids.set_bids_spec directly). Removing unused imports (or using the imported set_bids_spec) will avoid confusion and keep the Snakefile tidy.

Suggested change
from snakebids import bids, generate_inputs, get_wildcard_constraints, set_bids_spec
from snakebids import bids, generate_inputs

Copilot uses AI. Check for mistakes.
import snakebids

set_bids_spec("v0_11_0")
# update v15 spec to add template entity
spec = snakebids.paths.specs.v0_15_0()
tpl_spec = spec[0].copy()
tpl_spec["entity"] = "template"
tpl_spec["tag"] = "tpl"
spec.insert(0, tpl_spec)
snakebids.set_bids_spec(spec)


configfile: "config/snakebids.yml"
Expand Down Expand Up @@ -200,7 +207,7 @@ rule all_fieldfrac_tune:
inputs["spim"].expand(
bids(
root=root,
datatype="micr",
datatype="seg",
stain="{stain}",
level="{level}",
desc="otsu+k{k}i{i}",
Expand Down Expand Up @@ -233,9 +240,10 @@ rule all_register:
inputs["spim"].expand(
bids(
root=root,
datatype="micr",
datatype="xfm",
stain="{stain}",
space="{template}",
from_="SPIM",
to="{template}",
suffix="regqc.html",
**inputs["spim"].wildcards,
),
Expand All @@ -249,7 +257,7 @@ rule all_vessels:
inputs["spim"].expand(
bids(
root=root,
datatype="micr",
datatype="vessels",
stain="{stain}",
level="{level}",
desc="{desc}",
Expand All @@ -269,7 +277,7 @@ rule all_segment:
inputs["spim"].expand(
bids(
root=root,
datatype="micr",
datatype="featuremap",
seg="{seg}",
space="{template}",
desc="{desc}",
Expand Down Expand Up @@ -299,7 +307,7 @@ rule all_segment:
inputs["spim"].expand(
bids(
root=root,
datatype="micr",
datatype="seg",
stain="{stain}",
level="{level}",
desc="{desc}",
Expand All @@ -315,25 +323,7 @@ rule all_segment:
inputs["spim"].expand(
bids(
root=root,
datatype="micr",
stain="{stain}",
seg="{seg}",
desc="deform",
level="{level}",
from_="{template}",
suffix="dseg.{ext}",
**inputs["spim"].wildcards,
),
stain=stains_for_seg,
level=config["registration_level"],
seg=atlas_segs,
template=config["template"],
ext=["tsv", "itksnap.txt"],
),
inputs["spim"].expand(
bids(
root=root,
datatype="micr",
datatype="seg",
stain="{stain}",
level="{level}",
desc="{desc}",
Expand All @@ -347,7 +337,7 @@ rule all_segment:
inputs["spim"].expand(
bids(
root=root,
datatype="micr",
datatype="seg",
stain="{stain}",
space="{template}",
desc="{desc}",
Expand All @@ -358,14 +348,25 @@ rule all_segment:
template=config["template"],
desc=config["seg_method"],
),
expand(
bids(
root=root,
template="{template}",
seg="{seg}",
suffix="dseg.{ext}",
),
seg=atlas_segs,
template=config["template"],
ext=["tsv", "itksnap.txt"],
),


rule all_segment_coloc:
input:
inputs["spim"].expand(
bids(
root=root,
datatype="micr",
datatype="featuremap",
seg="{seg}",
space="{template}",
desc="{desc}",
Expand All @@ -380,7 +381,7 @@ rule all_segment_coloc:
inputs["spim"].expand(
bids(
root=root,
datatype="micr",
datatype="seg",
desc="{desc}",
space="{template}",
suffix="coloccounts.nii.gz",
Expand Down Expand Up @@ -408,8 +409,9 @@ rule all_mri_reg:
inputs["spim"].expand(
bids(
root=root,
datatype="anat",
space="SPIM",
datatype="xfm",
from_=f"{mri_suffix}",
to="SPIM",
suffix="regqc.html",
**inputs["spim"].wildcards,
),
Expand All @@ -421,7 +423,7 @@ rule all_spim_patches:
inputs["spim"].expand(
bids(
root=root,
datatype="micr",
datatype="seg",
stain="{stain}",
seg="{seg}",
from_="{template}",
Expand All @@ -439,7 +441,7 @@ rule all_spim_patches:
inputs["spim"].expand(
bids(
root=root,
datatype="micr",
datatype="seg",
stain="{stain}",
seg="{seg}",
from_="{template}",
Expand All @@ -461,7 +463,7 @@ rule all_imaris_crops:
inputs["spim"].expand(
bids(
root=root,
datatype="micr",
datatype="seg",
seg="{seg}",
from_="{template}",
level="{level}",
Expand Down
19 changes: 5 additions & 14 deletions spimquant/workflow/rules/common.smk
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ Common utility functions for SPIMquant workflows.

This module provides shared helper functions used across multiple workflow rules:

- bids_tpl(): BIDS path constructor for template-specific files
- resources_path(): Path resolver for resources directory
- get_template_path(): Template file locator with optional cropping
- get_template_for_reg(): Registration-specific template selector
Expand All @@ -14,12 +13,6 @@ organization following BIDS conventions.
"""

from pathlib import Path
from snakebids import bids


def bids_tpl(root, template, **entities):
"""bids() wrapper for files in tpl-template folder"""
return str(Path(bids(root=root, tpl=template)) / bids(tpl=template, **entities))


def resources_path(path):
Expand All @@ -38,14 +31,14 @@ def get_template_path(root, template, template_crop=None):
suffix = "anat"

if template_crop is not None:
return bids_tpl(
return bids(
root=root,
template=template,
desc=f"{template_crop}crop",
suffix=f"{suffix}.nii.gz",
)
else:
return bids_tpl(root=root, template=template, suffix=f"{suffix}.nii.gz")
return bids(root=root, template=template, suffix=f"{suffix}.nii.gz")


def get_template_for_reg(wildcards):
Expand All @@ -58,9 +51,7 @@ def get_template_for_reg(wildcards):
if config.get("template_crop") is not None:
return get_template_path(root, wildcards.template, config["template_crop"])
else:
return bids_tpl(
root=root, template=wildcards.template, suffix=f"{suffix}.nii.gz"
)
return bids(root=root, template=wildcards.template, suffix=f"{suffix}.nii.gz")


def get_stains_all_subjects():
Expand All @@ -79,7 +70,7 @@ def get_regionprops_parquet(wildcards):
if do_vessels:
return bids(
root=root,
datatype="micr",
datatype="tabular",
desc="{desc}+vessels",
space="{template}",
vessels=stain_for_vessels,
Expand All @@ -89,7 +80,7 @@ def get_regionprops_parquet(wildcards):
else:
return bids(
root=root,
datatype="micr",
datatype="tabular",
desc="{desc}",
space="{template}",
suffix="regionprops.parquet",
Expand Down
16 changes: 8 additions & 8 deletions spimquant/workflow/rules/counts.smk
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ rule counts_per_voxel:
ref_spim=inputs["spim"].path,
regionprops_parquet=bids(
root=root,
datatype="micr",
datatype="tabular",
stain="{stain}",
desc="{desc}",
suffix="regionprops.parquet",
Expand All @@ -16,7 +16,7 @@ rule counts_per_voxel:
output:
counts_nii=bids(
root=root,
datatype="micr",
datatype="seg",
level="{level}",
stain="{stain}",
desc="{desc}",
Expand All @@ -35,10 +35,10 @@ rule counts_per_voxel_template:
"""Calculate counts per voxel based on points
in template space"""
input:
template=bids_tpl(root=root, template="{template}", suffix="anat.nii.gz"),
template=bids(root=root, template="{template}", suffix="anat.nii.gz"),
regionprops_parquet=bids(
root=root,
datatype="micr",
datatype="tabular",
space="{template}",
desc="{desc}",
suffix="regionprops.parquet",
Expand All @@ -49,7 +49,7 @@ rule counts_per_voxel_template:
output:
counts_nii=bids(
root=root,
datatype="micr",
datatype="seg",
stain="{stain}",
space="{template}",
desc="{desc}",
Expand All @@ -68,10 +68,10 @@ rule coloc_per_voxel_template:
"""Calculate coloc counts per voxel based on points
in template space"""
input:
template=bids_tpl(root=root, template="{template}", suffix="anat.nii.gz"),
template=bids(root=root, template="{template}", suffix="anat.nii.gz"),
coloc_parquet=bids(
root=root,
datatype="micr",
datatype="tabular",
space="{template}",
desc="{desc}",
suffix="coloc.parquet",
Expand All @@ -82,7 +82,7 @@ rule coloc_per_voxel_template:
output:
counts_nii=bids(
root=root,
datatype="micr",
datatype="seg",
space="{template}",
desc="{desc}",
suffix="coloccounts.nii.gz",
Comment on lines 83 to 88
Copy link

Copilot AI Mar 31, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

coloccounts.nii.gz is a scalar count map, not a segmentation mask. Consider writing it under a scalar-image datatype (e.g., micr/) rather than seg/ to avoid mixing segmentations and scalar maps.

Copilot uses AI. Check for mistakes.
Expand Down
15 changes: 6 additions & 9 deletions spimquant/workflow/rules/fieldfrac.smk
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ rule fieldfrac:
input:
mask=bids(
root=root,
datatype="micr",
datatype="{datatype}",
stain="{stain}",
level=config["segmentation_level"],
desc="{desc}",
Expand All @@ -23,7 +23,7 @@ rule fieldfrac:
output:
fieldfrac_nii=bids(
root=root,
datatype="micr",
datatype="{datatype,seg|vessels}",
stain="{stain}",
level="{level}",
desc="{desc}",
Expand All @@ -42,7 +42,7 @@ rule map_fieldfrac_img_to_seg_tsv:
input:
img=bids(
root=root,
datatype="micr",
datatype="seg",
stain="{stain}",
level="{level}",
desc="{desc}",
Expand All @@ -51,22 +51,19 @@ rule map_fieldfrac_img_to_seg_tsv:
),
dseg=bids(
root=root,
datatype="micr",
datatype="parc",
seg="{seg}",
desc="deform",
level="{level}",
from_="{template}",
suffix="dseg.nii.gz",
**inputs["spim"].wildcards,
),
label_tsv=bids_tpl(
root=root, template="{template}", seg="{seg}", suffix="dseg.tsv"
),
label_tsv=bids(root=root, template="{template}", seg="{seg}", suffix="dseg.tsv"),
output:
tsv=temp(
bids(
root=root,
datatype="micr",
datatype="tabular",
seg="{seg}",
from_="{template}",
stain="{stain}",
Expand Down
Loading
Loading