Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ruff update #30

Merged
merged 3 commits into from
Sep 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 0 additions & 7 deletions .github/workflows/code-style.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,6 @@ jobs:
python -m pip install --progress-bar off .[style]
- name: Run Ruff
run: ruff check .
- name: Run isort
uses: isort/isort-action@master
- name: Run black
uses: psf/black@stable
with:
options: "--check --verbose"
version: "23.10.1"
- name: Run codespell
uses: codespell-project/actions-codespell@master
with:
Expand Down
12 changes: 4 additions & 8 deletions brainprint/asymmetry.py
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
"""
Contains asymmetry estimation functionality.
"""
from typing import Dict

import numpy as np
from lapy import shapedna


def compute_asymmetry(
eigenvalues, distance: str = "euc", skip_cortex: bool = False
) -> Dict[str, float]:
) -> dict[str, float]:
"""
Compute lateral shape distances from BrainPrint analysis results.

Expand All @@ -24,7 +22,7 @@ def compute_asymmetry(

Returns
-------
Dict[str, float]
dict[str, float]
{left_label}_{right_label}, distance.
"""
# Define structures
Expand Down Expand Up @@ -75,10 +73,8 @@ def compute_asymmetry(
key = f"{left_label}_{right_label}"
if has_nan:
message = (
"NaNs found for {left_label} or {right_label}, "
"skipping asymmetry computation...".format(
left_label=left_label, right_label=right_label
)
f"NaNs found for {left_label} or {right_label}, "
"skipping asymmetry computation..."
)
print(message)
distances[key] = np.nan
Expand Down
26 changes: 13 additions & 13 deletions brainprint/brainprint.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import shutil
import warnings
from pathlib import Path
from typing import Dict, Tuple, Union
from typing import Union

import numpy as np
from lapy import TriaMesh, shapedna
Expand Down Expand Up @@ -69,7 +69,7 @@ def compute_surface_brainprint(
norm: str = "none",
reweight: bool = False,
use_cholmod: bool = False,
) -> Tuple[np.ndarray, Union[np.ndarray, None]]:
) -> tuple[np.ndarray, Union[np.ndarray, None]]:
"""
Compute BrainPrint eigenvalues and eigenvectors for the given surface.

Expand All @@ -94,7 +94,7 @@ def compute_surface_brainprint(

Returns
-------
Tuple[np.ndarray, Union[np.ndarray, None]]
tuple[np.ndarray, Union[np.ndarray, None]]
Eigenvalues, eigenvectors (if returned).
"""
triangular_mesh = read_vtk(path)
Expand Down Expand Up @@ -126,19 +126,19 @@ def compute_surface_brainprint(


def compute_brainprint(
surfaces: Dict[str, Path],
surfaces: dict[str, Path],
keep_eigenvectors: bool = False,
num: int = 50,
norm: str = "none",
reweight: bool = False,
use_cholmod: bool = False,
) -> Tuple[Dict[str, np.ndarray], Union[Dict[str, np.ndarray], None]]:
) -> tuple[dict[str, np.ndarray], Union[dict[str, np.ndarray], None]]:
"""
Compute ShapeDNA descriptors over several surfaces.

Parameters
----------
surfaces : Dict[str, Path]
surfaces : dict[str, Path]
Dictionary mapping from labels to *.vtk* paths.
keep_eigenvectors : bool, optional
Whether to also return eigenvectors or not, by default False.
Expand All @@ -155,7 +155,7 @@ def compute_brainprint(

Returns
-------
Tuple[Dict[str, np.ndarray], Union[Dict[str, np.ndarray], None]]
tuple[dict[str, np.ndarray], Union[dict[str, np.ndarray], None]]
Surface label to eigenvalues, surface label to eigenvectors (if
*keep_eigenvectors* is True).
"""
Expand All @@ -177,9 +177,9 @@ def compute_brainprint(
except Exception as e:
message = (
"BrainPrint analysis raised the following exception:\n"
"{exception}".format(exception=e)
f"{e}"
)
warnings.warn(message)
warnings.warn(message, stacklevel = 2)
eigenvalues[surface_label] = ["NaN"] * (num + 2)
else:
if len(surface_eigenvalues) == 0:
Expand Down Expand Up @@ -275,7 +275,7 @@ def run_brainprint(
skip_cortex=skip_cortex,
)

csv_name = "{subject_id}.brainprint.csv".format(subject_id=subject_id)
csv_name = f"{subject_id}.brainprint.csv"
csv_path = destination / csv_name
export_brainprint_results(csv_path, eigenvalues, eigenvectors, distances)
if not keep_temp:
Expand Down Expand Up @@ -358,7 +358,7 @@ def __init__(
if freesurfer_validation:
test_freesurfer()

def run(self, subject_id: str, destination: Path = None) -> Dict[str, Path]:
def run(self, subject_id: str, destination: Path = None) -> dict[str, Path]:
"""
Run Brainprint analysis for a specified subject.

Expand All @@ -371,7 +371,7 @@ def run(self, subject_id: str, destination: Path = None) -> Dict[str, Path]:

Returns
-------
Dict[str, Path]
dict[str, Path]
A dictionary containing paths to the generated analysis results.
"""
self._eigenvalues = self._eigenvectors = self._distances = None
Expand Down Expand Up @@ -418,7 +418,7 @@ def export_results(self, destination: Path, subject_id: str) -> None:
-------
None
"""
csv_name = "{subject_id}.brainprint.csv".format(subject_id=subject_id)
csv_name = f"{subject_id}.brainprint.csv"
csv_path = destination / csv_name
return export_brainprint_results(
csv_path, self._eigenvalues, self._eigenvectors, self._distances
Expand Down
31 changes: 13 additions & 18 deletions brainprint/surfaces.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,14 @@
"""
import uuid
from pathlib import Path
from typing import Dict, List

from lapy import TriaMesh

from .utils.utils import run_shell_command


def create_aseg_surface(
subject_dir: Path, destination: Path, indices: List[int]
subject_dir: Path, destination: Path, indices: list[int]
) -> Path:
"""
Generate a surface from the aseg and label files.
Expand All @@ -22,7 +21,7 @@ def create_aseg_surface(
Path to the subject's directory.
destination : Path
Path to the destination directory where the surface will be saved.
indices : List[int]
indices : list[int]
List of label indices to include in the surface generation.

Returns
Expand All @@ -32,7 +31,7 @@ def create_aseg_surface(
"""
aseg_path = subject_dir / "mri/aseg.mgz"
norm_path = subject_dir / "mri/norm.mgz"
temp_name = "temp/aseg.{uid}".format(uid=uuid.uuid4())
temp_name = f"temp/aseg.{uuid.uuid4()}"
indices_mask = destination / f"{temp_name}.mgz"
# binarize on selected labels (creates temp indices_mask)
# always binarize first, otherwise pretess may scale aseg if labels are
Expand All @@ -58,7 +57,7 @@ def create_aseg_surface(
run_shell_command(pretess_command)

# runs marching cube to extract surface
surface_name = "{name}.surf".format(name=temp_name)
surface_name = f"{temp_name}.surf"
surface_path = destination / surface_name
extraction_template = "mri_mc {source} {label_value} {destination}"
extraction_command = extraction_template.format(
Expand All @@ -80,7 +79,7 @@ def create_aseg_surface(
return conversion_destination


def create_aseg_surfaces(subject_dir: Path, destination: Path) -> Dict[str, Path]:
def create_aseg_surfaces(subject_dir: Path, destination: Path) -> dict[str, Path]:
"""
Create surfaces from FreeSurfer aseg labels.

Expand All @@ -93,7 +92,7 @@ def create_aseg_surfaces(subject_dir: Path, destination: Path) -> Dict[str, Path

Returns
-------
Dict[str, Path]
dict[str, Path]
Dictionary of label names mapped to corresponding surface Path objects.
"""
# Define aseg labels
Expand Down Expand Up @@ -145,7 +144,7 @@ def create_aseg_surfaces(subject_dir: Path, destination: Path) -> Dict[str, Path
}


def create_cortical_surfaces(subject_dir: Path, destination: Path) -> Dict[str, Path]:
def create_cortical_surfaces(subject_dir: Path, destination: Path) -> dict[str, Path]:
"""
Create cortical surfaces from FreeSurfer labels.

Expand All @@ -158,7 +157,7 @@ def create_cortical_surfaces(subject_dir: Path, destination: Path) -> Dict[str,

Returns
-------
Dict[str, Path]
dict[str, Path]
Dictionary mapping label names to associated surface Paths.
"""
cortical_labels = {
Expand All @@ -178,7 +177,7 @@ def create_cortical_surfaces(subject_dir: Path, destination: Path) -> Dict[str,

def create_surfaces(
subject_dir: Path, destination: Path, skip_cortex: bool = False
) -> Dict[str, Path]:
) -> dict[str, Path]:
"""
Create surfaces based on FreeSurfer labels.

Expand All @@ -193,7 +192,7 @@ def create_surfaces(

Returns
-------
Dict[str, Path]
dict[str, Path]
Dict mapping label names to the corresponding Path objects of created surfaces.
"""
surfaces = create_aseg_surfaces(subject_dir, destination)
Expand Down Expand Up @@ -225,15 +224,11 @@ def read_vtk(path: Path):
try:
triangular_mesh = TriaMesh.read_vtk(path)
except Exception:
message = "Failed to read VTK from the following path: {path}!".format(
path=path
)
raise RuntimeError(message)
message = f"Failed to read VTK from the following path: {path}!"
raise RuntimeError(message) from None
else:
if triangular_mesh is None:
message = "Failed to read VTK from the following path: {path}!".format(
path=path
)
message = f"Failed to read VTK from the following path: {path}!"
raise RuntimeError(message)
return triangular_mesh

Expand Down
6 changes: 3 additions & 3 deletions brainprint/utils/_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import sys
from functools import partial
from importlib.metadata import requires, version
from typing import IO, Callable, List, Optional
from typing import IO, Callable, Optional

import psutil

Expand Down Expand Up @@ -67,7 +67,7 @@ def sys_info(fid: Optional[IO] = None, developer: bool = False):
_list_dependencies_info(out, ljust, dependencies)


def _list_dependencies_info(out: Callable, ljust: int, dependencies: List[str]):
def _list_dependencies_info(out: Callable, ljust: int, dependencies: list[str]):
"""List dependencies names and versions.

Parameters
Expand All @@ -76,7 +76,7 @@ def _list_dependencies_info(out: Callable, ljust: int, dependencies: List[str]):
output function
ljust : int
length of returned string
dependencies : List[str]
dependencies : list[str]
list of dependencies

"""
Expand Down
23 changes: 9 additions & 14 deletions brainprint/utils/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
import shlex
import subprocess
from pathlib import Path
from typing import Dict

import numpy as np
import pandas as pd
Expand Down Expand Up @@ -34,11 +33,11 @@ def test_freesurfer() -> None:
command = "mri_binarize -version"
try:
run_shell_command(command)
except FileNotFoundError:
except FileNotFoundError as err:
raise RuntimeError(
"Failed to run FreeSurfer command, please check the required binaries "
"are included in your $PATH."
)
) from err


def run_shell_command(command: str, verbose: bool = False):
Expand All @@ -62,17 +61,15 @@ def run_shell_command(command: str, verbose: bool = False):
return_code = subprocess.call(args)
except Exception as e:
message = (
"Failed to execute the following command:\n{command}\n"
"The following exception was raised:\n{exception}".format(
command=command, exception=e
)
f"Failed to execute the following command:\n{command}\n"
f"The following exception was raised:\n{e}"
)
print(message)
raise
if return_code != 0:
message = (
"Execution of the following command:\n{command}\n"
"Returned non-zero exit code!".format(command=command)
f"Execution of the following command:\n{command}\n"
"Returned non-zero exit code!"
)
raise RuntimeError(message)

Expand All @@ -96,9 +93,7 @@ def validate_subject_dir(subjects_dir: Path, subject_id: str) -> Path:
"""
subject_dir = Path(subjects_dir) / subject_id
if not subject_dir.is_dir():
message = "FreeSurfer results directory at {path} does not exist!".format(
path=subject_dir
)
message = f"FreeSurfer results directory at {subject_dir} does not exist!"
raise FileNotFoundError(message)
return subject_dir

Expand Down Expand Up @@ -141,7 +136,7 @@ def export_brainprint_results(
eigenvalues: np.ndarray,
eigenvectors: np.ndarray = None,
distances: np.ndarray = None,
) -> Dict[str, Path]:
) -> dict[str, Path]:
"""
Writes the BrainPrint analysis results to CSV files.

Expand All @@ -167,7 +162,7 @@ def export_brainprint_results(
eigenvectors_dir = destination.parent / "eigenvectors"
eigenvectors_dir.mkdir(parents=True, exist_ok=True)
for key, value in eigenvectors.items():
suffix = ".evecs-{key}.csv".format(key=key)
suffix = f".evecs-{key}.csv"
name = destination.with_suffix(suffix).name
vectors_destination = eigenvectors_dir / name
pd.DataFrame(value).to_csv(
Expand Down
Loading