Skip to content

Commit

Permalink
RF: Reorgnaize the fitlins output naming structure to use node name a…
Browse files Browse the repository at this point in the history
…s the base directory
  • Loading branch information
shashankbansal6 committed Mar 31, 2022
1 parent bb95b1a commit bfe77b7
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 36 deletions.
4 changes: 2 additions & 2 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ repos:
- id: end-of-file-fixer
- id: trailing-whitespace
- repo: https://github.com/psf/black
rev: 21.12b0
rev: 22.3.0
hooks:
- id: black
exclude: ^(fitlins/_version.py|versioneer.py)
Expand All @@ -18,7 +18,7 @@ repos:
name: Sort python imports (isort)
args: ["--profile", "black", "--filter-files"]
- repo: https://github.com/asottile/pyupgrade
rev: v2.31.0
rev: v2.31.1
hooks:
- id: pyupgrade
exclude: ^(fitlins/_version.py|versioneer.py)
4 changes: 4 additions & 0 deletions fitlins/data/fitlins.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@

"name": "name",
"pattern": "[_/\\\\]name-([a-zA-Z0-9]+)"
},
{
"name": "node",
"pattern": "[_/\\\\]node-([a-zA-Z0-9]+)"
}
]
}
24 changes: 11 additions & 13 deletions fitlins/interfaces/bids.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,26 @@
import os
import re
import shutil

import numpy as np
import nibabel as nb

from gzip import GzipFile
from itertools import chain
from pathlib import Path
from gzip import GzipFile

import nibabel as nb
import numpy as np
from nipype import logging
from nipype.utils.filemanip import copyfile
from nipype.interfaces.base import (
BaseInterfaceInputSpec,
TraitedSpec,
SimpleInterface,
Directory,
File,
InputMultiPath,
OutputMultiPath,
File,
Directory,
traits,
SimpleInterface,
TraitedSpec,
isdefined,
traits,
)
from nipype.interfaces.io import IOBase
from nipype.utils.filemanip import copyfile

from ..utils import snake_to_camel, to_alphanum

Expand Down Expand Up @@ -238,8 +236,8 @@ class LoadBIDSModel(SimpleInterface):
output_spec = LoadBIDSModelOutputSpec

def _run_interface(self, runtime):
from bids.modeling import BIDSStatsModelsGraph
from bids.layout import BIDSLayout
from bids.modeling import BIDSStatsModelsGraph

layout = BIDSLayout.load(database_path=self.inputs.database_path)
selectors = self.inputs.selectors
Expand Down Expand Up @@ -480,7 +478,7 @@ def _list_outputs(self):
# format (eg: gain.Range, gain.EqualIndifference).
# This prevents issues when creating/searching files for the report
for k, v in ents.items():
if k in ("name", "contrast", "stat"):
if k in ("node", "name", "contrast", "stat"):
ents.update({k: to_alphanum(str(v))})

out_fname = os.path.join(
Expand Down
70 changes: 49 additions & 21 deletions fitlins/workflows/base.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import warnings

from collections import OrderedDict
from pathlib import Path

Expand All @@ -21,17 +20,23 @@ def init_fitlins_wf(
base_dir=None,
name='fitlins_wf',
):
from nipype.pipeline import engine as pe
from nipype.interfaces import utility as niu
from ..interfaces.bids import ModelSpecLoader, LoadBIDSModel, BIDSSelect, BIDSDataSink
from nipype.pipeline import engine as pe

from ..interfaces.bids import (
BIDSDataSink,
BIDSSelect,
LoadBIDSModel,
ModelSpecLoader,
)
from ..interfaces.nistats import DesignMatrix, SecondLevelModel
from ..interfaces.utils import CollateWithMetadata, MergeAll
from ..interfaces.visualizations import (
DesignPlot,
DesignCorrelationPlot,
ContrastMatrixPlot,
DesignCorrelationPlot,
DesignPlot,
GlassBrainPlot,
)
from ..interfaces.utils import MergeAll, CollateWithMetadata
from ..utils import snake_to_camel

if estimator == 'afni':
Expand Down Expand Up @@ -121,6 +126,7 @@ def init_fitlins_wf(

def _deindex(tsv):
from pathlib import Path

import pandas as pd

out_tsv = str(Path.cwd() / Path(tsv).name)
Expand All @@ -133,33 +139,33 @@ def _deindex(tsv):

# Set up common patterns
image_pattern = (
"reports/[sub-{subject}/][ses-{session}/]figures/[run-{run}/]"
"reports/[node-{node}/][sub-{subject}/][ses-{session}/]figures/[run-{run}/]"
"[level-{level}_][name-{name}_][sub-{subject}_][ses-{session}_][task-{task}_]"
"[acq-{acquisition}_][rec-{reconstruction}_][run-{run}_][echo-{echo}_]"
"{suffix<design|corr|contrasts>}{extension<.svg>|.svg}"
)

contrast_plot_pattern = (
"reports/[sub-{subject}/][ses-{session}/]figures/[run-{run}/]"
"reports/[node-{node}/][sub-{subject}/][ses-{session}/]figures/[run-{run}/]"
"[level-{level}_][name-{name}_][sub-{subject}_][ses-{session}_][task-{task}_]"
"[acq-{acquisition}_][rec-{reconstruction}_][run-{run}_][echo-{echo}_][space-{space}_]"
"contrast-{contrast}_stat-{stat<effect|variance|z|p|t|F|Meta>}_ortho{extension<.png>|.png}"
)
design_matrix_pattern = (
"[sub-{subject}/][ses-{session}/]"
"[node-{node}/][sub-{subject}/][ses-{session}/]"
"[level-{level}_][name-{name}_][sub-{subject}_][ses-{session}_][task-{task}_]"
"[acq-{acquisition}_][rec-{reconstruction}_][run-{run}_][echo-{echo}_]"
"{suffix<design>}{extension<.tsv>|.tsv}"
)
contrast_pattern = (
"[sub-{subject}/][ses-{session}/]"
"[node-{node}/][sub-{subject}/][ses-{session}/]"
"[level-{level}_][name-{name}_][sub-{subject}_][ses-{session}_][task-{task}_]"
"[acq-{acquisition}_][rec-{reconstruction}_][run-{run}_][echo-{echo}_][space-{space}_]"
"contrast-{contrast}_stat-{stat<effect|variance|z|p|t|F|Meta>}_"
"statmap{extension<.nii.gz|.dscalar.nii>}"
)
model_map_pattern = (
"[sub-{subject}/][ses-{session}/]"
"[node-{node}/][sub-{subject}/][ses-{session}/]"
"[level-{level}_][name-{name}_][sub-{subject}_][ses-{session}_][task-{task}_]"
"[acq-{acquisition}_][rec-{reconstruction}_][run-{run}_][echo-{echo}_][space-{space}_]"
"stat-{stat<rSquare|logLikelihood|tsnr|errorts|a|b|lam|LjungBox|residtsnr|"
Expand All @@ -171,14 +177,20 @@ def _deindex(tsv):
# saved as individual derivative files
#

n_run = [
snake_to_camel(node.name.replace('-', '_'))
for node in graph.nodes.values()
if node.level == 'run'
][0]
reportlet_dir = Path(base_dir) / 'reportlets' / 'fitlins'
reportlet_dir.mkdir(parents=True, exist_ok=True)
snippet_pattern = (
'[sub-{subject}/][ses-{session}/][level-{level}_][sub-{subject}_]'
'[node-{node}/][sub-{subject}/][ses-{session}/][level-{level}_][sub-{subject}_]'
'[ses-{session}_][task-{task}_][run-{run}_]snippet.html'
)
ds_model_warnings = pe.MapNode(
BIDSDataSink(base_directory=str(reportlet_dir), path_patterns=snippet_pattern),
fixed_entities={'node': n_run},
iterfield=['entities', 'in_file'],
run_without_submitting=True,
name='ds_model_warning',
Expand All @@ -201,7 +213,7 @@ def _deindex(tsv):
ds_design = pe.MapNode(
BIDSDataSink(
base_directory=out_dir,
fixed_entities={"level": "run", 'suffix': 'design'},
fixed_entities={"level": "run", 'suffix': 'design', 'node': n_run},
path_patterns=image_pattern,
),
iterfield=['entities', 'in_file'],
Expand All @@ -212,7 +224,7 @@ def _deindex(tsv):
ds_design_matrix = pe.MapNode(
BIDSDataSink(
base_directory=out_dir,
fixed_entities={"level": "run", 'suffix': 'design'},
fixed_entities={"level": "run", 'suffix': 'design', 'node': n_run},
path_patterns=design_matrix_pattern,
),
iterfield=['entities', 'in_file'],
Expand All @@ -223,7 +235,7 @@ def _deindex(tsv):
ds_corr = pe.MapNode(
BIDSDataSink(
base_directory=out_dir,
fixed_entities={"level": "run", 'suffix': 'corr'},
fixed_entities={"level": "run", 'suffix': 'corr', 'node': n_run},
path_patterns=image_pattern,
),
iterfield=['entities', 'in_file'],
Expand All @@ -234,7 +246,7 @@ def _deindex(tsv):
ds_run_contrasts = pe.MapNode(
BIDSDataSink(
base_directory=out_dir,
fixed_entities={"level": "run", 'suffix': 'contrasts'},
fixed_entities={"level": "run", 'suffix': 'contrasts', 'node': n_run},
path_patterns=image_pattern,
),
iterfield=['entities', 'in_file'],
Expand Down Expand Up @@ -333,20 +345,32 @@ def _select_specs(all_specs, name):
)

ds_contrast_maps = pe.Node(
BIDSDataSink(base_directory=out_dir, path_patterns=contrast_pattern),
BIDSDataSink(
base_directory=out_dir,
fixed_entities={'node': name},
path_patterns=contrast_pattern,
),
run_without_submitting=True,
name=f'ds_{name}_contrast_maps',
)

ds_contrast_plots = pe.Node(
BIDSDataSink(base_directory=out_dir, path_patterns=contrast_plot_pattern),
BIDSDataSink(
base_directory=out_dir,
fixed_entities={'node': name},
path_patterns=contrast_plot_pattern,
),
run_without_submitting=True,
name=f'ds_{name}_contrast_plots',
)

if level == 'run':
ds_model_maps = pe.Node(
BIDSDataSink(base_directory=out_dir, path_patterns=model_map_pattern),
BIDSDataSink(
base_directory=out_dir,
fixed_entities={'node': name},
path_patterns=model_map_pattern,
),
run_without_submitting=True,
name=f'ds_{name}_model_maps',
)
Expand Down Expand Up @@ -408,9 +432,13 @@ def _select_specs(all_specs, name):
model.inputs.smoothing_type = smoothing_type
else:
if smoothing_type == "isoblurto":
from nipype.interfaces.afni.preprocess import BlurToFWHM as smooth_interface
from nipype.interfaces.afni.preprocess import (
BlurToFWHM as smooth_interface,
)
elif smoothing_type == "iso":
from nipype.interfaces.afni.preprocess import BlurInMask as smooth_interface
from nipype.interfaces.afni.preprocess import (
BlurInMask as smooth_interface,
)
smooth = pe.MapNode(
smooth_interface(), iterfield=["in_file", "mask"], name="smooth"
)
Expand Down

0 comments on commit bfe77b7

Please sign in to comment.