Skip to content

Commit 6374f4f

Browse files
Add option to fix the random seed
1 parent da4ef9e commit 6374f4f

File tree

2 files changed

+49
-1
lines changed

2 files changed

+49
-1
lines changed

mriqc/cli/parser.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -439,6 +439,14 @@ def _bids_filter(value):
439439
default=False,
440440
help='Despike the functional scans during head motion correction preprocessing.',
441441
)
442+
g_func.add_argument(
443+
'--random-seed',
444+
dest='_random_seed',
445+
action='store',
446+
type=int,
447+
default=None,
448+
help='Initialize the random seed for the workflow',
449+
)
442450
g_func.add_argument(
443451
'--start-idx',
444452
action=DeprecateAction,
@@ -453,7 +461,6 @@ def _bids_filter(value):
453461
help='DEPRECATED Final volume in functional timeseries that should be '
454462
'considered for preprocessing.',
455463
)
456-
457464
latest = check_latest()
458465
if latest is not None and currentv < latest:
459466
print(

mriqc/config.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,7 @@
9797
from time import strftime
9898
from typing import TYPE_CHECKING, Any, Iterable
9999
from uuid import uuid4
100+
import random
100101

101102
try:
102103
# This option is only available with Python 3.8
@@ -674,11 +675,51 @@ def getLogger(cls, name) -> logging.Logger:
674675
return retval
675676

676677

678+
class seeds(_Config):
679+
"""Initialize the PRNG and track random seed assignments"""
680+
681+
_random_seed = None
682+
master = None
683+
"""Master random seed to initialize the Pseudorandom Number Generator (PRNG)"""
684+
ants = None
685+
"""Seed used for antsRegistration, antsAI, antsMotionCorr"""
686+
numpy = None
687+
"""Seed used by NumPy"""
688+
689+
@classmethod
690+
def init(cls):
691+
if cls._random_seed is not None:
692+
cls.master = cls._random_seed
693+
if cls.master is None:
694+
cls.master = random.randint(1, 65536)
695+
random.seed(cls.master) # initialize the PRNG
696+
# functions to set program specific seeds
697+
cls.ants = _set_ants_seed()
698+
cls.numpy = _set_numpy_seed()
699+
700+
701+
def _set_ants_seed():
702+
"""Fix random seed for antsRegistration, antsAI, antsMotionCorr"""
703+
val = random.randint(1, 65536)
704+
os.environ['ANTS_RANDOM_SEED'] = str(val)
705+
return val
706+
707+
708+
def _set_numpy_seed():
709+
"""NumPy's random seed is independent from Python's `random` module"""
710+
import numpy as np
711+
712+
val = random.randint(1, 65536)
713+
np.random.seed(val)
714+
return val
715+
716+
677717
def from_dict(sections: dict) -> None:
678718
"""Read settings from a flat dictionary."""
679719
execution.load(sections)
680720
workflow.load(sections)
681721
nipype.load(sections, init=False)
722+
seeds.load(sections, init=False)
682723

683724

684725
def load(filename: str | os.PathLike) -> None:

0 commit comments

Comments
 (0)