Skip to content

kymflow_core.state¤

Psygnal-powered state containers shared between GUI components.

Classes¤

AppState ¤

Bases: EventedModel

Shared application state for the NiceGUI GUI.

Manages the current folder, file list, selected file, theme, and image display parameters. Provides signals for state changes to coordinate updates across GUI components.

Attributes:

Name Type Description
folder Optional[Path]

Currently selected folder path.

files List[KymFile]

List of KymFile instances in the current folder.

selected_file Optional[KymFile]

Currently selected KymFile, or None.

theme_mode ThemeMode

Current UI theme (dark or light).

Signals

file_list_changed: Emitted when the file list is updated. selection_changed: Emitted when the selected file changes (kym_file, origin). metadata_changed: Emitted when file metadata is updated (kym_file). theme_changed: Emitted when theme changes (ThemeMode). image_display_changed: Emitted when image display parameters change (ImageDisplayParams).

Source code in src/kymflow_core/state.py
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
class AppState(EventedModel):
    """Shared application state for the NiceGUI GUI.

    Manages the current folder, file list, selected file, theme, and image
    display parameters. Provides signals for state changes to coordinate
    updates across GUI components.

    Attributes:
        folder: Currently selected folder path.
        files: List of KymFile instances in the current folder.
        selected_file: Currently selected KymFile, or None.
        theme_mode: Current UI theme (dark or light).

    Signals:
        file_list_changed: Emitted when the file list is updated.
        selection_changed: Emitted when the selected file changes
            (kym_file, origin).
        metadata_changed: Emitted when file metadata is updated (kym_file).
        theme_changed: Emitted when theme changes (ThemeMode).
        image_display_changed: Emitted when image display parameters change
            (ImageDisplayParams).
    """

    model_config = ConfigDict(arbitrary_types_allowed=True)

    folder: Optional[Path] = None
    files: List[KymFile] = Field(default_factory=list)
    selected_file: Optional[KymFile] = None
    theme_mode: ThemeMode = ThemeMode.DARK

    file_list_changed: ClassVar[Signal] = Signal()
    selection_changed: ClassVar[Signal] = Signal(object, object)
    metadata_changed: ClassVar[Signal] = Signal(object)
    theme_changed: ClassVar[Signal] = Signal(object)
    image_display_changed: ClassVar[Signal] = Signal(object)

    def load_folder(self, folder: Path) -> FolderScanResult:
        """Scan folder for kymograph files and update app state.

        Scans the specified folder for TIFF files, creates KymFile instances,
        and updates the app state. Automatically selects the first file if
        files are found. Emits file_list_changed signal.

        Args:
            folder: Path to the folder to scan.

        Returns:
            FolderScanResult containing the scanned folder and file list.
        """
        result = scan_folder(folder)
        self.folder = result.folder
        self.files = result.files

        logger.info("--> emit file_list_changed")
        self.file_list_changed.emit()

        if self.files:
            self.select_file(self.files[0])
        else:
            self.select_file(None)
        return result

    def select_file(
        self,
        kym_file: Optional[KymFile],
        origin: Optional[SelectionOrigin] = None,
    ) -> None:
        """Set the currently selected file and emit selection_changed signal.

        Updates the selected file and emits a signal to notify GUI components.
        If the file is already selected, no signal is emitted.

        Args:
            kym_file: KymFile to select, or None to clear selection.
            origin: Source of the selection change (for avoiding feedback loops).
                Defaults to None.
        """
        if self.selected_file is kym_file:
            return
        self.selected_file = kym_file

        logger.info(f"--> emit selection_changed kym_file: {kym_file} origin: {origin}")
        self.selection_changed.emit(kym_file, origin)

    def notify_metadata_changed(self, kym_file: KymFile) -> None:
        """Notify listeners that file metadata has been updated.

        Emits metadata_changed signal to notify GUI components that metadata
        for the specified file has been modified.

        Args:
            kym_file: KymFile whose metadata was updated.
        """
        logger.info(f"--> emit metadata_changed kym_file: {kym_file}")
        self.metadata_changed.emit(kym_file)

    def refresh_file_rows(self) -> None:
        """Notify listeners that file metadata changed without reloading folder.

        Emits file_list_changed signal to refresh file table displays without
        re-scanning the folder. Useful when metadata is updated but the file
        list itself hasn't changed.
        """
        logger.info("--> emit file_list_changed")
        self.file_list_changed.emit()

    def set_theme(self, mode: ThemeMode) -> None:
        """Set the application theme and emit theme_changed signal.

        Updates the theme mode and notifies GUI components. If the theme
        is already set to the specified mode, no signal is emitted.

        Args:
            mode: Theme mode to set (DARK or LIGHT).
        """
        if self.theme_mode == mode:
            return
        self.theme_mode = mode
        logger.info(f"--> emit theme_changed mode: {mode}")
        self.theme_changed.emit(mode)

    def set_image_display(self, params: ImageDisplayParams) -> None:
        """Emit signal to update image display parameters (colorscale, intensity range).

        Args:
            params: Complete event payload containing colorscale, zmin, zmax, and origin.
        """
        logger.info(f"--> emit image_display_changed {params}")
        self.image_display_changed.emit(params)

Functions¤

load_folder(folder) ¤

Scan folder for kymograph files and update app state.

Scans the specified folder for TIFF files, creates KymFile instances, and updates the app state. Automatically selects the first file if files are found. Emits file_list_changed signal.

Parameters:

Name Type Description Default
folder Path

Path to the folder to scan.

required

Returns:

Type Description
FolderScanResult

FolderScanResult containing the scanned folder and file list.

Source code in src/kymflow_core/state.py
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
def load_folder(self, folder: Path) -> FolderScanResult:
    """Scan folder for kymograph files and update app state.

    Scans the specified folder for TIFF files, creates KymFile instances,
    and updates the app state. Automatically selects the first file if
    files are found. Emits file_list_changed signal.

    Args:
        folder: Path to the folder to scan.

    Returns:
        FolderScanResult containing the scanned folder and file list.
    """
    result = scan_folder(folder)
    self.folder = result.folder
    self.files = result.files

    logger.info("--> emit file_list_changed")
    self.file_list_changed.emit()

    if self.files:
        self.select_file(self.files[0])
    else:
        self.select_file(None)
    return result
notify_metadata_changed(kym_file) ¤

Notify listeners that file metadata has been updated.

Emits metadata_changed signal to notify GUI components that metadata for the specified file has been modified.

Parameters:

Name Type Description Default
kym_file KymFile

KymFile whose metadata was updated.

required
Source code in src/kymflow_core/state.py
181
182
183
184
185
186
187
188
189
190
191
def notify_metadata_changed(self, kym_file: KymFile) -> None:
    """Notify listeners that file metadata has been updated.

    Emits metadata_changed signal to notify GUI components that metadata
    for the specified file has been modified.

    Args:
        kym_file: KymFile whose metadata was updated.
    """
    logger.info(f"--> emit metadata_changed kym_file: {kym_file}")
    self.metadata_changed.emit(kym_file)
refresh_file_rows() ¤

Notify listeners that file metadata changed without reloading folder.

Emits file_list_changed signal to refresh file table displays without re-scanning the folder. Useful when metadata is updated but the file list itself hasn't changed.

Source code in src/kymflow_core/state.py
193
194
195
196
197
198
199
200
201
def refresh_file_rows(self) -> None:
    """Notify listeners that file metadata changed without reloading folder.

    Emits file_list_changed signal to refresh file table displays without
    re-scanning the folder. Useful when metadata is updated but the file
    list itself hasn't changed.
    """
    logger.info("--> emit file_list_changed")
    self.file_list_changed.emit()
select_file(kym_file, origin=None) ¤

Set the currently selected file and emit selection_changed signal.

Updates the selected file and emits a signal to notify GUI components. If the file is already selected, no signal is emitted.

Parameters:

Name Type Description Default
kym_file Optional[KymFile]

KymFile to select, or None to clear selection.

required
origin Optional[SelectionOrigin]

Source of the selection change (for avoiding feedback loops). Defaults to None.

None
Source code in src/kymflow_core/state.py
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
def select_file(
    self,
    kym_file: Optional[KymFile],
    origin: Optional[SelectionOrigin] = None,
) -> None:
    """Set the currently selected file and emit selection_changed signal.

    Updates the selected file and emits a signal to notify GUI components.
    If the file is already selected, no signal is emitted.

    Args:
        kym_file: KymFile to select, or None to clear selection.
        origin: Source of the selection change (for avoiding feedback loops).
            Defaults to None.
    """
    if self.selected_file is kym_file:
        return
    self.selected_file = kym_file

    logger.info(f"--> emit selection_changed kym_file: {kym_file} origin: {origin}")
    self.selection_changed.emit(kym_file, origin)
set_image_display(params) ¤

Emit signal to update image display parameters (colorscale, intensity range).

Parameters:

Name Type Description Default
params ImageDisplayParams

Complete event payload containing colorscale, zmin, zmax, and origin.

required
Source code in src/kymflow_core/state.py
218
219
220
221
222
223
224
225
def set_image_display(self, params: ImageDisplayParams) -> None:
    """Emit signal to update image display parameters (colorscale, intensity range).

    Args:
        params: Complete event payload containing colorscale, zmin, zmax, and origin.
    """
    logger.info(f"--> emit image_display_changed {params}")
    self.image_display_changed.emit(params)
set_theme(mode) ¤

Set the application theme and emit theme_changed signal.

Updates the theme mode and notifies GUI components. If the theme is already set to the specified mode, no signal is emitted.

Parameters:

Name Type Description Default
mode ThemeMode

Theme mode to set (DARK or LIGHT).

required
Source code in src/kymflow_core/state.py
203
204
205
206
207
208
209
210
211
212
213
214
215
216
def set_theme(self, mode: ThemeMode) -> None:
    """Set the application theme and emit theme_changed signal.

    Updates the theme mode and notifies GUI components. If the theme
    is already set to the specified mode, no signal is emitted.

    Args:
        mode: Theme mode to set (DARK or LIGHT).
    """
    if self.theme_mode == mode:
        return
    self.theme_mode = mode
    logger.info(f"--> emit theme_changed mode: {mode}")
    self.theme_changed.emit(mode)

ImageDisplayParams dataclass ¤

Event payload for image display parameter changes.

Contains all information about display parameter changes, including which UI element initiated the change. Used to coordinate image display updates across GUI components.

Attributes:

Name Type Description
colorscale str

Name of the color scale to use (e.g., "viridis", "gray").

zmin Optional[int]

Minimum intensity value for display scaling. If None, uses data minimum.

zmax Optional[int]

Maximum intensity value for display scaling. If None, uses data maximum.

origin ImageDisplayOrigin

Source of the display parameter change (for avoiding feedback loops).

Source code in src/kymflow_core/state.py
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
@dataclass
class ImageDisplayParams:
    """Event payload for image display parameter changes.

    Contains all information about display parameter changes, including
    which UI element initiated the change. Used to coordinate image display
    updates across GUI components.

    Attributes:
        colorscale: Name of the color scale to use (e.g., "viridis", "gray").
        zmin: Minimum intensity value for display scaling. If None, uses
            data minimum.
        zmax: Maximum intensity value for display scaling. If None, uses
            data maximum.
        origin: Source of the display parameter change (for avoiding feedback loops).
    """

    colorscale: str
    zmin: Optional[int] = None
    zmax: Optional[int] = None
    origin: ImageDisplayOrigin = ImageDisplayOrigin.OTHER

    def __str__(self) -> str:
        return f"ImageDisplayParams(colorscale: {self.colorscale}, zmin: {self.zmin}, zmax: {self.zmax}, origin: {self.origin})"

TaskState ¤

Bases: EventedModel

Container for tracking long-running UI tasks with progress.

Provides signals for progress updates, cancellation, and completion. Used to coordinate between background threads and GUI components.

Attributes:

Name Type Description
running bool

Whether a task is currently running.

progress float

Progress value between 0.0 and 1.0.

message str

Status message describing current task state.

cancellable bool

Whether the task can be cancelled.

Signals

progress_changed: Emitted when progress value changes (float). cancelled: Emitted when cancellation is requested. finished: Emitted when task completes.

Source code in src/kymflow_core/state.py
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
class TaskState(EventedModel):
    """Container for tracking long-running UI tasks with progress.

    Provides signals for progress updates, cancellation, and completion.
    Used to coordinate between background threads and GUI components.

    Attributes:
        running: Whether a task is currently running.
        progress: Progress value between 0.0 and 1.0.
        message: Status message describing current task state.
        cancellable: Whether the task can be cancelled.

    Signals:
        progress_changed: Emitted when progress value changes (float).
        cancelled: Emitted when cancellation is requested.
        finished: Emitted when task completes.
    """

    running: bool = False
    progress: float = 0.0
    message: str = ""
    cancellable: bool = False

    progress_changed: ClassVar[Signal] = Signal(float)
    cancelled: ClassVar[Signal] = Signal()
    finished: ClassVar[Signal] = Signal()

    def set_progress(self, value: float, message: str = "") -> None:
        """Update task progress and emit progress_changed signal.

        Args:
            value: Progress value between 0.0 and 1.0.
            message: Optional status message describing current progress.
        """
        self.progress = value
        self.message = message
        self.progress_changed.emit(value)

    def request_cancel(self) -> None:
        """Request cancellation of the current task.

        Emits the cancelled signal if a task is currently running.
        The task implementation should check for cancellation and stop
        processing when this is called.
        """
        if not self.running:
            return
        self.cancelled.emit()

Functions¤

request_cancel() ¤

Request cancellation of the current task.

Emits the cancelled signal if a task is currently running. The task implementation should check for cancellation and stop processing when this is called.

Source code in src/kymflow_core/state.py
85
86
87
88
89
90
91
92
93
94
def request_cancel(self) -> None:
    """Request cancellation of the current task.

    Emits the cancelled signal if a task is currently running.
    The task implementation should check for cancellation and stop
    processing when this is called.
    """
    if not self.running:
        return
    self.cancelled.emit()
set_progress(value, message='') ¤

Update task progress and emit progress_changed signal.

Parameters:

Name Type Description Default
value float

Progress value between 0.0 and 1.0.

required
message str

Optional status message describing current progress.

''
Source code in src/kymflow_core/state.py
74
75
76
77
78
79
80
81
82
83
def set_progress(self, value: float, message: str = "") -> None:
    """Update task progress and emit progress_changed signal.

    Args:
        value: Progress value between 0.0 and 1.0.
        message: Optional status message describing current progress.
    """
    self.progress = value
    self.message = message
    self.progress_changed.emit(value)

Functions¤

All material is Copyright 2011-2023 Robert H. Cudmore