Coverage for graphica/gui/datasets/plugin_runs.py: 100.0%
66 statements
« prev ^ index » next coverage.py v7.16.2, created at 2026-10-12 16:38 +0000
« prev ^ index » next coverage.py v7.16.2, created at 2026-10-12 16:38 +0000
1"""プラグインが登録したデータ処理と解析の実行。結果の追加は Undo できる。"""
2import logging
3from PySide6.QtWidgets import QDialog
5from graphica.gui import notify
6from graphica.core.dataset import Dataset
7from graphica.core.plugin_types import AnalysisResult, PluginExecutionError
8from graphica.gui.dialogs import PluginParamDialog, ResultDialog
10logger = logging.getLogger(__name__)
13class PluginRunController:
14 """プラグインのデータ処理(processor)と解析(analyzer)を今のデータセットに対して実行する。"""
16 def __init__(self, host):
17 self._host = host
18 self.analysis_result_dialog = None
20 def run_processor(self, processor):
21 """processor が返したデータセットを Undo できる形で足す(プラグイン側は Undo を意識しない)。"""
22 dataset = self._host.current_dataset()
23 if dataset is None:
24 notify.information(self._host.parent_widget, processor.name, "データセットを選択してください。")
25 return
27 params = {}
28 if processor.param_schema:
29 dialog = PluginParamDialog(processor.name, processor.param_schema, self._host.parent_widget)
30 if dialog.exec() != QDialog.DialogCode.Accepted:
31 return
32 params = dialog.get_values()
34 try:
35 new_dataset = processor.fn(dataset, params)
36 if not isinstance(new_dataset, Dataset):
37 raise TypeError(f"Datasetを返しませんでした(型: {type(new_dataset).__name__})。")
38 except Exception as e:
39 logger.exception("[plugin:%s] processor の実行に失敗しました", processor.plugin_name)
40 notify.critical(
41 self._host.parent_widget, "データ処理エラー",
42 str(PluginExecutionError(processor.plugin_name, f"「{processor.name}」の実行に失敗しました: {e}"))
43 )
44 return
46 # どのプラグインが作ったかを残す
47 new_dataset.source_plugin = processor.plugin_name
48 self._host.add_dataset_with_undo(
49 new_dataset, self._host.target_folder_for_new_dataset(),
50 description=f"データ処理: {processor.name}"
51 )
52 self._host.show_status(f"「{new_dataset.name}」を追加しました")
54 def run_analyzer(self, analyzer):
55 """analyzer の結果(派生データセット・注釈・表)を、それぞれ Undo できる形や結果の窓で反映する。"""
56 dataset = self._host.current_dataset()
57 if dataset is None:
58 notify.information(self._host.parent_widget, analyzer.name, "データセットを選択してください。")
59 return
61 params = {}
62 if analyzer.param_schema:
63 dialog = PluginParamDialog(analyzer.name, analyzer.param_schema, self._host.parent_widget)
64 if dialog.exec() != QDialog.DialogCode.Accepted:
65 return
66 params = dialog.get_values()
68 try:
69 result = analyzer.fn(dataset, params)
70 if not isinstance(result, AnalysisResult):
71 raise TypeError(f"AnalysisResultを返しませんでした(型: {type(result).__name__})。")
72 except Exception as e:
73 logger.exception("[plugin:%s] analyzer の実行に失敗しました", analyzer.plugin_name)
74 notify.critical(
75 self._host.parent_widget, "解析エラー",
76 str(PluginExecutionError(analyzer.plugin_name, f"「{analyzer.name}」の実行に失敗しました: {e}"))
77 )
78 return
80 if result.new_datasets:
81 target_folder = self._host.target_folder_for_new_dataset()
82 with self._host.deferred_redraw():
83 for new_dataset in result.new_datasets:
84 new_dataset.source_plugin = analyzer.plugin_name
85 self._host.add_dataset_with_undo(
86 new_dataset, target_folder, description=f"解析による追加: {analyzer.name}"
87 )
89 if result.annotations:
90 self._host.add_annotations_to_active_axis(result.annotations, f"解析による注釈追加: {analyzer.name}")
92 if result.table is not None:
93 if self.analysis_result_dialog is not None:
94 self.analysis_result_dialog.close()
95 self.analysis_result_dialog = ResultDialog(
96 analyzer.name, f"[{analyzer.name}] の解析結果", self._host.parent_widget, csv_data=result.table
97 )
98 self.analysis_result_dialog.show()
100 self._host.show_status(f"「{analyzer.name}」を実行しました")