Skip to content
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
14 changes: 14 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -100,3 +100,17 @@ PYQT5 = false
PYSIDE2 = false
PYQT6 = true
PYSIDE6 = false

[tool.ruff]
target-version = "py311"

[tool.ruff.lint]
# Subsets of B and PLR, the only ones that need no ignore list.
select = ["B006", "B008", "E", "F", "I", "PLR1722", "RUF013", "RUF022", "SIM102", "UP"]
ignore = [
"E501", # line-too-long
"E741", # ambiguous-variable-name
]

[tool.ruff.lint.per-file-ignores]
"__init__.py" = ["F401"]
2 changes: 1 addition & 1 deletion src/mosaic/animation/_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

import numpy as np
from PIL import Image
from qtpy.QtGui import QImage, QGuiApplication
from qtpy.QtGui import QGuiApplication, QImage
from qtpy.QtWidgets import QFileDialog
from vtkmodules.util import numpy_support
from vtkmodules.vtkRenderingCore import vtkWindowToImageFilter
Expand Down
27 changes: 14 additions & 13 deletions src/mosaic/animation/animations.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
from abc import ABC, abstractmethod
from enum import Enum
from typing import List, Dict, Any
from typing import Any

from vtk import vtkTransform
from qtpy.QtWidgets import QDialog
from vtk import vtkTransform

from ..stylesheets import Colors, Typography

Expand Down Expand Up @@ -44,7 +44,7 @@ def _init_parameters(self) -> None:
pass

@abstractmethod
def get_settings(self) -> List[Dict[str, Any]]:
def get_settings(self) -> list[dict[str, Any]]:
"""Return a list of setting definitions for the UI"""
pass

Expand Down Expand Up @@ -180,7 +180,7 @@ def update_parameters(self, **kwargs):

return super().update_parameters(**kwargs)

def get_settings(self) -> List[Dict[str, Any]]:
def get_settings(self) -> list[dict[str, Any]]:
n_frames = getattr(self, "_trajectory", None)
n_frames = n_frames.frames if n_frames is not None else 0
available = self._available_trajectories()
Expand Down Expand Up @@ -271,7 +271,7 @@ def _get_axis_size(self, axis=None):
return 0
return shape[_mapping.get(axis.lower(), 0)]

def get_settings(self) -> List[Dict[str, Any]]:
def get_settings(self) -> list[dict[str, Any]]:
projection = [
self.volume_viewer.primary.project_selector.itemText(i)
for i in range(self.volume_viewer.primary.project_selector.count())
Expand Down Expand Up @@ -396,7 +396,7 @@ def _init_parameters(self) -> None:
self.stop_frame = 180
self._transform = vtkTransform()

def get_settings(self) -> List[Dict[str, Any]]:
def get_settings(self) -> list[dict[str, Any]]:
return [
{
"label": "axis",
Expand Down Expand Up @@ -484,13 +484,13 @@ class ActorSelectionDialog(QDialog):

def __init__(self, cdata, current_selection=None, parent=None):
from qtpy.QtWidgets import (
QVBoxLayout,
QFrame,
QGroupBox,
QHBoxLayout,
QTreeWidget,
QLabel,
QFrame,
QPushButton,
QGroupBox,
QTreeWidget,
QVBoxLayout,
)

from mosaic.widgets import DialogFooter
Expand Down Expand Up @@ -604,7 +604,7 @@ def _init_parameters(self) -> None:
self._original_opacities = {}
self._cached_actors = None

def get_settings(self) -> List[Dict[str, Any]]:
def get_settings(self) -> list[dict[str, Any]]:
return [
{
"label": "start_opacity",
Expand Down Expand Up @@ -775,6 +775,7 @@ def _clear_waypoints(self):
def _init_spline(self):
"""Initialize the spline curve from waypoints."""
import numpy as np

from mosaic.parametrization import SplineCurve

waypoints = self.parameters.get("waypoints", [])
Expand Down Expand Up @@ -911,7 +912,7 @@ def cleanup_preview(self):
except Exception:
self._path_actors.clear()

def get_settings(self) -> List[Dict[str, Any]]:
def get_settings(self) -> list[dict[str, Any]]:
n = len(self.parameters.get("waypoints", []))
count_text = f"{n} waypoint{'s' if n != 1 else ''} defined"
return [
Expand Down Expand Up @@ -1015,7 +1016,7 @@ def _init_parameters(self) -> None:
)
self._initial_distance = None

def get_settings(self) -> List[Dict[str, Any]]:
def get_settings(self) -> list[dict[str, Any]]:
return [
{
"label": "zoom_factor",
Expand Down
54 changes: 26 additions & 28 deletions src/mosaic/animation/compose.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,43 +8,43 @@

import json
from dataclasses import dataclass
from typing import Dict, List, Any
from typing import Any
from uuid import uuid4

import imageio
from vtkmodules.vtkRenderingCore import vtkWindowToImageFilter
from qtpy.QtCore import Qt, QTimer, QSize
from qtpy.QtCore import QSize, Qt, QTimer
from qtpy.QtGui import QKeySequence, QShortcut
from qtpy.QtWidgets import (
QApplication,
QCheckBox,
QDialog,
QWidget,
QVBoxLayout,
QHBoxLayout,
QFileDialog,
QGridLayout,
QPushButton,
QToolButton,
QSpinBox,
QGroupBox,
QFileDialog,
QApplication,
QSizePolicy,
QCheckBox,
QHBoxLayout,
QMessageBox,
QPushButton,
QSizePolicy,
QSpinBox,
QToolButton,
QVBoxLayout,
QWidget,
)
from .timeline import TimelineWidget
from .animations import AnimationType, BaseAnimation
from .settings import AnimationSettings, ExportDialog
from vtkmodules.vtkRenderingCore import vtkWindowToImageFilter

from ..icons import icon
from ..stylesheets import Colors
from ..utils import Throttle
from ..widgets import MosaicMessageBox
from ._utils import (
FrameWriter,
capture_frame,
read_frame,
scaled_device_pixel_attributes,
)

from ..icons import icon
from ..utils import Throttle
from ..stylesheets import Colors
from ..widgets import MosaicMessageBox
from .animations import AnimationType, BaseAnimation
from .settings import AnimationSettings, ExportDialog
from .timeline import TimelineWidget


@dataclass
Expand All @@ -66,7 +66,7 @@ class AnimationComposerDialog(QDialog):

def __init__(self, vtk_widget, volume_viewer=None, cdata=None, parent=None):
super().__init__(parent)
self.tracks: List[Track] = []
self.tracks: list[Track] = []
self.selected_track = None
self.current_frame = 0

Expand Down Expand Up @@ -393,7 +393,7 @@ def _on_track_moved(self, track_id: str, new_frame: int):
self.properties_panel.global_start_spin.setValue(new_frame)
self.timeline.update()

def _on_animation_changed(self, changes: Dict[str, Any]):
def _on_animation_changed(self, changes: dict[str, Any]):
self.timeline.update()

def _get_total_frames(self) -> int:
Expand Down Expand Up @@ -645,9 +645,7 @@ def export_animation(self):
render_height = height * magnification
render_window.SetSize(render_width, render_height)

pixel_scale = (
render_height / original_size[1] if original_size[1] else 1
)
pixel_scale = render_height / original_size[1] if original_size[1] else 1
with scaled_device_pixel_attributes(render_window, pixel_scale):
render_window.Render()

Expand Down Expand Up @@ -749,7 +747,7 @@ def save_project(self):
except Exception as e:
MosaicMessageBox.warning(self, "Save Error", f"Failed to save project: {e}")

def _serialize_parameters(self, params: Dict) -> Dict:
def _serialize_parameters(self, params: dict) -> dict:
"""Convert parameters to JSON-serializable format."""
serialized = {}
for key, value in params.items():
Expand Down Expand Up @@ -787,7 +785,7 @@ def load_project(self):
self.toggle_play()

try:
with open(filename, "r") as f:
with open(filename) as f:
project_data = json.load(f)
except Exception as e:
MosaicMessageBox.warning(
Expand Down
23 changes: 12 additions & 11 deletions src/mosaic/animation/settings.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,25 @@
from qtpy.QtCore import Signal, Qt
from qtpy.QtCore import Qt, Signal
from qtpy.QtWidgets import (
QWidget,
QDialog,
QVBoxLayout,
QHBoxLayout,
QLabel,
QLineEdit,
QSpinBox,
QCheckBox,
QComboBox,
QGroupBox,
QFormLayout,
QDialog,
QDoubleSpinBox,
QFormLayout,
QGridLayout,
QGroupBox,
QHBoxLayout,
QLabel,
QLineEdit,
QPushButton,
QSizePolicy,
QSpinBox,
QVBoxLayout,
QWidget,
)
from mosaic.widgets import create_setting_widget

from mosaic.icons import icon
from mosaic.stylesheets import Colors
from mosaic.widgets import create_setting_widget


class AnimationSettings(QGroupBox):
Expand Down
6 changes: 3 additions & 3 deletions src/mosaic/animation/timeline.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from qtpy.QtCore import Qt, QRect, Signal
from qtpy.QtWidgets import QWidget, QScrollArea, QApplication
from qtpy.QtGui import QPainter, QColor, QPen, QFont, QMouseEvent
from qtpy.QtCore import QRect, Qt, Signal
from qtpy.QtGui import QColor, QFont, QMouseEvent, QPainter, QPen
from qtpy.QtWidgets import QApplication, QScrollArea, QWidget

from ..icons import icon
from ..stylesheets import Colors, Typography
Expand Down
4 changes: 2 additions & 2 deletions src/mosaic/commands/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
Author: Valentin Maurer <valentin.maurer@embl-hamburg.de>
"""

from .session import Session
from .registry import CommandRegistry
from .session import Session

__all__ = ["Session", "CommandRegistry"]
__all__ = ["CommandRegistry", "Session"]
14 changes: 7 additions & 7 deletions src/mosaic/commands/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@
import re
import shlex
from dataclasses import dataclass, field
from typing import Any, Dict, List, Optional
from typing import Any

__all__ = ["ParsedCommand", "parse_command", "format_value", "format_kwargs"]
__all__ = ["ParsedCommand", "format_kwargs", "format_value", "parse_command"]

_TARGET_RE = re.compile(r"^#\d+(-\d+)?$")
_SPECIAL_TARGETS = {"@last", "*"}


def _split_tokens(text: str) -> List[str]:
def _split_tokens(text: str) -> list[str]:
"""Split a command line into shell-like tokens.

Quotes group tokens on every platform. On Windows the backslash is kept
Expand Down Expand Up @@ -169,9 +169,9 @@ class ParsedCommand:
"""

verb: str
targets: List[str] = field(default_factory=list)
args: List[str] = field(default_factory=list)
kwargs: Dict[str, Any] = field(default_factory=dict)
targets: list[str] = field(default_factory=list)
args: list[str] = field(default_factory=list)
kwargs: dict[str, Any] = field(default_factory=dict)

def resolve_positional(self, params) -> None:
"""Map remaining positional *args* into *kwargs* by parameter order.
Expand Down Expand Up @@ -205,7 +205,7 @@ def resolve_positional(self, params) -> None:
self.args = remaining


def parse_command(text: str) -> Optional[ParsedCommand]:
def parse_command(text: str) -> ParsedCommand | None:
"""Parse a text command into a :class:`ParsedCommand`.

Parameters
Expand Down
Loading
Loading