Skip to content

Commit 6869160

Browse files
committed
Merge tag '2.13.2'
2.13.2 (July 28, 2025) Patch release in the 2.13.x series. This includes a fix for cases where a scan contributes to multiple `B0FieldIdentifier`s. * [FIX] Fixes conditions of overlapping B0FieldIdentifier, resulting in no estimators (#497)
2 parents 13fbcc7 + 7fdd531 commit 6869160

File tree

3 files changed

+165
-12
lines changed

3 files changed

+165
-12
lines changed

CHANGES.rst

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,21 @@
1-
2.13.1 (Jane 12, 2025)
1+
2.13.2 (July 28, 2025)
2+
======================
3+
Patch release in the 2.13.x series.
4+
5+
This includes a fix for cases where a scan contributes to multiple ``B0FieldIdentifier``\s.
6+
7+
* [FIX] Fixes conditions of overlapping B0FieldIdentifier, resulting in no estimators (#497)
8+
9+
10+
2.13.1 (June 12, 2025)
211
======================
312
Patch release in the 2.13.x series.
413

514
This includes a fix to ``init_fmap_preproc_wf`` node naming.
615

716
* FIX: Use the sanitized id when naming through nipype (#495)
817

18+
919
2.13.0 (May 15, 2025)
1020
=====================
1121
Feature release in the 2.13.x series.

sdcflows/utils/tests/test_wrangler.py

Lines changed: 152 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,146 @@ def gen_layout(bids_dir, database_dir=None):
202202
}
203203

204204

205+
pepolar_b0ids = {
206+
'01': [
207+
{
208+
'session': '01',
209+
'anat': [{'suffix': 'T1w', 'metadata': {'EchoTime': 1}}],
210+
'func': [
211+
{
212+
'task': 'rest',
213+
'run': 1,
214+
'suffix': 'bold',
215+
'metadata': {
216+
'RepetitionTime': 0.8,
217+
'TotalReadoutTime': 0.5,
218+
'PhaseEncodingDirection': 'j',
219+
'B0FieldIdentifier': 'b0_pepolar',
220+
'B0FieldSource': 'b0_pepolar',
221+
},
222+
},
223+
{
224+
'task': 'rest',
225+
'run': 2,
226+
'suffix': 'bold',
227+
'metadata': {
228+
'RepetitionTime': 0.8,
229+
'TotalReadoutTime': 0.5,
230+
'PhaseEncodingDirection': 'j-',
231+
'B0FieldIdentifier': 'b0_pepolar',
232+
'B0FieldSource': 'b0_pepolar',
233+
},
234+
},
235+
],
236+
},
237+
{
238+
'session': '02',
239+
'anat': [{'suffix': 'T1w', 'metadata': {'EchoTime': 1}}],
240+
'func': [
241+
{
242+
'task': 'rest',
243+
'run': 1,
244+
'suffix': 'bold',
245+
'metadata': {
246+
'RepetitionTime': 0.8,
247+
'TotalReadoutTime': 0.5,
248+
'PhaseEncodingDirection': 'j',
249+
'B0FieldSource': 'b0_pepolar',
250+
},
251+
},
252+
{
253+
'task': 'rest',
254+
'run': 2,
255+
'suffix': 'bold',
256+
'metadata': {
257+
'RepetitionTime': 0.8,
258+
'TotalReadoutTime': 0.5,
259+
'PhaseEncodingDirection': 'j-',
260+
'B0FieldSource': 'b0_pepolar',
261+
},
262+
},
263+
{
264+
'task': 'rest',
265+
'run': 1,
266+
'suffix': 'sbref',
267+
'metadata': {
268+
'RepetitionTime': 0.8,
269+
'TotalReadoutTime': 0.5,
270+
'PhaseEncodingDirection': 'j',
271+
'B0FieldIdentifier': 'b0_pepolar',
272+
'B0FieldSource': 'b0_pepolar',
273+
},
274+
},
275+
{
276+
'task': 'rest',
277+
'run': 2,
278+
'suffix': 'sbref',
279+
'metadata': {
280+
'RepetitionTime': 0.8,
281+
'TotalReadoutTime': 0.5,
282+
'PhaseEncodingDirection': 'j-',
283+
'B0FieldIdentifier': 'b0_pepolar',
284+
'B0FieldSource': 'b0_pepolar',
285+
},
286+
},
287+
],
288+
},
289+
{
290+
'session': '03',
291+
'anat': [{'suffix': 'T1w', 'metadata': {'EchoTime': 1}}],
292+
'func': [
293+
{
294+
'task': 'rest',
295+
'run': 1,
296+
'suffix': 'bold',
297+
'metadata': {
298+
'RepetitionTime': 0.8,
299+
'TotalReadoutTime': 0.5,
300+
'PhaseEncodingDirection': 'j',
301+
'B0FieldSource': 'b0_pepolar',
302+
},
303+
},
304+
{
305+
'task': 'rest',
306+
'run': 2,
307+
'suffix': 'bold',
308+
'metadata': {
309+
'RepetitionTime': 0.8,
310+
'TotalReadoutTime': 0.5,
311+
'PhaseEncodingDirection': 'j-',
312+
'B0FieldSource': 'b0_pepolar',
313+
},
314+
},
315+
{
316+
'task': 'rest',
317+
'run': 1,
318+
'suffix': 'sbref',
319+
'metadata': {
320+
'RepetitionTime': 0.8,
321+
'TotalReadoutTime': 0.5,
322+
'PhaseEncodingDirection': 'j',
323+
'B0FieldIdentifier': ['b0_pepolar', 'b0_pepolar_dup'],
324+
'B0FieldSource': 'b0_pepolar',
325+
},
326+
},
327+
{
328+
'task': 'rest',
329+
'run': 2,
330+
'suffix': 'sbref',
331+
'metadata': {
332+
'RepetitionTime': 0.8,
333+
'TotalReadoutTime': 0.5,
334+
'PhaseEncodingDirection': 'j-',
335+
'B0FieldIdentifier': ['b0_pepolar', 'b0_pepolar_dup'],
336+
'B0FieldSource': 'b0_pepolar',
337+
},
338+
},
339+
],
340+
},
341+
]
342+
}
343+
344+
205345
phasediff = {
206346
'01': [
207347
{
@@ -304,26 +444,28 @@ def gen_layout(bids_dir, database_dir=None):
304444

305445

306446
@pytest.mark.parametrize(
307-
'name,skeleton,estimations',
447+
'name,skeleton,estimations,bids_filters',
308448
[
309-
('pepolar', pepolar, 1),
310-
('phasediff', phasediff, 1),
449+
('pepolar', pepolar, 1, 'fmap'),
450+
('pepolar_b0ids', pepolar_b0ids, 1, 'bold'),
451+
('phasediff', phasediff, 1, 'fmap'),
311452
],
312453
)
313-
def test_wrangler_filter(tmpdir, name, skeleton, estimations):
454+
def test_wrangler_filter(tmpdir, name, skeleton, estimations, bids_filters):
314455
bids_dir = str(tmpdir / name)
315456
generate_bids_skeleton(bids_dir, skeleton)
316457
layout = gen_layout(bids_dir)
317-
est = find_estimators(layout=layout, subject='01', bids_filters=filters['fmap'])
458+
est = find_estimators(layout=layout, subject='01', bids_filters=filters[bids_filters])
318459
assert len(est) == estimations
319460
clear_registry()
320461

321462

322463
@pytest.mark.parametrize(
323-
'name,skeleton,total_estimations',
464+
'name,skeleton,total_estimations,test_auto',
324465
[
325-
('pepolar', pepolar, 5),
326-
('phasediff', phasediff, 3),
466+
('pepolar', pepolar, 5, True),
467+
('pepolar_b0ids', pepolar_b0ids, 2, False),
468+
('phasediff', phasediff, 3, True),
327469
],
328470
)
329471
@pytest.mark.parametrize(
@@ -335,7 +477,7 @@ def test_wrangler_filter(tmpdir, name, skeleton, estimations):
335477
(None, None),
336478
],
337479
)
338-
def test_wrangler_URIs(tmpdir, name, skeleton, session, estimations, total_estimations):
480+
def test_wrangler_URIs(tmpdir, name, skeleton, session, estimations, total_estimations, test_auto):
339481
bids_dir = str(tmpdir / name)
340482
generate_bids_skeleton(bids_dir, skeleton)
341483
layout = gen_layout(bids_dir)
@@ -345,7 +487,7 @@ def test_wrangler_URIs(tmpdir, name, skeleton, session, estimations, total_estim
345487
sessions=[session] if session else None,
346488
)
347489
assert len(est) == estimations or total_estimations
348-
if session:
490+
if session and test_auto:
349491
bold = layout.get(session=session, suffix='bold', extension='.nii.gz')[0]
350492
intended_rel = re.sub(r'^sub-[a-zA-Z0-9]*/', '', str(Path(bold).relative_to(layout.root)))
351493
b0_id = get_identifier(intended_rel)

sdcflows/utils/wrangler.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -377,7 +377,8 @@ def find_estimators(
377377
[
378378
fm.FieldmapFile(fmap.path, metadata=fmap.get_metadata())
379379
for fmap in bare_ids + listed_ids
380-
]
380+
],
381+
bids_id=b0_id,
381382
)
382383
except (ValueError, TypeError) as err:
383384
_log_debug_estimator_fail(

0 commit comments

Comments
 (0)