1414import polars as pl
1515from tqdm import tqdm
1616
17- from rbc .cli import _DEFAULT_ENV_VARS , _FUNC_GROUP_ENTITIES , _SUB_SES_QUERY
17+ from rbc .cli import (
18+ _ANAT_GROUP_ENTITIES ,
19+ _DEFAULT_ENV_VARS ,
20+ _FUNC_GROUP_ENTITIES ,
21+ _SUB_SES_QUERY ,
22+ )
1823from rbc .cli .base import BaseArgs , _validate_atlas , _validate_positive , _validate_task
1924from rbc .cli .query import iter_session_files , load_session
2025from rbc .context import PipelineContext
@@ -77,17 +82,22 @@ def main(args: AllArgs) -> int: # noqa: C901
7782 dataset_dir = args .input_dir , index_fpath = None , max_workers = 0 , verbose = ctx .verbose
7883 )
7984
80- filters = [pl .col ("space" ).is_null (), pl .col ("desc" ).is_null ()]
85+ filters = [
86+ pl .col ("ses" ) != "longitudinal" ,
87+ pl .col ("space" ).is_null (),
88+ pl .col ("desc" ).is_null (),
89+ ]
8190 if len (args .participant_label ) > 0 :
8291 filters .append (pl .col ("sub" ).is_in (args .participant_label ))
8392 if len (args .session_label ) > 0 :
8493 filters .append (pl .col ("ses" ).is_in (args .session_label ))
8594 if args .task is not None :
8695 filters .append (pl .col ("task" ) == args .task )
87- if filters :
88- df = df .filter (pl .all_horizontal (filters ))
96+ df = df .filter (pl .all_horizontal (filters ))
8997
90- for _ , sub_ses_group in tqdm (df .group_by (_SUB_SES_QUERY ), disable = not ctx .verbose ):
98+ for _ , sub_ses_group in tqdm (
99+ df .group_by (_SUB_SES_QUERY , maintain_order = True ), disable = not ctx .verbose
100+ ):
91101 pipe_ctx = PipelineContext (
92102 sub = sub_ses_group ["sub" ][0 ],
93103 ses = sub_ses_group ["ses" ][0 ] or None ,
@@ -96,29 +106,41 @@ def main(args: AllArgs) -> int: # noqa: C901
96106 session = load_session (sub_ses_group , pipe_ctx .sub , pipe_ctx .ses )
97107
98108 # --- Anatomical (once per session, first T1w) ---
99- anat_row = session .anat .row (0 , named = True )
100- t1w_fpath = Path (anat_row ["root" ]) / anat_row ["path" ]
101- ctx .logger .info (f"Anatomical: { t1w_fpath } " )
102-
103- anat_outputs = anatomical_preprocess (in_t1w = t1w_fpath )
104-
105- anat = pipe_ctx .bids (datatype = Datatype .ANAT )
106- anat .save (anat_outputs .brain , suffix = Suffix .T1W , desc = "brain" )
107- anat .save (anat_outputs .brain_mask , suffix = Suffix .MASK , desc = "T1w" )
108- anat .save (anat_outputs .csf_mask , suffix = Suffix .MASK , desc = "csf" )
109- anat .save (anat_outputs .gm_mask , suffix = Suffix .MASK , desc = "gm" )
110- anat .save (anat_outputs .wm_mask , suffix = Suffix .MASK , desc = "wm" )
111- anat .save (anat_outputs .wm_bbr_mask , suffix = Suffix .MASK , desc = "wmBBR" )
112- anat .save (
113- anat_outputs .forward_xfm ,
114- suffix = "xfm" ,
115- extra = {"from" : "T1w" , "to" : TemplateSpace .MNI152NLIN6ASYM , "mode" : "image" },
116- )
117- anat .save (
118- anat_outputs .inverse_xfm ,
119- suffix = "xfm" ,
120- extra = {"from" : TemplateSpace .MNI152NLIN6ASYM , "to" : "T1w" , "mode" : "image" },
121- )
109+ for _ , anat_df in session .anat .filter (pl .col ("suffix" ) == "T1w" ).group_by (
110+ _ANAT_GROUP_ENTITIES , maintain_order = True
111+ ):
112+ anat_row = anat_df .filter (suffix = "T1w" ).row (0 , named = True )
113+ t1w_fpath = Path (anat_row ["root" ]) / anat_row ["path" ]
114+ ents = extract_entities (anat_row , ["run" , "acq" , "rec" , "echo" ])
115+ ctx .logger .info (f"Anatomical: { t1w_fpath } " )
116+
117+ anat_outputs = anatomical_preprocess (in_t1w = t1w_fpath )
118+
119+ anat = pipe_ctx .bids (datatype = Datatype .ANAT , entities = ents )
120+ anat .save (anat_outputs .brain , suffix = Suffix .T1W , desc = "brain" )
121+ anat .save (anat_outputs .brain_mask , suffix = Suffix .MASK , desc = "T1w" )
122+ anat .save (anat_outputs .csf_mask , suffix = Suffix .MASK , desc = "csf" )
123+ anat .save (anat_outputs .gm_mask , suffix = Suffix .MASK , desc = "gm" )
124+ anat .save (anat_outputs .wm_mask , suffix = Suffix .MASK , desc = "wm" )
125+ anat .save (anat_outputs .wm_bbr_mask , suffix = Suffix .MASK , desc = "wmBBR" )
126+ anat .save (
127+ anat_outputs .forward_xfm ,
128+ suffix = "xfm" ,
129+ extra = {
130+ "from" : "T1w" ,
131+ "to" : TemplateSpace .MNI152NLIN6ASYM ,
132+ "mode" : "image" ,
133+ },
134+ )
135+ anat .save (
136+ anat_outputs .inverse_xfm ,
137+ suffix = "xfm" ,
138+ extra = {
139+ "from" : TemplateSpace .MNI152NLIN6ASYM ,
140+ "to" : "T1w" ,
141+ "mode" : "image" ,
142+ },
143+ )
122144
123145 # --- Functional + Metrics + QC (per BOLD run) ---
124146 for func_df , _anat_df in iter_session_files (
0 commit comments