Multi-Echo Denoising with tedana

Multi-Echo Denoising with tedana#

In this analysis tutorial, we will use tedana [DuPre et al., 2021] to perform multi-echo denoising.

Specifically, we will use tedana.workflows.tedana_workflow().

import json
import os
from glob import glob
from pprint import pprint

import pandas as pd
from IPython.display import HTML, display
from repo2data.repo2data import Repo2Data
from tedana import workflows

# Install the data if running locally, or point to cached data if running on neurolibre
DATA_REQ_FILE = os.path.join("../binder/data_requirement.json")

# Download data
repo2data = Repo2Data(DATA_REQ_FILE)
data_path = repo2data.install()
data_path = os.path.abspath(data_path[0])
---- repo2data starting ----
/opt/hostedtoolcache/Python/3.10.14/x64/lib/python3.10/site-packages/repo2data
Config from file :
../binder/data_requirement.json
Destination:
./../data/multi-echo-data-analysis

Info : ./../data/multi-echo-data-analysis already downloaded
func_dir = os.path.join(data_path, "func/")
data_files = [
    os.path.join(
        func_dir,
        "sub-04570_task-rest_echo-1_space-scanner_desc-partialPreproc_bold.nii.gz",
    ),
    os.path.join(
        func_dir,
        "sub-04570_task-rest_echo-2_space-scanner_desc-partialPreproc_bold.nii.gz",
    ),
    os.path.join(
        func_dir,
        "sub-04570_task-rest_echo-3_space-scanner_desc-partialPreproc_bold.nii.gz",
    ),
    os.path.join(
        func_dir,
        "sub-04570_task-rest_echo-4_space-scanner_desc-partialPreproc_bold.nii.gz",
    ),
]
echo_times = [12.0, 28.0, 44.0, 60.0]
mask_file = os.path.join(
    func_dir, "sub-04570_task-rest_space-scanner_desc-brain_mask.nii.gz"
)
confounds_file = os.path.join(
    func_dir, "sub-04570_task-rest_desc-confounds_timeseries.tsv"
)

out_dir = os.path.join(data_path, "tedana")
workflows.tedana_workflow(
    data_files,
    echo_times,
    out_dir=out_dir,
    mask=mask_file,
    prefix="sub-04570_task-rest_space-scanner",
    fittype="curvefit",
    tedpca="mdl",
    verbose=True,
    gscontrol=["mir"],
)
Hide code cell output
INFO     tedana:tedana_workflow:488 Using output directory: /home/runner/work/multi-echo-data-analysis/multi-echo-data-analysis/data/multi-echo-data-analysis/tedana
INFO     tedana:tedana_workflow:506 Initializing and validating component selection tree
WARNING  component_selector:validate_tree:127 Decision tree includes fields that are not used or logged {'_comment'}
INFO     component_selector:__init__:250 Performing component selection with tedana_orig_decision_tree
INFO     component_selector:__init__:251 Very similar to the decision tree designed by Prantik Kundu
INFO     tedana:tedana_workflow:509 Loading input data: ['/home/runner/work/multi-echo-data-analysis/multi-echo-data-analysis/data/multi-echo-data-analysis/func/sub-04570_task-rest_echo-1_space-scanner_desc-partialPreproc_bold.nii.gz', '/home/runner/work/multi-echo-data-analysis/multi-echo-data-analysis/data/multi-echo-data-analysis/func/sub-04570_task-rest_echo-2_space-scanner_desc-partialPreproc_bold.nii.gz', '/home/runner/work/multi-echo-data-analysis/multi-echo-data-analysis/data/multi-echo-data-analysis/func/sub-04570_task-rest_echo-3_space-scanner_desc-partialPreproc_bold.nii.gz', '/home/runner/work/multi-echo-data-analysis/multi-echo-data-analysis/data/multi-echo-data-analysis/func/sub-04570_task-rest_echo-4_space-scanner_desc-partialPreproc_bold.nii.gz']
INFO     io:__init__:155 Generating figures directory: /home/runner/work/multi-echo-data-analysis/multi-echo-data-analysis/data/multi-echo-data-analysis/tedana/figures
INFO     tedana:tedana_workflow:572 Using user-defined mask
INFO     tedana:tedana_workflow:620 Computing T2* map
INFO     combine:make_optcom:192 Optimally combining data with voxel-wise T2* estimates
INFO     tedana:tedana_workflow:645 Writing optimally combined data set: /home/runner/work/multi-echo-data-analysis/multi-echo-data-analysis/data/multi-echo-data-analysis/tedana/sub-04570_task-rest_space-scanner_desc-optcom_bold.nii.gz
INFO     pca:tedpca:203 Computing PCA of optimally combined multi-echo data with selection criteria: mdl
INFO     pca:tedpca:243 Optimal number of components based on different criteria:
INFO     pca:tedpca:244 AIC: 81 | KIC: 71 | MDL: 46 | 90% varexp: 142 | 95% varexp: 187
INFO     pca:tedpca:249 Explained variance based on different criteria:
INFO     pca:tedpca:250 AIC: 0.821% | KIC: 0.806% | MDL: 0.762% | 90% varexp: 0.9% | 95% varexp: 0.95%
INFO     pca:tedpca:267 Plotting maPCA optimization curves
INFO     collect:generate_metrics:121 Calculating weight maps
INFO     collect:generate_metrics:130 Calculating parameter estimate maps for optimally combined data
INFO     collect:generate_metrics:143 Calculating z-statistic maps
INFO     collect:generate_metrics:153 Calculating F-statistic maps
INFO     collect:generate_metrics:173 Thresholding z-statistic maps
INFO     collect:generate_metrics:180 Calculating T2* F-statistic maps
INFO     collect:generate_metrics:187 Calculating S0 F-statistic maps
INFO     collect:generate_metrics:195 Counting significant voxels in T2* F-statistic maps
INFO     collect:generate_metrics:201 Counting significant voxels in S0 F-statistic maps
INFO     collect:generate_metrics:208 Thresholding optimal combination beta maps to match T2* F-statistic maps
INFO     collect:generate_metrics:214 Thresholding optimal combination beta maps to match S0 F-statistic maps
INFO     collect:generate_metrics:221 Calculating kappa and rho
INFO     collect:generate_metrics:230 Calculating variance explained
INFO     collect:generate_metrics:236 Calculating normalized variance explained
INFO     collect:generate_metrics:243 Calculating DSI between thresholded T2* F-statistic and optimal combination beta maps
INFO     collect:generate_metrics:254 Calculating DSI between thresholded S0 F-statistic and optimal combination beta maps
INFO     collect:generate_metrics:265 Calculating signal-noise t-statistics
INFO     collect:generate_metrics:303 Counting significant noise voxels from z-statistic maps
INFO     collect:generate_metrics:314 Calculating decision table score
INFO     pca:tedpca:397 Selected 46 components with 76.18% normalized variance explained using mdl dimensionality estimate
/opt/hostedtoolcache/Python/3.10.14/x64/lib/python3.10/site-packages/tedana/io.py:346: FutureWarning: Downcasting behavior in `replace` is deprecated and will be removed in a future version. To retain the old behavior, explicitly call `result.infer_objects(copy=False)`. To opt-in to the future behavior, set `pd.set_option('future.no_silent_downcasting', True)`
  deblanked = data.replace("", np.nan)
INFO     ica:tedica:80 ICA with random seed 42 converged in 91 iterations
INFO     collect:generate_metrics:121 Calculating weight maps
INFO     collect:generate_metrics:130 Calculating parameter estimate maps for optimally combined data
INFO     collect:generate_metrics:143 Calculating z-statistic maps
INFO     collect:generate_metrics:153 Calculating F-statistic maps
INFO     collect:generate_metrics:173 Thresholding z-statistic maps
INFO     collect:generate_metrics:180 Calculating T2* F-statistic maps
INFO     collect:generate_metrics:187 Calculating S0 F-statistic maps
INFO     collect:generate_metrics:195 Counting significant voxels in T2* F-statistic maps
INFO     collect:generate_metrics:201 Counting significant voxels in S0 F-statistic maps
INFO     collect:generate_metrics:208 Thresholding optimal combination beta maps to match T2* F-statistic maps
INFO     collect:generate_metrics:214 Thresholding optimal combination beta maps to match S0 F-statistic maps
INFO     collect:generate_metrics:221 Calculating kappa and rho
INFO     collect:generate_metrics:230 Calculating variance explained
INFO     collect:generate_metrics:236 Calculating normalized variance explained
INFO     collect:generate_metrics:243 Calculating DSI between thresholded T2* F-statistic and optimal combination beta maps
INFO     collect:generate_metrics:254 Calculating DSI between thresholded S0 F-statistic and optimal combination beta maps
INFO     collect:generate_metrics:265 Calculating signal-noise t-statistics
INFO     collect:generate_metrics:303 Counting significant noise voxels from z-statistic maps
INFO     collect:generate_metrics:314 Calculating decision table score
INFO     tedana:tedana_workflow:694 Selecting components from ICA results
INFO     tedica:automatic_selection:55 Performing ICA component selection
INFO     selection_nodes:manual_classify:104 Step 0: manual_classify: Set all to unclassified 
INFO     selection_utils:log_decision_tree_step:406 Step 0: manual_classify applied to 46 components. 46 True -> unclassified. 0 False -> nochange.
INFO     selection_nodes:manual_classify:136 Step 0: manual_classify component classification tags are cleared
INFO     selection_utils:log_classification_counts:451 Step 0: Total component classifications: 46 unclassified
INFO     selection_nodes:dec_left_op_right:389 Step 1: left_op_right: rejected if rho>kappa, else nochange
INFO     selection_utils:log_decision_tree_step:406 Step 1: left_op_right applied to 46 components. 18 True -> rejected. 28 False -> nochange.
INFO     selection_utils:log_classification_counts:451 Step 1: Total component classifications: 18 rejected, 28 unclassified
INFO     selection_nodes:dec_left_op_right:389 Step 2: left_op_right: rejected if ['countsigFS0>countsigFT2 & countsigFT2>0'], else nochange
INFO     selection_utils:log_decision_tree_step:406 Step 2: left_op_right applied to 46 components. 19 True -> rejected. 27 False -> nochange.
INFO     selection_utils:log_classification_counts:451 Step 2: Total component classifications: 22 rejected, 24 unclassified
INFO     selection_nodes:calc_median:653 Step 3: calc_median: Median(median_varex)
INFO     selection_utils:log_decision_tree_step:418 Step 3: calc_median calculated: median_varex=0.5449334485072186
INFO     selection_utils:log_classification_counts:451 Step 3: Total component classifications: 22 rejected, 24 unclassified
INFO     selection_nodes:dec_left_op_right:389 Step 4: left_op_right: rejected if ['dice_FS0>dice_FT2 & variance explained>0.54'], else nochange
INFO     selection_utils:log_decision_tree_step:406 Step 4: left_op_right applied to 46 components. 6 True -> rejected. 40 False -> nochange.
INFO     selection_utils:log_classification_counts:451 Step 4: Total component classifications: 22 rejected, 24 unclassified
INFO     selection_nodes:dec_left_op_right:389 Step 5: left_op_right: rejected if ['0>signal-noise_t & variance explained>0.54'], else nochange
INFO     selection_utils:log_decision_tree_step:406 Step 5: left_op_right applied to 46 components. 9 True -> rejected. 37 False -> nochange.
INFO     selection_utils:log_classification_counts:451 Step 5: Total component classifications: 26 rejected, 20 unclassified
INFO     selection_nodes:calc_kappa_elbow:757 Step 6: calc_kappa_elbow: Calc Kappa Elbow
INFO     selection_utils:kappa_elbow_kundu:621 Calculating kappa elbow based on min of all and nonsig components.
INFO     selection_utils:log_decision_tree_step:418 Step 6: calc_kappa_elbow calculated: kappa_elbow_kundu=21.277964952355223, kappa_allcomps_elbow=40.1214389679082, kappa_nonsig_elbow=21.277964952355223, varex_upper_p=0.7802353000706743
INFO     selection_utils:log_classification_counts:451 Step 6: Total component classifications: 26 rejected, 20 unclassified
INFO     selection_nodes:dec_reclassify_high_var_comps:1120 Step 7: reclassify_high_var_comps: Change unclassified to unclass_highvar for the top couple of components with the highest jumps in variance
INFO     selection_utils:log_decision_tree_step:406 Step 7: reclassify_high_var_comps applied to 20 components. 2 True -> unclass_highvar. 18 False -> nochange.
INFO     selection_utils:log_classification_counts:451 Step 7: Total component classifications: 26 rejected, 2 unclass_highvar, 18 unclassified
INFO     selection_nodes:calc_rho_elbow:882 Step 8: calc_rho_elbow: Calc Rho Elbow
INFO     selection_utils:log_decision_tree_step:418 Step 8: calc_rho_elbow calculated: rho_elbow_kundu=17.93932546658279, rho_allcomps_elbow=27.779814570572192, rho_unclassified_elbow=15.910197343162249, elbow_f05=10.127964486013928
INFO     selection_utils:log_classification_counts:451 Step 8: Total component classifications: 26 rejected, 2 unclass_highvar, 18 unclassified
INFO     selection_nodes:dec_left_op_right:389 Step 9: left_op_right: provisionalaccept if kappa>=21.28, else nochange
INFO     selection_utils:log_decision_tree_step:406 Step 9: left_op_right applied to 18 components. 12 True -> provisionalaccept. 6 False -> nochange.
INFO     selection_utils:log_classification_counts:451 Step 9: Total component classifications: 12 provisionalaccept, 26 rejected, 2 unclass_highvar, 6 unclassified
INFO     selection_nodes:dec_left_op_right:389 Step 10: left_op_right: unclassified if rho>17.94, else nochange
INFO     selection_utils:log_decision_tree_step:406 Step 10: left_op_right applied to 12 components. 3 True -> unclassified. 9 False -> nochange.
INFO     selection_utils:log_classification_counts:451 Step 10: Total component classifications: 9 provisionalaccept, 26 rejected, 2 unclass_highvar, 9 unclassified
INFO     selection_nodes:dec_classification_doesnt_exist:1009 Step 11: classification_doesnt_exist: Change ['provisionalaccept', 'unclassified', 'unclass_highvar'] to accepted if less than 2 components with provisionalaccept exist
INFO     selection_nodes:dec_classification_doesnt_exist:1011 Step 11: classification_doesnt_exist If nothing is provisionally accepted by this point, then rerun ICA & selection. If max iterations of rerunning done, then accept everything not already rejected
INFO     selection_utils:log_decision_tree_step:406 Step 11: classification_doesnt_exist applied to 20 components. None True -> 0. None False -> 20.
INFO     selection_utils:log_classification_counts:451 Step 11: Total component classifications: 9 provisionalaccept, 26 rejected, 2 unclass_highvar, 9 unclassified
INFO     selection_nodes:calc_varex_thresh:1308 Step 12: calc_varex_thresh: Calc varex_upper_thresh, 90th percentile threshold
INFO     selection_utils:log_decision_tree_step:418 Step 12: calc_varex_thresh calculated: varex_upper_thresh=0.8908095307208492, upper_perc=90
INFO     selection_utils:log_classification_counts:451 Step 12: Total component classifications: 9 provisionalaccept, 26 rejected, 2 unclass_highvar, 9 unclassified
INFO     selection_nodes:calc_varex_thresh:1308 Step 13: calc_varex_thresh: Calc varex_lower_thresh, 25th percentile threshold
INFO     selection_utils:log_decision_tree_step:418 Step 13: calc_varex_thresh calculated: varex_lower_thresh=0.32109341064129754, lower_perc=25
INFO     selection_utils:log_classification_counts:451 Step 13: Total component classifications: 9 provisionalaccept, 26 rejected, 2 unclass_highvar, 9 unclassified
INFO     selection_utils:get_extend_factor:798 extend_factor=2.0, based on number of fMRI volumes
INFO     selection_utils:log_decision_tree_step:418 Step 14: calc_extend_factor calculated: extend_factor=2.0
INFO     selection_utils:log_classification_counts:451 Step 14: Total component classifications: 9 provisionalaccept, 26 rejected, 2 unclass_highvar, 9 unclassified
INFO     selection_utils:log_decision_tree_step:418 Step 15: calc_max_good_meanmetricrank calculated: max_good_meanmetricrank=18.0
INFO     selection_utils:log_classification_counts:451 Step 15: Total component classifications: 9 provisionalaccept, 26 rejected, 2 unclass_highvar, 9 unclassified
INFO     selection_utils:log_decision_tree_step:418 Step 16: calc_varex_kappa_ratio calculated: kappa_rate=75.59581211806685
INFO     selection_utils:log_classification_counts:451 Step 16: Total component classifications: 9 provisionalaccept, 26 rejected, 2 unclass_highvar, 9 unclassified
INFO     selection_nodes:dec_left_op_right:389 Step 17: left_op_right: rejected if ['d_table_score>18.0 & variance explained>2.0*0.89'], else nochange
INFO     selection_nodes:dec_left_op_right:391 Step 17: left_op_right If variance and d_table_scores are high, then reject
INFO     selection_utils:comptable_classification_changer:277 Step 17: No components fit criterion True to change classification
INFO     selection_utils:log_decision_tree_step:406 Step 17: left_op_right applied to 20 components. 0 True -> rejected. 20 False -> nochange.
INFO     selection_utils:log_classification_counts:451 Step 17: Total component classifications: 9 provisionalaccept, 26 rejected, 2 unclass_highvar, 9 unclassified
INFO     selection_nodes:dec_left_op_right:389 Step 18: left_op_right: accepted if ['d_table_score>18.0 & variance explained<=0.32 & kappa<=21.28'], else nochange
INFO     selection_nodes:dec_left_op_right:391 Step 18: left_op_right If low variance, accept even if bad kappa & d_table_scores
INFO     selection_utils:log_decision_tree_step:406 Step 18: left_op_right applied to 20 components. 5 True -> accepted. 15 False -> nochange.
INFO     selection_utils:log_classification_counts:451 Step 18: Total component classifications: 5 accepted, 9 provisionalaccept, 26 rejected, 2 unclass_highvar, 4 unclassified
INFO     selection_nodes:dec_classification_doesnt_exist:1009 Step 19: classification_doesnt_exist: Change ['provisionalaccept', 'unclassified', 'unclass_highvar'] to accepted if ['unclassified', 'unclass_highvar'] doesn't exist
INFO     selection_nodes:dec_classification_doesnt_exist:1011 Step 19: classification_doesnt_exist If nothing left is unclassified, then accept all
INFO     selection_utils:log_decision_tree_step:406 Step 19: classification_doesnt_exist applied to 15 components. None True -> 0. None False -> 15.
INFO     selection_utils:log_classification_counts:451 Step 19: Total component classifications: 5 accepted, 9 provisionalaccept, 26 rejected, 2 unclass_highvar, 4 unclassified
INFO     selection_nodes:calc_revised_meanmetricrank_guesses:1768 Step 20: calc_revised_meanmetricrank_guesses: Calc revised d_table_score & num accepted component guesses
INFO     selection_utils:log_decision_tree_step:418 Step 20: calc_revised_meanmetricrank_guesses calculated: num_acc_guess=11, conservative_guess=5.5, restrict_factor=2
INFO     selection_utils:log_classification_counts:451 Step 20: Total component classifications: 5 accepted, 9 provisionalaccept, 26 rejected, 2 unclass_highvar, 4 unclassified
INFO     selection_nodes:dec_left_op_right:389 Step 21: left_op_right: rejected if ['d_table_score_node20>5.5 & varex kappa ratio>2*2.0 & variance explained>2.0*0.89'], else nochange
INFO     selection_nodes:dec_left_op_right:391 Step 21: left_op_right Reject if a combination of kappa, variance, and other factors are ranked worse than others
INFO     selection_utils:log_decision_tree_step:406 Step 21: left_op_right applied to 15 components. 2 True -> rejected. 13 False -> nochange.
INFO     selection_utils:log_classification_counts:451 Step 21: Total component classifications: 5 accepted, 9 provisionalaccept, 28 rejected, 4 unclassified
INFO     selection_nodes:dec_left_op_right:389 Step 22: left_op_right: rejected if ['d_table_score_node20>0.9*11 & variance explained>2.0*0.32'], else nochange
INFO     selection_nodes:dec_left_op_right:391 Step 22: left_op_right Reject if a combination of variance and ranks of other metrics are worse than others
INFO     selection_utils:log_decision_tree_step:406 Step 22: left_op_right applied to 13 components. 2 True -> rejected. 11 False -> nochange.
INFO     selection_utils:log_classification_counts:451 Step 22: Total component classifications: 5 accepted, 9 provisionalaccept, 30 rejected, 2 unclassified
INFO     selection_nodes:calc_varex_thresh:1308 Step 23: calc_varex_thresh: Calc varex_new_lower_thresh, 25th percentile threshold
INFO     selection_utils:log_decision_tree_step:418 Step 23: calc_varex_thresh calculated: varex_new_lower_thresh=0.33750948831195976, new_lower_perc=25
INFO     selection_utils:log_classification_counts:451 Step 23: Total component classifications: 5 accepted, 9 provisionalaccept, 30 rejected, 2 unclassified
INFO     selection_nodes:dec_left_op_right:389 Step 24: left_op_right: accepted if ['d_table_score_node20>11 & variance explained>0.34'], else nochange
INFO     selection_nodes:dec_left_op_right:391 Step 24: left_op_right Accept components with a bad d_table_score, but are at the higher end of the remaining variance so more cautious to not remove
INFO     selection_utils:log_decision_tree_step:406 Step 24: left_op_right applied to 11 components. 1 True -> accepted. 10 False -> nochange.
INFO     selection_utils:log_classification_counts:451 Step 24: Total component classifications: 6 accepted, 9 provisionalaccept, 30 rejected, 1 unclassified
INFO     selection_nodes:dec_left_op_right:389 Step 25: left_op_right: accepted if ['kappa<=21.28 & variance explained>0.34'], else nochange
INFO     selection_nodes:dec_left_op_right:391 Step 25: left_op_right For not already rejected components, accept ones below the kappa elbow, but at the higher end of the remaining variance so more cautious to not remove
INFO     selection_utils:comptable_classification_changer:277 Step 25: No components fit criterion True to change classification
INFO     selection_utils:log_decision_tree_step:406 Step 25: left_op_right applied to 10 components. 0 True -> accepted. 10 False -> nochange.
INFO     selection_utils:log_classification_counts:451 Step 25: Total component classifications: 6 accepted, 9 provisionalaccept, 30 rejected, 1 unclassified
INFO     selection_nodes:manual_classify:104 Step 26: manual_classify: Set ['provisionalaccept', 'unclassified', 'unclass_highvar'] to accepted 
INFO     selection_nodes:manual_classify:106 Step 26: manual_classify Anything still provisional (accepted or rejected) or unclassified should be accepted
INFO     selection_utils:log_decision_tree_step:406 Step 26: manual_classify applied to 10 components. 10 True -> accepted. 0 False -> nochange.
INFO     selection_utils:log_classification_counts:451 Step 26: Total component classifications: 16 accepted, 30 rejected
INFO     io:denoise_ts:527 Variance explained by decomposition: 92.18%
INFO     io:write_split_ts:599 Writing high-Kappa time series: /home/runner/work/multi-echo-data-analysis/multi-echo-data-analysis/data/multi-echo-data-analysis/tedana/sub-04570_task-rest_space-scanner_desc-optcomAccepted_bold.nii.gz
INFO     io:write_split_ts:607 Writing low-Kappa time series: /home/runner/work/multi-echo-data-analysis/multi-echo-data-analysis/data/multi-echo-data-analysis/tedana/sub-04570_task-rest_space-scanner_desc-optcomRejected_bold.nii.gz
INFO     io:write_split_ts:614 Writing denoised time series: /home/runner/work/multi-echo-data-analysis/multi-echo-data-analysis/data/multi-echo-data-analysis/tedana/sub-04570_task-rest_space-scanner_desc-denoised_bold.nii.gz
INFO     io:writeresults:663 Writing full ICA coefficient feature set: /home/runner/work/multi-echo-data-analysis/multi-echo-data-analysis/data/multi-echo-data-analysis/tedana/sub-04570_task-rest_space-scanner_desc-ICA_components.nii.gz
INFO     io:writeresults:667 Writing denoised ICA coefficient feature set: /home/runner/work/multi-echo-data-analysis/multi-echo-data-analysis/data/multi-echo-data-analysis/tedana/sub-04570_task-rest_space-scanner_desc-ICAAccepted_components.nii.gz
INFO     io:writeresults:673 Writing Z-normalized spatial component maps: /home/runner/work/multi-echo-data-analysis/multi-echo-data-analysis/data/multi-echo-data-analysis/tedana/sub-04570_task-rest_space-scanner_desc-ICAAccepted_stat-z_components.nii.gz
INFO     gscontrol:minimum_image_regression:167 Performing minimum image regression to remove spatially-diffuse noise
INFO     io:writeresults_echoes:713 Writing Kappa-filtered echo #1 timeseries
INFO     io:denoise_ts:527 Variance explained by decomposition: 84.08%
INFO     io:write_split_ts:596 Writing high-Kappa time series: /home/runner/work/multi-echo-data-analysis/multi-echo-data-analysis/data/multi-echo-data-analysis/tedana/sub-04570_task-rest_space-scanner_echo-1_desc-Accepted_bold.nii.gz
INFO     io:write_split_ts:604 Writing low-Kappa time series: /home/runner/work/multi-echo-data-analysis/multi-echo-data-analysis/data/multi-echo-data-analysis/tedana/sub-04570_task-rest_space-scanner_echo-1_desc-Rejected_bold.nii.gz
INFO     io:write_split_ts:614 Writing denoised time series: /home/runner/work/multi-echo-data-analysis/multi-echo-data-analysis/data/multi-echo-data-analysis/tedana/sub-04570_task-rest_space-scanner_echo-1_desc-Denoised_bold.nii.gz
INFO     io:writeresults_echoes:713 Writing Kappa-filtered echo #2 timeseries
INFO     io:denoise_ts:527 Variance explained by decomposition: 85.17%
INFO     io:write_split_ts:596 Writing high-Kappa time series: /home/runner/work/multi-echo-data-analysis/multi-echo-data-analysis/data/multi-echo-data-analysis/tedana/sub-04570_task-rest_space-scanner_echo-2_desc-Accepted_bold.nii.gz
INFO     io:write_split_ts:604 Writing low-Kappa time series: /home/runner/work/multi-echo-data-analysis/multi-echo-data-analysis/data/multi-echo-data-analysis/tedana/sub-04570_task-rest_space-scanner_echo-2_desc-Rejected_bold.nii.gz
INFO     io:write_split_ts:614 Writing denoised time series: /home/runner/work/multi-echo-data-analysis/multi-echo-data-analysis/data/multi-echo-data-analysis/tedana/sub-04570_task-rest_space-scanner_echo-2_desc-Denoised_bold.nii.gz
INFO     io:writeresults_echoes:713 Writing Kappa-filtered echo #3 timeseries
INFO     io:denoise_ts:527 Variance explained by decomposition: 85.59%
INFO     io:write_split_ts:596 Writing high-Kappa time series: /home/runner/work/multi-echo-data-analysis/multi-echo-data-analysis/data/multi-echo-data-analysis/tedana/sub-04570_task-rest_space-scanner_echo-3_desc-Accepted_bold.nii.gz
INFO     io:write_split_ts:604 Writing low-Kappa time series: /home/runner/work/multi-echo-data-analysis/multi-echo-data-analysis/data/multi-echo-data-analysis/tedana/sub-04570_task-rest_space-scanner_echo-3_desc-Rejected_bold.nii.gz
INFO     io:write_split_ts:614 Writing denoised time series: /home/runner/work/multi-echo-data-analysis/multi-echo-data-analysis/data/multi-echo-data-analysis/tedana/sub-04570_task-rest_space-scanner_echo-3_desc-Denoised_bold.nii.gz
INFO     io:writeresults_echoes:713 Writing Kappa-filtered echo #4 timeseries
INFO     io:denoise_ts:527 Variance explained by decomposition: 85.47%
INFO     io:write_split_ts:596 Writing high-Kappa time series: /home/runner/work/multi-echo-data-analysis/multi-echo-data-analysis/data/multi-echo-data-analysis/tedana/sub-04570_task-rest_space-scanner_echo-4_desc-Accepted_bold.nii.gz
INFO     io:write_split_ts:604 Writing low-Kappa time series: /home/runner/work/multi-echo-data-analysis/multi-echo-data-analysis/data/multi-echo-data-analysis/tedana/sub-04570_task-rest_space-scanner_echo-4_desc-Rejected_bold.nii.gz
INFO     io:write_split_ts:614 Writing denoised time series: /home/runner/work/multi-echo-data-analysis/multi-echo-data-analysis/data/multi-echo-data-analysis/tedana/sub-04570_task-rest_space-scanner_echo-4_desc-Denoised_bold.nii.gz
INFO     tedana:tedana_workflow:885 Making figures folder with static component maps and timecourse plots.
INFO     io:denoise_ts:527 Variance explained by decomposition: 92.18%
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
Cell In[3], line 1
----> 1 workflows.tedana_workflow(
      2     data_files,
      3     echo_times,
      4     out_dir=out_dir,
      5     mask=mask_file,
      6     prefix="sub-04570_task-rest_space-scanner",
      7     fittype="curvefit",
      8     tedpca="mdl",
      9     verbose=True,
     10     gscontrol=["mir"],
     11 )

File /opt/hostedtoolcache/Python/3.10.14/x64/lib/python3.10/site-packages/tedana/workflows/tedana.py:906, in tedana_workflow(data, tes, out_dir, mask, convention, prefix, fittype, combmode, tree, tedpca, fixed_seed, maxit, maxrestart, tedort, gscontrol, no_reports, png_cmap, verbose, low_mem, debug, quiet, overwrite, t2smap, mixm, tedana_command)
    889 reporting.static_figures.carpet_plot(
    890     optcom_ts=data_oc,
    891     denoised_ts=dn_ts,
   (...)
    896     gscontrol=gscontrol,
    897 )
    898 reporting.static_figures.comp_figures(
    899     data_oc,
    900     mask=mask_denoise,
   (...)
    904     png_cmap=png_cmap,
    905 )
--> 906 reporting.static_figures.plot_t2star_and_s0(io_generator=io_generator, mask=mask_denoise)
    908 LGR.info("Generating dynamic report")
    909 reporting.generate_report(io_generator)

File /opt/hostedtoolcache/Python/3.10.14/x64/lib/python3.10/site-packages/tedana/reporting/static_figures.py:593, in plot_t2star_and_s0(io_generator, mask)
    591 # Plot T2* and S0 maps
    592 t2star_plot = f"{io_generator.prefix}t2star_brain.svg"
--> 593 plotting.plot_stat_map(
    594     t2star_img,
    595     bg_img=None,
    596     display_mode="mosaic",
    597     symmetric_cbar=False,
    598     black_bg=True,
    599     cmap="gray",
    600     vmin=t2s_p02,
    601     vmax=t2s_p98,
    602     annotate=False,
    603     output_file=os.path.join(io_generator.out_dir, "figures", t2star_plot),
    604 )
    606 s0_plot = f"{io_generator.prefix}s0_brain.svg"
    607 plotting.plot_stat_map(
    608     s0_img,
    609     bg_img=None,
   (...)
    617     output_file=os.path.join(io_generator.out_dir, "figures", s0_plot),
    618 )

File /opt/hostedtoolcache/Python/3.10.14/x64/lib/python3.10/site-packages/nilearn/plotting/img_plotting.py:934, in plot_stat_map(stat_map_img, bg_img, cut_coords, output_file, display_mode, colorbar, cbar_tick_format, figure, axes, title, threshold, annotate, draw_cross, black_bg, cmap, symmetric_cbar, dim, vmax, resampling_interpolation, **kwargs)
    929 bg_img, black_bg, bg_vmin, bg_vmax = _load_anat(bg_img, dim=dim,
    930                                                 black_bg=black_bg)
    932 stat_map_img = _utils.check_niimg_3d(stat_map_img, dtype='auto')
--> 934 cbar_vmin, cbar_vmax, vmin, vmax = _get_colorbar_and_data_ranges(
    935     _safe_get_data(stat_map_img, ensure_finite=True),
    936     vmax,
    937     symmetric_cbar,
    938     kwargs)
    940 display = _plot_img_with_bg(
    941     img=stat_map_img, bg_img=bg_img, cut_coords=cut_coords,
    942     output_file=output_file, display_mode=display_mode,
   (...)
    947     cbar_vmin=cbar_vmin, cbar_vmax=cbar_vmax,
    948     resampling_interpolation=resampling_interpolation, **kwargs)
    950 return display

File /opt/hostedtoolcache/Python/3.10.14/x64/lib/python3.10/site-packages/nilearn/plotting/img_plotting.py:76, in _get_colorbar_and_data_ranges(stat_map_data, vmax, symmetric_cbar, kwargs, force_min_stat_map_value)
     66 """Internal function for setting colormap and colorbar limits.
     67 
     68 Used by for plot_stat_map and plot_glass_brain.
   (...)
     73 
     74 """
     75 if 'vmin' in kwargs:
---> 76     raise ValueError('this function does not accept a "vmin" '
     77                      'argument, as it uses a symmetrical range '
     78                      'defined via the vmax argument. To threshold '
     79                      'the plotted map, use the "threshold" argument')
     81 # make sure that the color range is symmetrical
     82 if vmax is None or symmetric_cbar in ['auto', False]:
     83     # Avoid dealing with masked_array:

ValueError: this function does not accept a "vmin" argument, as it uses a symmetrical range defined via the vmax argument. To threshold the plotted map, use the "threshold" argument

The tedana workflow writes out a number of files.

out_files = sorted(glob(os.path.join(out_dir, "*")))
out_files = [os.path.basename(f) for f in out_files]
print("\n".join(out_files))
metrics = pd.read_table(
    os.path.join(out_dir, "sub-04570_task-rest_space-scanner_desc-tedana_metrics.tsv")
)
Hide code cell source
def color_rejected_red(series):
    """Color rejected components red."""
    return [
        "color: red" if series["classification"] == "rejected" else "" for v in series
    ]


metrics.style.apply(color_rejected_red, axis=1)
with open(
    os.path.join(out_dir, "sub-04570_task-rest_space-scanner_desc-tedana_metrics.json"),
    "r",
) as fo:
    data = json.load(fo)

first_five_keys = list(data.keys())[:5]
reduced_data = {k: data[k] for k in first_five_keys}
pprint(reduced_data)
df = pd.DataFrame.from_dict(data, orient="index")
df = df.fillna("n/a")
display(HTML(df.to_html()))
report = os.path.join(out_dir, "tedana_report.html")
with open(report, "r") as fo:
    report_data = fo.read()

figures_dir = os.path.relpath(os.path.join(out_dir, "figures"), os.getcwd())
report_data = report_data.replace("./figures", figures_dir)

display(HTML(report_data))