graphica-plot 2.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (181) hide show
  1. graphica/Graphica.ico +0 -0
  2. graphica/__init__.py +1 -0
  3. graphica/__main__.py +111 -0
  4. graphica/assets/__init__.py +0 -0
  5. graphica/assets/icons/__init__.py +0 -0
  6. graphica/assets/icons/arrow-right.svg +21 -0
  7. graphica/assets/icons/bold.svg +20 -0
  8. graphica/assets/icons/calculator.svg +26 -0
  9. graphica/assets/icons/chart-histogram.svg +24 -0
  10. graphica/assets/icons/chart-line.svg +20 -0
  11. graphica/assets/icons/chevron-down.svg +19 -0
  12. graphica/assets/icons/chevron-right.svg +19 -0
  13. graphica/assets/icons/color-swatch.svg +22 -0
  14. graphica/assets/icons/column-insert-right.svg +21 -0
  15. graphica/assets/icons/column-remove.svg +21 -0
  16. graphica/assets/icons/copy.svg +20 -0
  17. graphica/assets/icons/download.svg +21 -0
  18. graphica/assets/icons/edit.svg +21 -0
  19. graphica/assets/icons/eye-off.svg +21 -0
  20. graphica/assets/icons/eye.svg +20 -0
  21. graphica/assets/icons/file-plus.svg +22 -0
  22. graphica/assets/icons/folder-plus.svg +21 -0
  23. graphica/assets/icons/folder.svg +19 -0
  24. graphica/assets/icons/highlight.svg +22 -0
  25. graphica/assets/icons/history.svg +20 -0
  26. graphica/assets/icons/italic.svg +21 -0
  27. graphica/assets/icons/layout-grid.svg +22 -0
  28. graphica/assets/icons/math-function.svg +22 -0
  29. graphica/assets/icons/message-2.svg +21 -0
  30. graphica/assets/icons/mountain.svg +20 -0
  31. graphica/assets/icons/palette.svg +22 -0
  32. graphica/assets/icons/pointer.svg +19 -0
  33. graphica/assets/icons/refresh.svg +20 -0
  34. graphica/assets/icons/row-insert-bottom.svg +21 -0
  35. graphica/assets/icons/row-remove.svg +21 -0
  36. graphica/assets/icons/search.svg +20 -0
  37. graphica/assets/icons/select-all.svg +35 -0
  38. graphica/assets/icons/subscript.svg +20 -0
  39. graphica/assets/icons/superscript.svg +20 -0
  40. graphica/assets/icons/table.svg +21 -0
  41. graphica/assets/icons/trash.svg +23 -0
  42. graphica/assets/icons/typography.svg +23 -0
  43. graphica/assets/icons/x.svg +20 -0
  44. graphica/core/__init__.py +0 -0
  45. graphica/core/analysis.py +1278 -0
  46. graphica/core/app_paths.py +35 -0
  47. graphica/core/axis_settings.py +128 -0
  48. graphica/core/caption_export.py +47 -0
  49. graphica/core/color_palettes.py +56 -0
  50. graphica/core/commands.py +226 -0
  51. graphica/core/cvd_simulation.py +49 -0
  52. graphica/core/dataset.py +443 -0
  53. graphica/core/diagnostics.py +105 -0
  54. graphica/core/excel_utils.py +58 -0
  55. graphica/core/fit_models.py +379 -0
  56. graphica/core/grid_data.py +128 -0
  57. graphica/core/i18n.py +44 -0
  58. graphica/core/json_utils.py +27 -0
  59. graphica/core/label_utils.py +21 -0
  60. graphica/core/methods_text.py +115 -0
  61. graphica/core/named_colors.py +126 -0
  62. graphica/core/plugin_api.py +515 -0
  63. graphica/core/plugin_context.py +167 -0
  64. graphica/core/plugin_install.py +82 -0
  65. graphica/core/plugin_manifest.py +67 -0
  66. graphica/core/plugin_testing.py +213 -0
  67. graphica/core/plugin_types.py +118 -0
  68. graphica/core/provenance.py +19 -0
  69. graphica/core/report_export.py +51 -0
  70. graphica/core/safe_eval.py +194 -0
  71. graphica/core/script_export.py +272 -0
  72. graphica/core/translations_en.py +530 -0
  73. graphica/core/unit_conversion.py +51 -0
  74. graphica/core/update_check.py +43 -0
  75. graphica/core/version.py +14 -0
  76. graphica/gui/__init__.py +0 -0
  77. graphica/gui/app_settings.py +119 -0
  78. graphica/gui/axis_bindings.py +173 -0
  79. graphica/gui/binding.py +135 -0
  80. graphica/gui/builders/__init__.py +1 -0
  81. graphica/gui/builders/axis_panel.py +431 -0
  82. graphica/gui/builders/canvas_area.py +176 -0
  83. graphica/gui/builders/common.py +120 -0
  84. graphica/gui/builders/dataset_panel.py +433 -0
  85. graphica/gui/builders/property_sections.py +208 -0
  86. graphica/gui/canvas.py +519 -0
  87. graphica/gui/color_history.py +47 -0
  88. graphica/gui/color_picker_widget.py +198 -0
  89. graphica/gui/crash_handler.py +77 -0
  90. graphica/gui/cvd_preview.py +23 -0
  91. graphica/gui/data_editor.py +761 -0
  92. graphica/gui/data_import_flow.py +355 -0
  93. graphica/gui/dataset_bindings.py +107 -0
  94. graphica/gui/dataset_style_icon.py +80 -0
  95. graphica/gui/datasets/__init__.py +1 -0
  96. graphica/gui/datasets/actions_menu.py +114 -0
  97. graphica/gui/datasets/colors.py +218 -0
  98. graphica/gui/datasets/fitting.py +70 -0
  99. graphica/gui/datasets/host.py +162 -0
  100. graphica/gui/datasets/operations/__init__.py +1 -0
  101. graphica/gui/datasets/operations/fitting.py +468 -0
  102. graphica/gui/datasets/operations/peaks.py +109 -0
  103. graphica/gui/datasets/operations/processing.py +659 -0
  104. graphica/gui/datasets/operations/runner.py +148 -0
  105. graphica/gui/datasets/operations/transfer.py +227 -0
  106. graphica/gui/datasets/order.py +310 -0
  107. graphica/gui/datasets/overlays.py +74 -0
  108. graphica/gui/datasets/peaks.py +21 -0
  109. graphica/gui/datasets/plugin_runs.py +99 -0
  110. graphica/gui/datasets/processing.py +68 -0
  111. graphica/gui/datasets/property_panel.py +538 -0
  112. graphica/gui/datasets/transfer.py +36 -0
  113. graphica/gui/detached_canvas_window.py +22 -0
  114. graphica/gui/dialogs/__init__.py +137 -0
  115. graphica/gui/dialogs/analysis.py +1322 -0
  116. graphica/gui/dialogs/app.py +1015 -0
  117. graphica/gui/dialogs/appearance.py +851 -0
  118. graphica/gui/dialogs/data_edit.py +577 -0
  119. graphica/gui/dialogs/data_import.py +679 -0
  120. graphica/gui/dialogs/export.py +433 -0
  121. graphica/gui/dock_layout.py +176 -0
  122. graphica/gui/export_preview_panel.py +321 -0
  123. graphica/gui/export_settings.py +16 -0
  124. graphica/gui/file_association.py +97 -0
  125. graphica/gui/icon_utils.py +44 -0
  126. graphica/gui/main_app_window.py +210 -0
  127. graphica/gui/main_window.py +1151 -0
  128. graphica/gui/mathtext_preview.py +168 -0
  129. graphica/gui/menu_bar.py +320 -0
  130. graphica/gui/minimap_widget.py +151 -0
  131. graphica/gui/mixins/__init__.py +0 -0
  132. graphica/gui/mixins/export_mixin.py +520 -0
  133. graphica/gui/mixins/help_mixin.py +127 -0
  134. graphica/gui/mixins/project_io_mixin.py +289 -0
  135. graphica/gui/mixins/quick_access_mixin.py +194 -0
  136. graphica/gui/mixins/ui_setup_mixin.py +206 -0
  137. graphica/gui/notify.py +61 -0
  138. graphica/gui/panels/__init__.py +43 -0
  139. graphica/gui/panels/axis_settings.py +605 -0
  140. graphica/gui/panels/dataset_tree.py +424 -0
  141. graphica/gui/plot_type_drawers.py +131 -0
  142. graphica/gui/plugin_context.py +119 -0
  143. graphica/gui/project_files.py +361 -0
  144. graphica/gui/provenance_panel.py +65 -0
  145. graphica/gui/rendering/__init__.py +1 -0
  146. graphica/gui/rendering/annotations.py +177 -0
  147. graphica/gui/rendering/appearance.py +368 -0
  148. graphica/gui/rendering/common.py +316 -0
  149. graphica/gui/rendering/data_1d.py +376 -0
  150. graphica/gui/rendering/data_2d.py +66 -0
  151. graphica/gui/residual_panel.py +62 -0
  152. graphica/gui/resources.py +16 -0
  153. graphica/gui/single_instance.py +141 -0
  154. graphica/gui/splash.py +83 -0
  155. graphica/gui/task_runner.py +41 -0
  156. graphica/gui/theme.py +864 -0
  157. graphica/gui/tools/__init__.py +56 -0
  158. graphica/gui/tools/annotation.py +275 -0
  159. graphica/gui/tools/cursor.py +259 -0
  160. graphica/gui/tools/layout_edit.py +285 -0
  161. graphica/gui/tools/manager.py +78 -0
  162. graphica/gui/tools/peak_placement.py +132 -0
  163. graphica/gui/tools/range_select.py +191 -0
  164. graphica/gui/tools/region_highlight.py +222 -0
  165. graphica/gui/tools/slice_extraction.py +200 -0
  166. graphica/gui/widget_translation.py +46 -0
  167. graphica/gui/workers.py +280 -0
  168. graphica/models/__init__.py +0 -0
  169. graphica/models/project.py +197 -0
  170. graphica/plugin/__init__.py +20 -0
  171. graphica/plugin/testing.py +57 -0
  172. graphica/sample_data/__init__.py +0 -0
  173. graphica/sample_data/cooling_curve_sample.csv +42 -0
  174. graphica/ui_main_window.py +581 -0
  175. graphica_plot-2.0.0.dist-info/METADATA +317 -0
  176. graphica_plot-2.0.0.dist-info/RECORD +181 -0
  177. graphica_plot-2.0.0.dist-info/WHEEL +5 -0
  178. graphica_plot-2.0.0.dist-info/entry_points.txt +2 -0
  179. graphica_plot-2.0.0.dist-info/licenses/LICENSE +30 -0
  180. graphica_plot-2.0.0.dist-info/licenses/THIRD_PARTY_LICENSES.md +91 -0
  181. graphica_plot-2.0.0.dist-info/top_level.txt +1 -0
graphica/gui/splash.py ADDED
@@ -0,0 +1,83 @@
1
+ """起動画面。重いライブラリ(pandas・scipy・matplotlib)を読む前に出すので、ここでは PySide6 と軽いモジュールだけを使う。"""
2
+ from PySide6.QtCore import QRectF, Qt
3
+ from PySide6.QtGui import QColor, QFont, QIcon, QPainter, QPainterPath, QPixmap
4
+ from PySide6.QtWidgets import QApplication, QSplashScreen
5
+
6
+ from graphica.core.i18n import tr
7
+ from graphica.core.version import APP_NAME, __version__
8
+ from graphica.gui.resources import resource_path
9
+ from graphica.gui.theme import DARK_TOKENS, LIGHT_TOKENS
10
+
11
+ SPLASH_WIDTH = 440
12
+ SPLASH_HEIGHT = 220
13
+ _ICON_SIZE = 88
14
+ _CORNER_RADIUS = 14
15
+
16
+
17
+ def _render_background(dark, device_pixel_ratio):
18
+ colors = DARK_TOKENS if dark else LIGHT_TOKENS
19
+ pixmap = QPixmap(int(SPLASH_WIDTH * device_pixel_ratio), int(SPLASH_HEIGHT * device_pixel_ratio))
20
+ pixmap.setDevicePixelRatio(device_pixel_ratio)
21
+ pixmap.fill(Qt.GlobalColor.transparent)
22
+
23
+ painter = QPainter(pixmap)
24
+ painter.setRenderHint(QPainter.RenderHint.Antialiasing)
25
+ outline = QPainterPath()
26
+ outline.addRoundedRect(QRectF(0.5, 0.5, SPLASH_WIDTH - 1, SPLASH_HEIGHT - 1), _CORNER_RADIUS, _CORNER_RADIUS)
27
+ painter.fillPath(outline, QColor(colors["surface"]))
28
+ painter.setPen(QColor(colors["border"]))
29
+ painter.drawPath(outline)
30
+
31
+ icon_top = 40
32
+ icon = QIcon(resource_path("Graphica.ico")).pixmap(_ICON_SIZE, _ICON_SIZE)
33
+ painter.drawPixmap(32, icon_top, _ICON_SIZE, _ICON_SIZE, icon)
34
+
35
+ text_left = 32 + _ICON_SIZE + 24
36
+ name_font = QFont()
37
+ name_font.setPointSize(22)
38
+ name_font.setBold(True)
39
+ painter.setFont(name_font)
40
+ painter.setPen(QColor(colors["text_primary"]))
41
+ painter.drawText(QRectF(text_left, icon_top + 8, SPLASH_WIDTH - text_left - 24, 40),
42
+ Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignVCenter, APP_NAME)
43
+
44
+ version_font = QFont()
45
+ version_font.setPointSize(10)
46
+ painter.setFont(version_font)
47
+ painter.setPen(QColor(colors["text_secondary"]))
48
+ painter.drawText(QRectF(text_left, icon_top + 50, SPLASH_WIDTH - text_left - 24, 24),
49
+ Qt.AlignmentFlag.AlignLeft | Qt.AlignmentFlag.AlignVCenter,
50
+ tr("バージョン {version}").format(version=__version__))
51
+ painter.end()
52
+ return pixmap
53
+
54
+
55
+ class StartupSplash(QSplashScreen):
56
+ """アイコン・名前・版と、下に今の段階の文字を出す。最初のウィンドウを出したら finish() で閉じる。"""
57
+
58
+ def __init__(self, dark=False):
59
+ app = QApplication.instance()
60
+ ratio = app.devicePixelRatio() if app is not None else 1.0
61
+ super().__init__(_render_background(dark, ratio))
62
+ self.setAttribute(Qt.WidgetAttribute.WA_TranslucentBackground)
63
+ self._text_color = QColor((DARK_TOKENS if dark else LIGHT_TOKENS)["text_secondary"])
64
+
65
+ def drawContents(self, painter):
66
+ # 既定は端から 5px で文字が枠に近すぎるので、下に余白を取る
67
+ painter.setPen(self._text_color)
68
+ painter.drawText(self.rect().adjusted(24, 0, -24, -22),
69
+ Qt.AlignmentFlag.AlignBottom | Qt.AlignmentFlag.AlignHCenter, self.message())
70
+
71
+ def show_progress(self, text):
72
+ """文字を出して、すぐに描かせる(このあと重い処理でイベントループが止まるので)。"""
73
+ self.showMessage(text, Qt.AlignmentFlag.AlignBottom | Qt.AlignmentFlag.AlignHCenter, self._text_color)
74
+ app = QApplication.instance()
75
+ if app is not None:
76
+ app.processEvents()
77
+
78
+
79
+ def show_startup_splash(dark=False):
80
+ splash = StartupSplash(dark)
81
+ splash.show()
82
+ splash.show_progress(tr("起動しています…"))
83
+ return splash
@@ -0,0 +1,41 @@
1
+ """時間のかかる関数を別スレッドで動かす。"""
2
+ import logging
3
+ from PySide6.QtCore import QThread, Signal
4
+
5
+ logger = logging.getLogger(__name__)
6
+
7
+
8
+ class TaskRunner(QThread):
9
+ """fn(*args, report_progress, is_cancelled, **kwargs) を別スレッドで動かす。
10
+
11
+ report_progress(done, total, message="") と is_cancelled() は必ず渡る(使うかは fn の自由)。fn は Qt に依存させない。
12
+ fn が普通に戻れば、キャンセル中でも succeeded を出す(キャンセル時に途中までの結果を返す使い方のため。
13
+ 抑えると succeeded も failed も出ず、呼び出し側が待ち続ける)。
14
+ """
15
+ progress = Signal(int, int, str) # (done, total, message)
16
+ succeeded = Signal(object) # fn の戻り値
17
+ failed = Signal(str) # str(例外)
18
+
19
+ def __init__(self, fn, *args, parent=None, **kwargs):
20
+ super().__init__(parent)
21
+ self._fn = fn
22
+ self._args = args
23
+ self._kwargs = kwargs
24
+
25
+ def run(self):
26
+ def _report_progress(done, total, message=""):
27
+ self.progress.emit(done, total, message)
28
+
29
+ try:
30
+ result = self._fn(
31
+ *self._args,
32
+ report_progress=_report_progress,
33
+ is_cancelled=self.isInterruptionRequested,
34
+ **self._kwargs,
35
+ )
36
+ except Exception as e:
37
+ logger.exception("バックグラウンドタスクが失敗しました")
38
+ self.failed.emit(str(e))
39
+ return
40
+
41
+ self.succeeded.emit(result)