Skip to content

Commit

Permalink
[REF] Eliminate component sorting from metric calculation (#741)
Browse files Browse the repository at this point in the history
* Remove sort_df and apply_sort functions.

* Remove sort_by and ascending parameters.

* Update descriptions.
  • Loading branch information
tsalo authored Jul 12, 2021
1 parent cc78fcc commit d449925
Show file tree
Hide file tree
Showing 5 changed files with 6 additions and 64 deletions.
2 changes: 1 addition & 1 deletion tedana/decomposition/pca.py
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,7 @@ def tedpca(data_cat, data_oc, combmode, mask, adaptive_mask, t2sG,
comptable, _ = metrics.collect.generate_metrics(
data_cat, data_oc, comp_ts, adaptive_mask,
tes, io_generator, 'PCA',
metrics=required_metrics, sort_by=None
metrics=required_metrics,
)

# varex_norm from PCA overrides varex_norm from dependence_metrics,
Expand Down
38 changes: 0 additions & 38 deletions tedana/metrics/_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,44 +109,6 @@ def flip_components(*args, signs):
return [arg * signs for arg in args]


def sort_df(df, by="kappa", ascending=False):
"""Sort DataFrame and get index.
Parameters
----------
df : :obj:`pandas.DataFrame`
DataFrame to sort.
by : :obj:`str` or None, optional
Column by which to sort the DataFrame. Default is 'kappa'.
ascending : :obj:`bool`, optional
Whether to sort the DataFrame in ascending (True) or descending (False)
order. Default is False.
Returns
-------
df : :obj:`pandas.DataFrame`
DataFrame after sorting, with index resetted.
argsort : array_like
Sorting index.
"""
if by is None:
return df, df.index.values

# Order of kwargs is preserved at 3.6+
argsort = df[by].argsort()
if not ascending:
argsort = argsort[::-1]
df = df.loc[argsort].reset_index(drop=True)
return df, argsort


def apply_sort(*args, sort_idx, axis=0):
"""Apply a sorting index to an arbitrary set of arrays."""
for arg in args:
assert arg.shape[axis] == len(sort_idx)
return [np.take(arg, sort_idx, axis=axis) for arg in args]


def check_mask(data, mask):
"""Check that no zero-variance voxels remain in masked data.
Expand Down
21 changes: 2 additions & 19 deletions tedana/metrics/collect.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,7 @@
import pandas as pd

from . import dependence
from ._utils import (
determine_signs,
flip_components,
sort_df,
apply_sort,
dependency_resolver,
)
from ._utils import determine_signs, flip_components, dependency_resolver

from tedana import io
from tedana import utils
Expand All @@ -33,8 +27,6 @@ def generate_metrics(
io_generator,
label,
metrics=None,
sort_by="kappa",
ascending=False,
):
"""Fit TE-dependence and -independence models to components.
Expand All @@ -60,19 +52,14 @@ def generate_metrics(
The label for this metric generation type
metrics : list
List of metrics to return
sort_by : str, optional
Metric to sort component table by. Default is 'kappa'.
ascending : bool, optional
Whether to sort the table in ascending or descending order.
Default is False.
Returns
-------
comptable : (C x X) :obj:`pandas.DataFrame`
Component metric table. One row for each component, with a column for
each metric. The index is the component number.
mixing : :obj:`numpy.ndarray`
Mixing matrix after sign flipping and sorting.
Mixing matrix after sign flipping.
"""
# Load metric dependency tree from json file
dependency_config = op.join(utils.get_resource_path(), "config", "metrics.json")
Expand Down Expand Up @@ -340,10 +327,6 @@ def generate_metrics(
comptable["countsigFT2"],
)

# Sort the component table and mixing matrix
comptable, sort_idx = sort_df(comptable, by=sort_by, ascending=ascending)
(mixing,) = apply_sort(mixing, sort_idx=sort_idx, axis=1)

# Write verbose metrics if needed
if io_generator.verbose:
write_betas = "map echo betas" in metric_maps
Expand Down
2 changes: 0 additions & 2 deletions tedana/tests/test_metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,6 @@ def test_smoke_generate_metrics(testdata1):
testdata1["generator"],
'ICA',
metrics=metrics,
sort_by="kappa",
ascending=False,
)
assert isinstance(comptable, pd.DataFrame)

Expand Down
7 changes: 3 additions & 4 deletions tedana/workflows/tedana.py
Original file line number Diff line number Diff line change
Expand Up @@ -570,7 +570,7 @@ def tedana_workflow(data, tes, out_dir='.', mask=None,
comptable, mmix = metrics.collect.generate_metrics(
catd, data_oc, mmix_orig, masksum, tes,
io_generator, 'ICA',
metrics=required_metrics, sort_by='kappa', ascending=False,
metrics=required_metrics,
)
comptable, metric_metadata = selection.kundu_selection_v2(
comptable, n_echos, n_vols
Expand Down Expand Up @@ -602,7 +602,7 @@ def tedana_workflow(data, tes, out_dir='.', mask=None,
comptable, mmix = metrics.collect.generate_metrics(
catd, data_oc, mmix_orig, masksum, tes,
io_generator, 'ICA',
metrics=required_metrics, sort_by='kappa', ascending=False
metrics=required_metrics,
)
comptable, metric_metadata = selection.kundu_selection_v2(
comptable, n_echos, n_vols
Expand Down Expand Up @@ -638,8 +638,7 @@ def tedana_workflow(data, tes, out_dir='.', mask=None,
decomp_metadata = {
"Method": (
"Independent components analysis with FastICA "
"algorithm implemented by sklearn. Components "
"are sorted by Kappa in descending order. "
"algorithm implemented by sklearn. "
"Component signs are flipped to best match the "
"data."
),
Expand Down

0 comments on commit d449925

Please sign in to comment.