OSCR

Same ages, different stages: Pubertal development in 9- and 10-year olds is associated with entropy of fMRI signals.

Code ↔ Paper

2 matches between paragraphs of the paper and lines of its authors' code, computed by the harvester (lexical-v1). Click a colored paragraph or line to see its counterpart.

The 2 matches
  1. [1] § Method › Measures › Sample entropy ↔ app/pipelines.py, lines 12–92 · score 0.67 · bandpass filter, 0.009 Hz, smoothing, DCANBOLDproc, surface, HCP
  2. [2] § Method › Measures › Sample entropy ↔ app/pipelines.py, lines 12–92 · score 0.65 · BOLD signal, vertex, motion, contiguity, FD, subcortical

Paper

Loaded from Europe PMC by your browser, not stored by OSCR: doi.org · Europe PMC

The paper is loaded when this pane is shown.

The authors' code

Python · 1,034 lines · 37 KB · BSD-3-Clause · 2 matches

  1. import inspect
  2. import json
  3. import multiprocessing as mp
  4. import subprocess
  5. import os
  6. from helpers import (get_fmriname, get_readoutdir, get_realdwelltime,
  7. get_relpath, get_taskname, ijk_to_xyz)
  8. class ParameterSettings(object):
  9. """
  10. Paths to files and settings required to run DCAN HCP. Class attributes
  11. should be any parameters which are independent of input image parameters,
  12. for example, the target atlases. Instance attributes are attributes which
  13. are read from or dependent upon inputs. Additionally, they may include
  14. special options for processing or for overriding class attributes. All
  15. attributes will be formatted according to the available
  16. """
  17. summary_dir = "summary_{DCANBOLDPROCVER}"
  18. # @ templates @ #
  19. # MNI0.7mm template
  20. t1template = "{HCPPIPEDIR_Templates}/MNI152_T1_1mm.nii.gz"
  21. # Brain extracted MNI0.7mm template
  22. t1templatebrain = "{HCPPIPEDIR_Templates}/MNI152_T1_1mm_brain.nii.gz"
  23. # MNI2mm template
  24. t1template2mm = "{HCPPIPEDIR_Templates}/MNI152_T1_2mm.nii.gz"
  25. # MNI0.7mm T2wTemplate
  26. t2template = "{HCPPIPEDIR_Templates}/MNI152_T2_1mm.nii.gz"
  27. # Brain extracted MNI0.7mm T2wTemplate
  28. t2templatebrain = "{HCPPIPEDIR_Templates}/MNI152_T2_1mm_brain.nii.gz"
  29. # MNI2mm T2wTemplate
  30. t2template2mm = "{HCPPIPEDIR_Templates}/MNI152_T2_2mm.nii.gz"
  31. # Brain mask MNI0.7mm template
  32. templatemask = "{HCPPIPEDIR_Templates}/MNI152_T1_1mm_brain_mask.nii.gz"
  33. # MNI2mm template
  34. template2mmmask = "{HCPPIPEDIR_Templates}/MNI152_T1_2mm_brain_mask_dil" \
  35. ".nii.gz"
  36. # Myelin Maps
  37. refmyelinmaps = "{HCPPIPEDIR_Templates}/standard_mesh_atlases/" \
  38. "Conte69.MyelinMap_BC.164k_fs_LR.dscalar.nii"
  39. # Surface Atlas Templates
  40. surfatlasdir = "{HCPPIPEDIR_Templates}/standard_mesh_atlases"
  41. # Grayordinate Templates
  42. grayordinatesdir = "{HCPPIPEDIR_Templates}/91282_Greyordinates"
  43. # @ various settings @ #
  44. # fov size for robust_fov automatic cropping
  45. brainsize = 150
  46. # final time series isotropic resolution (mm)
  47. fmrires = 2.0
  48. # resolution of greyordinates (mm)
  49. grayordinatesres = 2
  50. # smoothing sigma for final greyordinate data (mm)
  51. smoothingFWHM = 2
  52. # surface registration algorithm, one of: FS, MSMSulc
  53. regname = "MSMSulc"
  54. # number of vertices (in thousands) for high and low res surface meshes
  55. hiresmesh = "164"
  56. lowresmesh = "32"
  57. # motion correction method
  58. mctype = 'MCFLIRT'
  59. # @ configuration files @ #
  60. topupconfig = "{HCPPIPEDIR_Config}/b02b0.cnf"
  61. fnirtconfig = "{HCPPIPEDIR_Config}/T1_2_MNI152_2mm.cnf"
  62. freesurferlabels = "{HCPPIPEDIR_Config}/FreeSurferAllLut.txt"
  63. subcortgraylabels = "{HCPPIPEDIR_Config}/FreeSurferSubcortical" \
  64. "LabelTableLut.txt"
  65. # @ bold processing defaults @ #
  66. # brain radius of subject set
  67. brain_radius = 50
  68. # threshold for valid signal regression frames.
  69. fd_threshold = 0.3
  70. # bold signal temporal bandpass filter parameters
  71. filter_order = 2
  72. lower_bpf = 0.009
  73. upper_bpf = 0.080
  74. # motion regressor bandstop filter parameters
  75. motion_filter_type = 'notch'
  76. motion_filter_order = 4
  77. band_stop_min = None
  78. band_stop_max = None
  79. motion_filter_option = 5
  80. # seconds to omit from beginning of scan
  81. skip_seconds = 5
  82. # cont frames
  83. contiguous_frames = 5
  84. def __init__(self, bids_data, output_directory):
  85. """
  86. Specification to run pipeline on a single subject session.
  87. :param bids_data: yielded spec from read_bids_dataset
  88. :param output_directory: output directory for pipeline
  89. """
  90. # input bids data struct
  91. self.bids_data = bids_data
  92. # @ parameters read from bids @ #
  93. self.t1w = self.bids_data['t1w']
  94. self.t1samplespacing = get_realdwelltime(
  95. self.bids_data['t1w_metadata'])
  96. if 'T2w' in self.bids_data['types']:
  97. self.useT2 = 'true'
  98. self.t2w = self.bids_data['t2w']
  99. self.t2samplespacing = get_realdwelltime(
  100. self.bids_data['t2w_metadata'])
  101. else:
  102. self.useT2 = 'false'
  103. self.t2w = []
  104. self.t2samplespacing = None
  105. # distortion correction method: TOPUP, FIELDMAP, or NONE, inferred
  106. # from files, defaults to spin echo (topup) if both field maps exist
  107. self.unwarpdir = get_readoutdir(self.bids_data['t1w_metadata'])
  108. fmap_types = {'magnitude', 'magnitude1', 'magnitude2', 'phasediff',
  109. 'phase1', 'phase2', 'fieldmap'}
  110. if 'epi' in self.bids_data['types']:
  111. self.dcmethod = 'TOPUP'
  112. # spin echo field map spacing @TODO read during volume per fmap?
  113. self.echospacing = self.bids_data['fmap_metadata']['positive'][0][
  114. 'EffectiveEchoSpacing']
  115. self.echospacing = ('%.12f' % self.echospacing).rstrip('0')
  116. # distortion correction phase encoding direction
  117. # somewhat arbitrary in PreFreeSurfer
  118. if self.bids_data['func']:
  119. # take phase encoding direction from first functional.
  120. self.seunwarpdir = ijk_to_xyz(
  121. self.bids_data['func_metadata'][0]['PhaseEncodingDirection'])
  122. else:
  123. # if no functional data is provided, use positive spin echo
  124. self.seunwarpdir = ijk_to_xyz(
  125. self.bids_data['fmap_metadata']['positive'][0][
  126. 'PhaseEncodingDirection'])
  127. # set unused fmap parameters to none
  128. self.fmapmag = self.fmapphase = self.fmapgeneralelectric = \
  129. self.echodiff = self.gdcoeffs = None
  130. elif fmap_types.intersection(set(self.bids_data['types'])):
  131. self.dcmethod = 'FIELDMAP'
  132. types = self.bids_data['fmap'].keys()
  133. # gradient field map delta TE
  134. if 'magnitude1' in types and 'magnitude2' in types:
  135. self.fmapmag = self.bids_data['fmap']['magnitude1']
  136. self.echodiff = self.bids_data['fmap_metadata'][
  137. 'magnitude2']['EchoTime'] - self.bids_data[
  138. 'fmap_metadata']['magnitude1']['EchoTime']
  139. self.echodiff = '%g' % (self.echodiff * 1000.) # milliseconds
  140. self.fmapgeneralelectric = None
  141. elif 'magnitude' in types:
  142. raise NotImplementedError
  143. else:
  144. raise Exception('No FM magnitude image identified')
  145. if 'phasediff' in types:
  146. self.fmapphase = self.bids_data['fmap']['phasediff']
  147. elif 'phase1' in types and 'phase2' in types:
  148. raise NotImplementedError
  149. else:
  150. raise Exception('No FM phase image identified')
  151. # set unused spin echo parameters to none
  152. self.seunwarpdir = self.gdcoeffs = self.echospacing = None
  153. else:
  154. # all distortion correction parameters set to none
  155. self.fmapmag = self.fmapphase = self.fmapgeneralelectric = \
  156. self.echodiff = self.gdcoeffs = self.dcmethod = \
  157. self.seunwarpdir = self.echospacing = None
  158. if not hasattr(self, 'fmribfcmethod'):
  159. self.fmribfcmethod = None # this parameter has not been validated
  160. # dwi parameters
  161. if 'dwi' in self.bids_data['types']:
  162. pass
  163. # @TODO handle bids formatted physio data
  164. self.physio = None
  165. # intermediate template defaults
  166. self.usestudytemplate = "false"
  167. self.studytemplate = None
  168. self.studytemplatebrain = None
  169. # @ output files @ #
  170. self.path = os.path.join(output_directory, 'files')
  171. self.logs = os.path.join(output_directory, 'logs')
  172. self.subject = self.bids_data['subject']
  173. self.session = self.bids_data['session']
  174. # Exec summ doesn't need this anymore. KJS 11/6/18
  175. #deriv_root = self.path.split('/')[:-3]
  176. #self.deriv = '/'.join(deriv_root)
  177. # @ input files @ #
  178. session_root = '/'.join(self.t1w[0].split('/')[:-2])
  179. self.unproc = os.path.join(session_root, 'func')
  180. bids_input_root = '/'.join(session_root.split('/')[:-2])
  181. self.sourcedata_root = os.path.join(bids_input_root,'sourcedata')
  182. # print command for HCP
  183. self.printcom = ''
  184. def __getitem__(self, item):
  185. # item getter
  186. return self._params()[item]
  187. def __setitem__(self, key, value):
  188. # item setter
  189. setattr(self, key, value)
  190. def _params(self):
  191. """
  192. gets all class parameters which do not start with an underscore.
  193. :return: dictionary of class parameter names and values.
  194. """
  195. params = inspect.getmembers(self, lambda a: not inspect.isroutine(a))
  196. params = {x[0]: x[1] for x in params if not x[0].startswith('_')}
  197. return params
  198. def _format(self):
  199. """
  200. formats all class parameter strings to insert environment variables.
  201. :return: None
  202. """
  203. params = self._params()
  204. # format all attributes
  205. for item, value in params.items():
  206. if isinstance(value, str):
  207. setattr(self, item, value.format(**os.environ))
  208. def get_params(self):
  209. """
  210. formats and returns instance variables.
  211. :return: dictionary of instance variable names and values
  212. """
  213. self._format()
  214. return self._params()
  215. def get_bids(self, *args):
  216. """
  217. get data from bids struct
  218. :param args: list of nested dict keys, e.g. one must provide 'fmap',
  219. 'positive' to retrieve the positive spin echo field maps.
  220. :return: bids data
  221. """
  222. val = self.bids_data
  223. for arg in args:
  224. val = val[arg]
  225. return val
  226. def set_anat_only(self, anat_only=False):
  227. if anat_only:
  228. # Assume there is no 'func' data...
  229. self.unproc = None
  230. # and no output from dcan-bold-proc.
  231. self.summary_dir = None
  232. def set_study_template(self, study_template, study_template_brain):
  233. """
  234. set template for intermediate registration steps.
  235. :param study_template: intermediate registration template head.
  236. :param study_template_brain: intermediate registration template brain.
  237. :return: None
  238. """
  239. self.usestudytemplate = "true"
  240. self.studytemplate = study_template
  241. self.studytemplatebrain = study_template_brain
  242. def set_dcmethod(self, value):
  243. if value:
  244. self.dcmethod = value
  245. class Status(object):
  246. """Status provides and updates node status information.
  247. Status information for each node is stored in the
  248. processing_logs/NodeName/status.json file. This class provides an
  249. abstraction layer between the NodeStep class and this status file.
  250. This is a write through data structure
  251. """
  252. name = 'status.json'
  253. states = {
  254. 'unchecked': 999,
  255. 'not_started': 4,
  256. 'failed': 3,
  257. 'incomplete': 2,
  258. 'succeeded': 1,
  259. }
  260. def __init__(self, folder_path):
  261. """
  262. param folder_path (str): absolute path to the Stage's bookkeeping
  263. (e.g. /output/sub/ses/processing_logs/PipelineStage)
  264. """
  265. self.file_path = os.path.join(folder_path, Status.name)
  266. defaults = {
  267. 'num_runs': 0,
  268. 'node_status': Status.states['not_started'],
  269. 'comment': '',
  270. }
  271. if not os.path.exists(self.file_path):
  272. self._write_dict(**defaults)
  273. def __getitem__(self, key):
  274. # item getter
  275. with open(self.file_path, 'r') as fd:
  276. return json.load(fd)[key]
  277. def __setitem__(self, key, value):
  278. # item setter
  279. with open(self.file_path, 'r') as fd:
  280. store = json.load(fd)
  281. store[key] = value
  282. self._write_dict(**store)
  283. return value
  284. def _write_dict(self, **contents):
  285. """
  286. write status dictionary to status.json in Stage log folder.
  287. """
  288. with open(self.file_path, 'w') as fd:
  289. json.dump(contents, fd, indent=4)
  290. def increment_run(self):
  291. # tic runs up, should be called on stage start.
  292. self['num_runs'] += 1
  293. def update_start_run(self):
  294. # reset node_status to incomplete when stage begins
  295. self.increment_run()
  296. self['node_status'] = Status.states['incomplete']
  297. def update_success(self):
  298. # update successful completion of stage
  299. self['node_status'] = Status.states['succeeded']
  300. self['comment'] = ''
  301. def update_failure(self, comment=''):
  302. """
  303. update stage failed.
  304. :param comment: optional comment describing failure.
  305. """
  306. self['node_status'] = Status.states['failed']
  307. self['comment'] = comment
  308. def update_unchecked(self, comment='no expected_outputs list for '
  309. 'completed node'):
  310. # update no configured expected outputs: ambiguous success.
  311. self['node_status'] = Status.states['unchecked']
  312. self['comment'] = comment
  313. def succeeded(self):
  314. """
  315. returns boolean if stage successful or if ambiguous (no expected
  316. outputs configured)
  317. """
  318. return self['node_status'] in (Status.states['succeeded'],
  319. Status.states['unchecked'])
  320. class Stage(object):
  321. """
  322. Base abstract class for pipeline stages.
  323. attributes:
  324. config: ParameterSettings object.
  325. kwargs: dict of attributes returned from ParamterSettings object.
  326. abstract methods which require overriding:
  327. script: script / tool / executable to run as a subprocess.
  328. args: should provide command line arguments to the script. Usually
  329. utilizes a "spec" attribute which is then formatted with the "kwargs"
  330. attribute. See PreFreeSurfer. Must be a generator for concurrency. See
  331. FMRIVolume.
  332. optional overriding:
  333. cmdline: will need overriding as generator to utilize concurrency. See
  334. FMRIVolume.
  335. setup: executes prior to executable. Recommended to wrap super().
  336. teardown: executes after executable completes. Recommended to wrap super().
  337. run: not intended for override.
  338. """
  339. # runtime settings
  340. call_active = True
  341. check_expected_outputs_active = True
  342. remove_expected_outputs_active = True
  343. ignore_expected_outputs = False
  344. def __init__(self, config):
  345. """
  346. :param config: instance of ParameterSettings
  347. """
  348. self.config = config
  349. self.kwargs = config.get_params()
  350. self.status = Status(self._get_log_dir())
  351. here = os.path.dirname(os.path.realpath(__file__))
  352. with open(os.path.join(here, 'pipeline_expected_outputs.json')) as fd:
  353. jso = json.load(fd)
  354. self.expected_outputs_spec = jso[self.__class__.__name__]
  355. def __str__(self):
  356. cmdline = self.cmdline()
  357. if inspect.isgenerator(cmdline):
  358. string = ''
  359. for cmd in cmdline:
  360. string += ' \\\n '.join(cmd.split()) + '\n'
  361. else:
  362. string = ' \\\n '.join(cmdline.split())
  363. return string
  364. @classmethod
  365. def deactivate_runtime_calls(cls):
  366. # prevent stages (all subclasses) from executing subprocesses
  367. cls.call_active = False
  368. @classmethod
  369. def deactivate_check_expected_outputs(cls):
  370. # prevent stages (all subclasses) from checking expected outputs
  371. cls.check_expected_outputs_active = False
  372. @classmethod
  373. def deactivate_remove_expected_outputs(cls):
  374. # prevent stages (all subclasses) from removing expected outputs
  375. cls.remove_expected_outputs_active = False
  376. @classmethod
  377. def activate_ignore_expected_outputs(cls):
  378. # stages will not terminate even if missing expected outputs
  379. cls.ignore_expected_outputs = True
  380. def _get_log_dir(self):
  381. """
  382. returns the subject's log directory for this stage
  383. :return: path to log directory
  384. """
  385. log_dir = os.path.join(self.kwargs['logs'], self.__class__.__name__)
  386. if not os.path.isdir(log_dir):
  387. os.makedirs(log_dir)
  388. return log_dir
  389. def check_expected_outputs(self):
  390. """
  391. checks the existence of the expected outputs for this stage.
  392. :return: True if all outputs exist, else False.
  393. """
  394. if not self.check_expected_outputs_active:
  395. return True
  396. outputs = self.get_expected_outputs()
  397. checklist = [os.path.exists(p) for p in outputs]
  398. if not all(checklist):
  399. print('missing expected outputs from %s' %
  400. self.__class__.__name__)
  401. dne_list = [f for i, f in enumerate(outputs) if not checklist[i]]
  402. for f in dne_list:
  403. print('file not found: %s' % f)
  404. if not self.ignore_expected_outputs:
  405. return False
  406. return True
  407. def get_expected_outputs(self):
  408. """
  409. formats and returns expected outputs. Must be overridden for
  410. expected outputs of concurrent executions.
  411. :return: formatted list of expected outputs
  412. """
  413. expected_outputs = [p.format(**self.kwargs)
  414. for p in self.expected_outputs_spec]
  415. expected_outputs += self.get_conditional_expected_outputs()
  416. return expected_outputs
  417. def get_conditional_expected_outputs(self):
  418. """
  419. this method includes any logic which needs to be used to determine
  420. if a file is an expected output, for example when different input
  421. modalities are utilized. Override this for individual stages to
  422. have contextually defined expected outputs.
  423. :return: list of any conditional expected outputs
  424. """
  425. return []
  426. def remove_expected_outputs(self):
  427. """
  428. removes expected outputs for this stage if they exist.
  429. :return: None
  430. """
  431. if not self.remove_expected_outputs:
  432. return
  433. outputs = self.get_expected_outputs()
  434. checklist = [os.path.isfile(p) for p in outputs]
  435. if any(checklist):
  436. print('found outputs from an earlier run of %s' %
  437. self.__class__.__name__)
  438. rm_list = [f for i, f in enumerate(outputs) if checklist[i]]
  439. for f in rm_list:
  440. print('removing %s' % f)
  441. os.remove(f)
  442. def setup(self):
  443. """
  444. runs prior to main script for this stage.
  445. :return: None
  446. """
  447. self.status.update_start_run()
  448. self.remove_expected_outputs()
  449. def teardown(self, result=0):
  450. """
  451. runs following the main script for this stage
  452. :param result: exit status or list of exit statuses for the main
  453. script.
  454. :return: None
  455. """
  456. if isinstance(result, list) and all(v == 0 for v in result):
  457. result = 0
  458. if result == 0:
  459. self.status.update_success()
  460. else:
  461. self.status.update_failure(
  462. 'stage terminated with exit code %s' % result
  463. )
  464. if not self.check_expected_outputs():
  465. self.status.update_failure(
  466. 'stage terminated, some required files were not created.'
  467. )
  468. # @TODO update status in case of missing expected outputs
  469. # finally, terminate pipeline in case of failure.
  470. if self.status['node_status'] != Status.states['succeeded']:
  471. raise Exception('error caught during stage: %s' %
  472. self.__class__.__name__)
  473. @property
  474. def args(self):
  475. """
  476. Formats the command line argument "spec", returning the full string of
  477. inputs to the main script. Must be overridden.
  478. :return: string of space separated command line arguments.
  479. """
  480. raise NotImplementedError
  481. @property
  482. def script(self):
  483. """
  484. formattable string for the path to the main script. Must be
  485. overridden.
  486. """
  487. raise NotImplementedError
  488. def cmdline(self):
  489. """
  490. returns the formatted string for the command to be called. Must
  491. be overridden as a generator object for concurrent execution.
  492. :return: command line string.
  493. """
  494. script = self.script.format(**os.environ)
  495. return ' '.join((script, self.args))
  496. def run(self, ncpus=1):
  497. """
  498. runs this stage
  499. :param ncpus: number of available cores for concurrent execution or
  500. for multithreaded computation.
  501. :return: None
  502. """
  503. self.setup()
  504. # a generator cmdline supports parallel execution
  505. if inspect.isgeneratorfunction(self.cmdline):
  506. cmdlist = []
  507. for cmd in self.cmdline():
  508. log_dir = self._get_log_dir()
  509. out_log = os.path.join(log_dir,
  510. self.kwargs['fmriname'] + '.out')
  511. err_log = os.path.join(log_dir,
  512. self.kwargs['fmriname'] + '.err')
  513. cmdlist.append((cmd, out_log, err_log))
  514. with mp.Pool(processes=ncpus) as pool:
  515. result = pool.starmap(self.call, cmdlist)
  516. else:
  517. cmd = self.cmdline()
  518. log_dir = self._get_log_dir()
  519. out_log = os.path.join(log_dir, self.__class__.__name__ + '.out')
  520. err_log = os.path.join(log_dir, self.__class__.__name__ + '.err')
  521. result = self.call(cmd, out_log, err_log, num_threads=ncpus)
  522. self.teardown(result)
  523. def call(self, *args, **kwargs):
  524. """
  525. runs command if call is active.
  526. """
  527. if self.call_active:
  528. return _call(*args, **kwargs)
  529. else:
  530. return 0 # "success"
  531. class PreFreeSurfer(Stage):
  532. script = '{HCPPIPEDIR}/PreFreeSurfer/PreFreeSurferPipeline.sh'
  533. spec = ' --path={path}' \
  534. ' --subject={subject}' \
  535. ' --t1={t1}' \
  536. ' --t2={t2}' \
  537. ' --t1template={t1template}' \
  538. ' --t1templatebrain={t1templatebrain}' \
  539. ' --t1template2mm={t1template2mm}' \
  540. ' --t2template={t2template}' \
  541. ' --t2templatebrain={t2templatebrain}' \
  542. ' --t2template2mm={t2template2mm}' \
  543. ' --templatemask={templatemask}' \
  544. ' --template2mmmask={template2mmmask}' \
  545. ' --brainsize={brainsize}' \
  546. ' --fnirtconfig={fnirtconfig}' \
  547. ' --fmapmag={fmapmag}' \
  548. ' --fmapphase={fmapphase}' \
  549. ' --fmapgeneralelectric={fmapgeneralelectric}' \
  550. ' --echodiff={echodiff}' \
  551. ' --SEPhaseNeg={sephaseneg}' \
  552. ' --SEPhasePos={sephasepos}' \
  553. ' --echospacing={echospacing}' \
  554. ' --seunwarpdir={seunwarpdir}' \
  555. ' --t1samplespacing={t1samplespacing}' \
  556. ' --t2samplespacing={t2samplespacing}' \
  557. ' --unwarpdir={unwarpdir}' \
  558. ' --gdcoeffs={gdcoeffs}' \
  559. ' --avgrdcmethod={dcmethod}' \
  560. ' --topupconfig={topupconfig}' \
  561. ' --useT2={useT2}' \
  562. ' --printcom={printcom}' \
  563. ' --useStudyTemplate={usestudytemplate}' \
  564. ' --StudyTemplate={studytemplate}' \
  565. ' --StudyTemplateBrain={studytemplatebrain}'
  566. def __init__(self, config):
  567. super(__class__, self).__init__(config)
  568. # modify t1/t2 inputs for spec
  569. self.kwargs['t1'] = '@'.join(self.kwargs.get('t1w'))
  570. self.kwargs['t2'] = '@'.join(self.kwargs.get('t2w', []))
  571. if self.kwargs['dcmethod'] == 'TOPUP':
  572. self.kwargs['sephasepos'], self.kwargs['sephaseneg'] = \
  573. self._get_intended_sefmaps()
  574. else:
  575. self.kwargs['sephasepos'] = self.kwargs['sephaseneg'] = None
  576. def _get_intended_sefmaps(self):
  577. """
  578. search for IntendedFor field from sidecar json, else give the first
  579. spin echo pair. @TODO Unfortunately, it will cause problems if someone
  580. includes the substring "T1w" in a spin echo sidecar name.
  581. :return: pair of spin echos, parallel
  582. """
  583. intended_idx = {}
  584. for direction in ['positive', 'negative']:
  585. for idx, sefm in enumerate(self.config.get_bids('fmap_metadata',
  586. direction)):
  587. intended_targets = sefm.get('IntendedFor', [])
  588. if 'T1w' in ' '.join(intended_targets):
  589. intended_idx[direction] = idx
  590. break
  591. else:
  592. if idx != 1:
  593. print('WARNING: the intended %s spin echo for anatomical '
  594. 'distortion correction is not explicitly defined in '
  595. 'the sidecar json.' % direction)
  596. intended_idx[direction] = 0
  597. return self.config.get_bids('fmap', 'positive', intended_idx[
  598. 'positive']), \
  599. self.config.get_bids('fmap', 'negative', intended_idx['negative'])
  600. @property
  601. def args(self):
  602. # None to NONE
  603. kw = {k: (v if v is not None else "NONE")
  604. for k, v in self.kwargs.items()}
  605. return self.spec.format(**kw)
  606. class FreeSurfer(Stage):
  607. script = '{HCPPIPEDIR}/FreeSurfer/FreeSurferPipeline.sh'
  608. spec = ' --subject={subject}' \
  609. ' --subjectDIR={freesurferdir}' \
  610. ' --t1={t1_restore}' \
  611. ' --t1brain={t1_restore_brain}' \
  612. ' --t2={t2_restore}' \
  613. ' --useT2={useT2}' \
  614. ' --printcom={printcom}'
  615. def __init__(self, config):
  616. super(__class__, self).__init__(config)
  617. self.kwargs['freesurferdir'] = os.path.join(
  618. self.kwargs['path'], 'T1w')
  619. self.kwargs['t1_restore'] = os.path.join(
  620. self.kwargs['freesurferdir'], 'T1w_acpc_dc_restore.nii.gz')
  621. self.kwargs['t1_restore_brain'] = os.path.join(
  622. self.kwargs['freesurferdir'], 'T1w_acpc_dc_restore_brain.nii.gz')
  623. self.kwargs['t2_restore'] = os.path.join(
  624. self.kwargs['freesurferdir'], 'T2w_acpc_dc_restore.nii.gz')
  625. @property
  626. def args(self):
  627. return self.spec.format(**self.kwargs)
  628. class PostFreeSurfer(Stage):
  629. script = '{HCPPIPEDIR}/PostFreeSurfer/PostFreeSurferPipeline.sh'
  630. spec = ' --path={path}' \
  631. ' --subject={subject}' \
  632. ' --surfatlasdir={surfatlasdir}' \
  633. ' --grayordinatesdir={grayordinatesdir}' \
  634. ' --grayordinatesres={grayordinatesres}' \
  635. ' --hiresmesh={hiresmesh}' \
  636. ' --lowresmesh={lowresmesh}' \
  637. ' --subcortgraylabels={subcortgraylabels}' \
  638. ' --freesurferlabels={freesurferlabels}' \
  639. ' --refmyelinmaps={refmyelinmaps}' \
  640. ' --regname={regname}' \
  641. ' --reference2mm={t1template2mm}' \
  642. ' --reference2mmmask={template2mmmask}' \
  643. ' --config={fnirtconfig}' \
  644. ' --useT2={useT2}' \
  645. ' --t1template={t1template}' \
  646. ' --t1templatebrain={t1templatebrain}' \
  647. ' --t1template2mm={t1template2mm}' \
  648. ' --t2template={t2template}' \
  649. ' --t2templatebrain={t2templatebrain}' \
  650. ' --t2template2mm={t2template2mm}' \
  651. ' --templatemask={templatemask}' \
  652. ' --template2mmmask={template2mmmask}' \
  653. ' --useStudyTemplate={usestudytemplate}' \
  654. ' --StudyTemplate={studytemplate}' \
  655. ' --StudyTemplateBrain={studytemplatebrain}' \
  656. ' --printcom={printcom}'
  657. def __init__(self, config):
  658. super(__class__, self).__init__(config)
  659. @property
  660. def args(self):
  661. return self.spec.format(**self.kwargs)
  662. class FMRIVolume(Stage):
  663. script = '{HCPPIPEDIR}/fMRIVolume/GenericfMRIVolumeProcessingPipeline.sh'
  664. spec = ' --path={path}' \
  665. ' --subject={subject}' \
  666. ' --fmriname={fmriname}' \
  667. ' --fmritcs={fmritcs}' \
  668. ' --fmriscout={fmriscout}' \
  669. ' --SEPhaseNeg={sephaseneg}' \
  670. ' --SEPhasePos={sephasepos}' \
  671. ' --fmapmag={fmapmag}' \
  672. ' --fmapphase={fmapphase}' \
  673. ' --fmapgeneralelectric={fmapgeneralelectric}' \
  674. ' --echospacing={echospacing}' \
  675. ' --echodiff={echodiff}' \
  676. ' --unwarpdir={seunwarpdir}' \
  677. ' --fmrires={fmrires}' \
  678. ' --dcmethod={dcmethod}' \
  679. ' --gdcoeffs={gdcoeffs}' \
  680. ' --topupconfig={topupconfig}' \
  681. ' --printcom={printcom}' \
  682. ' --biascorrection={fmribfcmethod}' \
  683. ' --mctype={mctype}' \
  684. ' --useT2={useT2}'
  685. def __init__(self, config):
  686. super(__class__, self).__init__(config)
  687. def __str__(self):
  688. string = ''
  689. for cmd in self.cmdline():
  690. string += ' \\\n '.join(cmd.split()) + '\n'
  691. return string
  692. def _get_intended_sefmaps(self):
  693. """
  694. search for IntendedFor field from sidecar json to determine
  695. appropriate field map pair, else give the first spin echo pair.
  696. :return: pair of spin echo filenames, positive then negative
  697. """
  698. intended_idx = {}
  699. for direction in ['positive', 'negative']:
  700. for idx, sefm in enumerate(self.config.get_bids('fmap_metadata',
  701. direction)):
  702. intended_targets = sefm.get('IntendedFor', [])
  703. if get_relpath(self.kwargs['fmritcs']) in ' '.join(
  704. intended_targets):
  705. intended_idx[direction] = idx
  706. break
  707. else:
  708. if idx != 0:
  709. print('WARNING: the intended %s spin echo for anatomical '
  710. 'distortion correction is not explicitly defined in '
  711. 'the sidecar json.' % direction)
  712. intended_idx[direction] = 0
  713. return self.config.get_bids('fmap', 'positive', intended_idx[
  714. 'positive']), \
  715. self.config.get_bids('fmap', 'negative',
  716. intended_idx['negative'])
  717. @property
  718. def args(self):
  719. for fmri, meta in zip(self.config.get_bids('func'),
  720. self.config.get_bids('func_metadata')):
  721. # set ts parameters
  722. self.kwargs['fmritcs'] = fmri
  723. self.kwargs['fmriname'] = get_fmriname(fmri)
  724. self.kwargs['fmriscout'] = None # not implemented
  725. if self.kwargs['dcmethod'] == 'TOPUP':
  726. self.kwargs['seunwarpdir'] = ijk_to_xyz(
  727. meta['PhaseEncodingDirection'])
  728. self.kwargs['sephasepos'], self.kwargs['sephaseneg'] = \
  729. self._get_intended_sefmaps()
  730. else:
  731. self.kwargs['sephasepos'] = self.kwargs['sephaseneg'] = None
  732. # None to NONE
  733. kw = {k: (v if v is not None else "NONE")
  734. for k, v in self.kwargs.items()}
  735. yield self.spec.format(**kw)
  736. def cmdline(self):
  737. script = self.script.format(**os.environ)
  738. for argset in self.args:
  739. yield ' '.join((script, argset))
  740. class FMRISurface(Stage):
  741. script = '{HCPPIPEDIR}/fMRISurface/GenericfMRISurfaceProcessingPipeline.sh'
  742. spec = ' --path={path}' \
  743. ' --subject={subject}' \
  744. ' --fmriname={fmriname}' \
  745. ' --lowresmesh={lowresmesh}' \
  746. ' --fmrires={fmrires}' \
  747. ' --smoothingFWHM={smoothingFWHM}' \
  748. ' --grayordinatesres={grayordinatesres}' \
  749. ' --regname={regname}'
  750. def __init__(self, config):
  751. super(__class__, self).__init__(config)
  752. def __str__(self):
  753. string = ''
  754. for cmd in self.cmdline():
  755. string += ' \\\n '.join(cmd.split()) + '\n'
  756. return string
  757. @property
  758. def args(self):
  759. for fmri in self.config.get_bids('func'):
  760. self.kwargs['fmriname'] = get_fmriname(fmri)
  761. yield self.spec.format(**self.kwargs)
  762. def cmdline(self):
  763. script = self.script.format(**os.environ)
  764. for argset in self.args:
  765. yield ' '.join((script, argset))
  766. class DCANBOLDProcessing(Stage):
  767. script = '{DCANBOLDPROCDIR}/dcan_bold_proc.py'
  768. spec = ' --subject={subject}' \
  769. ' --output-folder={path}' \
  770. ' --task={fmriname}' \
  771. ' --fd-threshold={fd_threshold}' \
  772. ' --filter-order={filter_order}' \
  773. ' --lower-bpf={lower_bpf}' \
  774. ' --upper-bpf={upper_bpf}' \
  775. ' --motion-filter-type={motion_filter_type}' \
  776. ' --physio={physio}' \
  777. ' --motion-filter-option={motion_filter_option}' \
  778. ' --motion-filter-order={motion_filter_order}' \
  779. ' --band-stop-min={band_stop_min}' \
  780. ' --band-stop-max={band_stop_max}' \
  781. ' --brain-radius={brain_radius}' \
  782. ' --skip-seconds={skip_seconds}' \
  783. ' --contiguous-frames={contiguous_frames}'
  784. def __init__(self, config):
  785. super(__class__, self).__init__(config)
  786. def set_bandstop_filter(self, lower_bound, upper_bound,
  787. filter_type='notch'):
  788. self.kwargs['motion_filter_type'] = filter_type
  789. self.kwargs['band_stop_min'] = lower_bound
  790. self.kwargs['band_stop_max'] = upper_bound
  791. def setup(self):
  792. """
  793. make ventricle and white matter masks.
  794. :return:
  795. """
  796. super(__class__, self).setup()
  797. script = self.script.format(**os.environ)
  798. args = self.spec.format(**self.kwargs)
  799. cmd = ' '.join((script, args))
  800. cmd += ' --setup'
  801. log_dir = self._get_log_dir()
  802. out_log = os.path.join(log_dir, self.__class__.__name__ + '_setup.out')
  803. err_log = os.path.join(log_dir, self.__class__.__name__ + '_setup.err')
  804. result = self.call(cmd, out_log, err_log)
  805. def teardown(self, result=0):
  806. """
  807. concatenate dtseries, parcellate, create grayplots.
  808. :param result:
  809. :return:
  810. """
  811. fmris = [get_fmriname(fmri) for fmri in self.config.get_bids('func')]
  812. fmrisets = list(set([get_taskname(fmri)
  813. for fmri in self.config.get_bids('func')]))
  814. script = self.script.format(**os.environ)
  815. args = self.spec.format(**self.kwargs)
  816. cmd = ' '.join((script, args))
  817. cmd += ' --teardown'
  818. for fmriset in fmrisets:
  819. fmrilist = sorted([fmri for fmri in fmris if fmriset in fmri])
  820. cmd += ' --tasklist ' + ','.join(fmrilist)
  821. log_dir = self._get_log_dir()
  822. out_log = os.path.join(log_dir, self.__class__.__name__ + '_teardown.out')
  823. err_log = os.path.join(log_dir, self.__class__.__name__ + '_teardown.err')
  824. result = self.call(cmd, out_log, err_log)
  825. super(__class__, self).teardown(result)
  826. @property
  827. def args(self):
  828. for fmri in self.config.get_bids('func'):
  829. self.kwargs['fmriname'] = get_fmriname(fmri)
  830. yield self.spec.format(**self.kwargs)
  831. def cmdline(self):
  832. script = self.script.format(**os.environ)
  833. for argset in self.args:
  834. yield ' '.join((script, argset))
  835. class DiffusionPreprocessing(Stage):
  836. script = '{HCPPIPEDIR}/DiffusionPreprocessing/DiffPreprocPipeline.sh'
  837. spec = ' --path={path}' \
  838. ' --subject={subject}' \
  839. ' --posData={dwi_positive}' \
  840. ' --negData={dwi_negative}' \
  841. ' --echospacing={dwi_echospacing}' \
  842. ' --PEdir={pedir}' \
  843. ' --printcom={printcom}'
  844. @property
  845. def args(self):
  846. raise NotImplemented
  847. def cmdline(self):
  848. raise NotImplemented
  849. class ExecutiveSummary(Stage):
  850. script = '{EXECSUMDIR}/ExecutiveSummary.py'
  851. spec = ' --bids-input={unproc}' \
  852. ' --output-dir={path}' \
  853. ' --participant-label={subject}' \
  854. ' --session-id={session}' \
  855. ' --atlas={t1templatebrain}' \
  856. ' --dcan-summary={summary_dir} '
  857. def __init__(self, config):
  858. super(__class__, self).__init__(config)
  859. @property
  860. def args(self):
  861. return self.spec.format(**self.kwargs)
  862. class CustomClean(Stage):
  863. script = '{CUSTOMCLEANDIR}/cleaning_script.py'
  864. spec = ' --dir={path}' \
  865. ' --json={input_json}'
  866. def __init__(self, config, input_json):
  867. super(__class__, self).__init__(config)
  868. self.kwargs['input_json'] = input_json
  869. @property
  870. def args(self):
  871. return self.spec.format(**self.kwargs)
  872. def _call(cmd, out_log, err_log, num_threads=1):
  873. env = os.environ.copy()
  874. if num_threads > 1:
  875. # set parallel environment variables
  876. env['OMP_NUM_THREADS'] = str(num_threads)
  877. env['ITK_GLOBAL_DEFAULT_NUMBER_OF_THREADS'] = str(num_threads)
  878. with open(out_log, 'w') as out, open(err_log, 'w') as err:
  879. result = subprocess.call(cmd.split(), stdout=out, stderr=err, env=env)
  880. if type(result) is list:
  881. if all(v == 0 for v in result):
  882. result = 0
  883. return result

pipelines.py at commit 0fe7f44, under BSD-3-Clause · at the source

Overview

Authors: Kirsten MP McKone1, Donovan J Roediger2, Stefanie L Sequeira3, Ellery Island4, Monica Luciana5, Mark B Fiecas4, Bryon A Mueller2, Bonnie Klimes-Dougan5, Kathryn R Cullen2
  1. University of Minnesota Institute of Child Development, USA
  2. University of Minnesota Department of Psychiatry & Behavioral Sciences, USA
  3. University of Virginia Department of Psychology, USA
  4. University of Minnesota Division of Biostatistics, USA
  5. University of Minnesota Department of Psychology, USA
Institutions: University of Minnesota (United States); University of Virginia (United States)
Journal: Developmental cognitive neuroscience, volume 81, article 101806
Dates: received 5 March 2026; accepted 27 August 2026; published online 1 September 2026; in print September 2026
Type: Research article · Language: English
License: CC BY
Identifiers: DOI 10.1016/j.dcn.2026.101806 · PMID 42691580 · PMCID PMC13571737 · OpenAlex W7204949848
Open access: gold, a free copy (OpenAlex)
Status: code verified
Categories: fMRI (modality), human (organism), developmental (subfield)
Methods: Spectral & time-frequency, Statistics, Complexity, fMRI & imaging
Keywords: Entropy, Pubertal development, Adolescence, ABCD Study, Brain development, Complexity, RsFMRI BOLD signal
Topic: Hypothalamic control of reproductive hormones (Reproductive Medicine, Medicine), according to OpenAlex
Funding: NIDA NIH HHS (U01 DA050988, U01 DA050989, U01 DA051016, U01 DA051037, U01 DA051038, U01 DA041022, U01 DA041148, U01 DA050987, U01 DA041134, U01 DA041120, U01 DA041156, U01 DA041048, U01 DA041025, U01 DA041174, U01 DA041028, U01 DA041093, U01 DA041117, U01 DA051018, U24 DA041123, U01 DA041089, U01 DA041106, U01 DA051039, U24 DA041147); National Institutes of Health (U01DA050988, U01DA051039, U01DA041089, U01DA041117, U01DA041134, U01DA041048, U01DA041174, U01DA051018, U24DA041147, U01DA041025, U01DA041106, U01DA050987, U01DA051038, U01DA041028, U01DA041148, U01DA041156, U01DA041093, U01DA041120, U01DA051016, U24DA041123, U01DA041022, U01DA050989, U01DA051037); NIMH NIH HHS (R01 MH122473, T32 MH015755)
Citations: not cited yet (Europe PMC); 67 references in the paper

Abstract

Entropy is a novel brain measure that holds important information about brain flexibility and functioning, with promise for informing brain development in adolescence, as it has been shown to change across the lifespan. However, little is known about how it changes during the critically important phase of pubertal development, which kickstarts a period of broad neural reorganization and restructuring. This proof-of-concept cross-sectional study examined associations between fMRI signal entropy and early pubertal development in a large, diverse sample of children. Data (N = 6838; 49.6% male; ages 8.92–11.08) was drawn from the first wave of the Adolescent Brain Cognitive Development study. Sample entropy was calculated on the time series of the resting-state fMRI signals for every grayordinate (i.e., cortical vertex and subcortical voxel). Parent-reported pubertal development (approximated Tanner stage) and salivary hormone levels (dehydroepiandrosterone; estradiol; testosterone) were correlated with sample entropy across the whole brain. The patterns of association between sample entropy and pubertal stage/hormone levels were inspected for males and females separately. Findings indicated pubertal development was associated with higher levels of resting state fMRI signal entropy, specifically in the occipital, parietal, and temporal lobes. Associations were apparent in females across most pubertal metrics. For males the constrained range of pubertal development may in part account for weaker associations observed. Further, adjustment for variables associated with early timing of pubertal development (socioeconomic status, body mass index) reduced the strength of puberty-entropy associations for both sexes. Longitudinal research is needed to confirm the associations between sample entropy and puberty, to evaluate whether stronger associations emerge as more males enter puberty in earnest, and to disentangle potential confounds.

Reproduced under the paper's license (CC BY), from the paper cited above.

Repository

Its files are read in the Code ↔ Paper reader above, with 2 matches between paragraphs and lines of code.

DCAN-Labs/abcd-hcp-pipeline

License: BSD-3-Clause
State: the link answers, verified on 26 September 2026
Evidence: files inventoried
Commit: 0fe7f449057b85eab9727d22a3302ce91499b86a, 16 January 2026
Languages: Python (4), Shell (2)
Size: 24 files, 6 scripts
Software Heritage: not archived
Found in: the text, “Data Statement”
Holds: README, license file, environment (Dockerfile, requirements.txt, app/requirements.txt), continuous integration, documentation
Not found: CITATION.cff, tests
Tools: FreeSurfer (2 files), FSL (1 file), HCP Pipelines (1 file), PyBIDS (1 file)
Availability: 1 check, the latest on 26 September 2026: the link answers
  • 26 September 2026: the link answers
8 files

Tracing map

Proposed by the machine: these links were found in the paper and verified at the source, without human review. The map will receive a Zenodo DOI once one of the paper's authors has validated it with their ORCID.

What the map holds:

  • 1 repository of the authors' code, each at its verified commit, with its license and how the link was found in the paper;
  • 6 scripts, each with its path and the digest of its content;
  • 2 matches between paragraphs of the paper and lines of the code (method lexical-v1);
  • neither the text of the paper nor the code itself.

Its JSON (tracing-map.json) is deposited on Zenodo with its DOI once the map is validated.

Data

No dataset and no data link were found in the paper.

Data availability

Data are publicly available at https://nda.nih.gov/abcd.

Reproduced under the paper's license (CC BY), from the paper cited above.

Versions

The history of this record: each version stored by the harvester or made by a correction of its authors or of the maintainers of its code, and what changed in its facts. The texts of the paper (its abstract, its availability statements) are not part of it; versions that changed only those are not listed.

Version 1, 27 September 2026: the first record

Recorded: type, language, journal, volume, pages, dates, 9 authors, 7 keywords, 3 funders, 66 references.

Cite

This paper

McKone, K. M., Roediger, D. J., Sequeira, S. L., Island, E., Luciana, M., Fiecas, M. B., Mueller, B. A., Klimes-Dougan, B., & Cullen, K. R. (2026). Same ages, different stages: Pubertal development in 9- and 10-year olds is associated with entropy of fMRI signals. Developmental cognitive neuroscience, 81, 101806. https://doi.org/10.1016/j.dcn.2026.101806

BibTeX

@article{mckone2026same,
author = {McKone, Kirsten MP and Roediger, Donovan J and Sequeira, Stefanie L and Island, Ellery and Luciana, Monica and Fiecas, Mark B and Mueller, Bryon A and Klimes-Dougan, Bonnie and Cullen, Kathryn R},
title = {{Same ages, different stages: Pubertal development in 9- and 10-year olds is associated with entropy of fMRI signals}},
journal = {Developmental cognitive neuroscience},
year = {2026},
month = sep,
volume = {81},
pages = {101806},
publisher = {Elsevier},
issn = {1878-9293},
doi = {10.1016/j.dcn.2026.101806},
url = {https://doi.org/10.1016/j.dcn.2026.101806},
pmid = {42691580},
pmcid = {PMC13571737}
}

RIS

TY - JOUR
AU - McKone, Kirsten MP
AU - Roediger, Donovan J
AU - Sequeira, Stefanie L
AU - Island, Ellery
AU - Luciana, Monica
AU - Fiecas, Mark B
AU - Mueller, Bryon A
AU - Klimes-Dougan, Bonnie
AU - Cullen, Kathryn R
TI - Same ages, different stages: Pubertal development in 9- and 10-year olds is associated with entropy of fMRI signals
T2 - Developmental cognitive neuroscience
J2 - Dev Cogn Neurosci
PY - 2026
DA - 2026/09/01
VL - 81
SP - 101806
SN - 1878-9293
PB - Elsevier
DO - 10.1016/j.dcn.2026.101806
UR - https://doi.org/10.1016/j.dcn.2026.101806
LA - en
ER -

CSL-JSON

{
"id": "10.1016/j.dcn.2026.101806",
"type": "article-journal",
"title": "Same ages, different stages: Pubertal development in 9- and 10-year olds is associated with entropy of fMRI signals",
"container-title": "Developmental cognitive neuroscience",
"author": [
{
"family": "McKone",
"given": "Kirsten MP"
},
{
"family": "Roediger",
"given": "Donovan J"
},
{
"family": "Sequeira",
"given": "Stefanie L"
},
{
"family": "Island",
"given": "Ellery"
},
{
"family": "Luciana",
"given": "Monica"
},
{
"family": "Fiecas",
"given": "Mark B"
},
{
"family": "Mueller",
"given": "Bryon A"
},
{
"family": "Klimes-Dougan",
"given": "Bonnie"
},
{
"family": "Cullen",
"given": "Kathryn R"
}
],
"container-title-short": "Dev Cogn Neurosci",
"volume": "81",
"page": "101806",
"DOI": "10.1016/j.dcn.2026.101806",
"PMID": "42691580",
"PMCID": "PMC13571737",
"ISSN": "1878-9293",
"publisher": "Elsevier",
"URL": "https://doi.org/10.1016/j.dcn.2026.101806",
"language": "en",
"issued": {
"date-parts": [
[
2026,
9,
1
]
]
}
}

The tracing map gets a citation of its own once an author has validated it and it has a DOI.

Similar papers

The papers with a page that share the most with this one: the tools found in their code, their categories, datasets, cited references and authors, the rarest counting most.

[1] doi:10.1038/s41467-026-71270-w [code]
Spatiotemporal dynamics of the human cortical functional hierarchy across the lifespan.
Journal: Nature communications
In common: HCP Pipelines, PyBIDS, FreeSurfer, 1 other tool, developmental, fMRI, 1 reference
[2] doi:10.1016/j.dcn.2026.101738 [code]
Timing and tempo of puberty and neurodevelopment following adversity: A registered report.
Journal: Developmental cognitive neuroscience
In common: developmental, 7 references
[3] doi:10.1016/j.neuroimage.2026.122085 [code]
Lifespan trajectories of the brain's functional complexity characterized by multiscale sample entropy.
Journal: NeuroImage
In common: fMRI, 5 references
[4] doi:10.1162/imag.a.1270
Disentangling the unique associations of age, pubertal stage, and pubertal hormones with white matter microstructure in childhood and adolescence.
Journal: Imaging neuroscience (Cambridge, Mass.)
In common: developmental, 5 references
[5] doi:10.1016/j.dcn.2026.101737 [code]
Being praised and criticized in adolescents and adults: Age-related changes in neural responses to social evaluations.
Journal: Developmental cognitive neuroscience
In common: developmental, fMRI, 4 references
[6] doi:10.1162/imag.a.1262 [code]
Frame-wise multi-echo distortion correction for superior functional MRI.
Journal: Imaging neuroscience (Cambridge, Mass.)
In common: PyBIDS, FreeSurfer, FSL, fMRI, 1 reference
[7] doi:10.1162/imag.a.1354 [code]
Development of a 24-channel 3T phased-array coil for fMRI in awake monkeys: Mitigating spatiotemporal artifacts in ferumoxytol-weighted functional connectivity estimation.
Journal: Imaging neuroscience (Cambridge, Mass.)
In common: HCP Pipelines, FreeSurfer, FSL, fMRI
[8] doi:10.1016/j.neuron.2026.04.011 [code]
Precision fMRI reveals densely interdigitated network patches with conserved motifs in the lateral prefrontal cortex.
Journal: Neuron
In common: FreeSurfer, FSL, fMRI, 2 references
[9] doi:10.1038/s41467-026-71719-y [code]
Brain functional-structural gradient coupling reflects development, behavior and genetic influences.
Journal: Nature communications
In common: FreeSurfer, FSL, developmental, 2 references
[10] doi:10.1038/s41467-026-73072-6 [code]
Mapping the spatiotemporal continuum of structural connectivity development across the human connectome in youth.
Journal: Nature communications
In common: FreeSurfer, developmental, 3 references

Contribute

The authors of this paper can claim it, correct its record and validate its tracing map, and the maintainers of its code (its owner, or a public member of its organization) correct what it says of their repository; anyone signed in can ask for its removal. Every request goes to OSCR's own machine, which answers it; your account page follows them.

Sign in with ORCID to claim this paper as one of its authors, correct its record or validate its tracing map: when the paper's metadata lists your ORCID iD, you are recognized at once. Maintainers of its code: sign in with GitHub, then claim the repository on your account page.

Request its removal

To ask OSCR to remove this record, the copies of its authors' scripts or its tracing map, use the removal request page: signed in, you say who you are, what to remove and why, then review and confirm the request. Published rules decide every request (how).

Discussion, reproductions, activity

Discussion: questions and error reports about this paper and its code, from signed-in readers and its authors. It opens with sign-in.

Reproductions: reports from readers who ran the authors' code: what they reproduced, with which environment, commit and data. It opens with sign-in.

Activity: what happens around this paper: new versions of its record, its map's validation, discussions and reproductions. It opens with sign-in.