setiastrosuitepro 1.6.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.

Potentially problematic release.


This version of setiastrosuitepro might be problematic. Click here for more details.

Files changed (174) hide show
  1. setiastro/__init__.py +2 -0
  2. setiastro/saspro/__init__.py +20 -0
  3. setiastro/saspro/__main__.py +784 -0
  4. setiastro/saspro/_generated/__init__.py +7 -0
  5. setiastro/saspro/_generated/build_info.py +2 -0
  6. setiastro/saspro/abe.py +1295 -0
  7. setiastro/saspro/abe_preset.py +196 -0
  8. setiastro/saspro/aberration_ai.py +694 -0
  9. setiastro/saspro/aberration_ai_preset.py +224 -0
  10. setiastro/saspro/accel_installer.py +218 -0
  11. setiastro/saspro/accel_workers.py +30 -0
  12. setiastro/saspro/add_stars.py +621 -0
  13. setiastro/saspro/astrobin_exporter.py +1007 -0
  14. setiastro/saspro/astrospike.py +153 -0
  15. setiastro/saspro/astrospike_python.py +1839 -0
  16. setiastro/saspro/autostretch.py +196 -0
  17. setiastro/saspro/backgroundneutral.py +560 -0
  18. setiastro/saspro/batch_convert.py +325 -0
  19. setiastro/saspro/batch_renamer.py +519 -0
  20. setiastro/saspro/blemish_blaster.py +488 -0
  21. setiastro/saspro/blink_comparator_pro.py +2923 -0
  22. setiastro/saspro/bundles.py +61 -0
  23. setiastro/saspro/bundles_dock.py +114 -0
  24. setiastro/saspro/cheat_sheet.py +168 -0
  25. setiastro/saspro/clahe.py +342 -0
  26. setiastro/saspro/comet_stacking.py +1377 -0
  27. setiastro/saspro/config.py +38 -0
  28. setiastro/saspro/config_bootstrap.py +40 -0
  29. setiastro/saspro/config_manager.py +316 -0
  30. setiastro/saspro/continuum_subtract.py +1617 -0
  31. setiastro/saspro/convo.py +1397 -0
  32. setiastro/saspro/convo_preset.py +414 -0
  33. setiastro/saspro/copyastro.py +187 -0
  34. setiastro/saspro/cosmicclarity.py +1564 -0
  35. setiastro/saspro/cosmicclarity_preset.py +407 -0
  36. setiastro/saspro/crop_dialog_pro.py +948 -0
  37. setiastro/saspro/crop_preset.py +189 -0
  38. setiastro/saspro/curve_editor_pro.py +2544 -0
  39. setiastro/saspro/curves_preset.py +375 -0
  40. setiastro/saspro/debayer.py +670 -0
  41. setiastro/saspro/debug_utils.py +29 -0
  42. setiastro/saspro/dnd_mime.py +35 -0
  43. setiastro/saspro/doc_manager.py +2634 -0
  44. setiastro/saspro/exoplanet_detector.py +2166 -0
  45. setiastro/saspro/file_utils.py +284 -0
  46. setiastro/saspro/fitsmodifier.py +744 -0
  47. setiastro/saspro/free_torch_memory.py +48 -0
  48. setiastro/saspro/frequency_separation.py +1343 -0
  49. setiastro/saspro/function_bundle.py +1594 -0
  50. setiastro/saspro/ghs_dialog_pro.py +660 -0
  51. setiastro/saspro/ghs_preset.py +284 -0
  52. setiastro/saspro/graxpert.py +634 -0
  53. setiastro/saspro/graxpert_preset.py +287 -0
  54. setiastro/saspro/gui/__init__.py +0 -0
  55. setiastro/saspro/gui/main_window.py +8494 -0
  56. setiastro/saspro/gui/mixins/__init__.py +33 -0
  57. setiastro/saspro/gui/mixins/dock_mixin.py +263 -0
  58. setiastro/saspro/gui/mixins/file_mixin.py +445 -0
  59. setiastro/saspro/gui/mixins/geometry_mixin.py +403 -0
  60. setiastro/saspro/gui/mixins/header_mixin.py +441 -0
  61. setiastro/saspro/gui/mixins/mask_mixin.py +421 -0
  62. setiastro/saspro/gui/mixins/menu_mixin.py +361 -0
  63. setiastro/saspro/gui/mixins/theme_mixin.py +367 -0
  64. setiastro/saspro/gui/mixins/toolbar_mixin.py +1324 -0
  65. setiastro/saspro/gui/mixins/update_mixin.py +309 -0
  66. setiastro/saspro/gui/mixins/view_mixin.py +435 -0
  67. setiastro/saspro/halobgon.py +462 -0
  68. setiastro/saspro/header_viewer.py +445 -0
  69. setiastro/saspro/headless_utils.py +88 -0
  70. setiastro/saspro/histogram.py +753 -0
  71. setiastro/saspro/history_explorer.py +939 -0
  72. setiastro/saspro/image_combine.py +414 -0
  73. setiastro/saspro/image_peeker_pro.py +1596 -0
  74. setiastro/saspro/imageops/__init__.py +37 -0
  75. setiastro/saspro/imageops/mdi_snap.py +292 -0
  76. setiastro/saspro/imageops/scnr.py +36 -0
  77. setiastro/saspro/imageops/starbasedwhitebalance.py +210 -0
  78. setiastro/saspro/imageops/stretch.py +244 -0
  79. setiastro/saspro/isophote.py +1179 -0
  80. setiastro/saspro/layers.py +208 -0
  81. setiastro/saspro/layers_dock.py +714 -0
  82. setiastro/saspro/lazy_imports.py +193 -0
  83. setiastro/saspro/legacy/__init__.py +2 -0
  84. setiastro/saspro/legacy/image_manager.py +2226 -0
  85. setiastro/saspro/legacy/numba_utils.py +3659 -0
  86. setiastro/saspro/legacy/xisf.py +1071 -0
  87. setiastro/saspro/linear_fit.py +534 -0
  88. setiastro/saspro/live_stacking.py +1830 -0
  89. setiastro/saspro/log_bus.py +5 -0
  90. setiastro/saspro/logging_config.py +460 -0
  91. setiastro/saspro/luminancerecombine.py +309 -0
  92. setiastro/saspro/main_helpers.py +201 -0
  93. setiastro/saspro/mask_creation.py +928 -0
  94. setiastro/saspro/masks_core.py +56 -0
  95. setiastro/saspro/mdi_widgets.py +353 -0
  96. setiastro/saspro/memory_utils.py +666 -0
  97. setiastro/saspro/metadata_patcher.py +75 -0
  98. setiastro/saspro/mfdeconv.py +3826 -0
  99. setiastro/saspro/mfdeconv_earlystop.py +71 -0
  100. setiastro/saspro/mfdeconvcudnn.py +3263 -0
  101. setiastro/saspro/mfdeconvsport.py +2382 -0
  102. setiastro/saspro/minorbodycatalog.py +567 -0
  103. setiastro/saspro/morphology.py +382 -0
  104. setiastro/saspro/multiscale_decomp.py +1290 -0
  105. setiastro/saspro/nbtorgb_stars.py +531 -0
  106. setiastro/saspro/numba_utils.py +3044 -0
  107. setiastro/saspro/numba_warmup.py +141 -0
  108. setiastro/saspro/ops/__init__.py +9 -0
  109. setiastro/saspro/ops/command_help_dialog.py +623 -0
  110. setiastro/saspro/ops/command_runner.py +217 -0
  111. setiastro/saspro/ops/commands.py +1594 -0
  112. setiastro/saspro/ops/script_editor.py +1102 -0
  113. setiastro/saspro/ops/scripts.py +1413 -0
  114. setiastro/saspro/ops/settings.py +560 -0
  115. setiastro/saspro/parallel_utils.py +554 -0
  116. setiastro/saspro/pedestal.py +121 -0
  117. setiastro/saspro/perfect_palette_picker.py +1053 -0
  118. setiastro/saspro/pipeline.py +110 -0
  119. setiastro/saspro/pixelmath.py +1600 -0
  120. setiastro/saspro/plate_solver.py +2435 -0
  121. setiastro/saspro/project_io.py +797 -0
  122. setiastro/saspro/psf_utils.py +136 -0
  123. setiastro/saspro/psf_viewer.py +549 -0
  124. setiastro/saspro/pyi_rthook_astroquery.py +95 -0
  125. setiastro/saspro/remove_green.py +314 -0
  126. setiastro/saspro/remove_stars.py +1625 -0
  127. setiastro/saspro/remove_stars_preset.py +404 -0
  128. setiastro/saspro/resources.py +472 -0
  129. setiastro/saspro/rgb_combination.py +207 -0
  130. setiastro/saspro/rgb_extract.py +19 -0
  131. setiastro/saspro/rgbalign.py +723 -0
  132. setiastro/saspro/runtime_imports.py +7 -0
  133. setiastro/saspro/runtime_torch.py +754 -0
  134. setiastro/saspro/save_options.py +72 -0
  135. setiastro/saspro/selective_color.py +1552 -0
  136. setiastro/saspro/sfcc.py +1425 -0
  137. setiastro/saspro/shortcuts.py +2807 -0
  138. setiastro/saspro/signature_insert.py +1099 -0
  139. setiastro/saspro/stacking_suite.py +17712 -0
  140. setiastro/saspro/star_alignment.py +7420 -0
  141. setiastro/saspro/star_alignment_preset.py +329 -0
  142. setiastro/saspro/star_metrics.py +49 -0
  143. setiastro/saspro/star_spikes.py +681 -0
  144. setiastro/saspro/star_stretch.py +470 -0
  145. setiastro/saspro/stat_stretch.py +502 -0
  146. setiastro/saspro/status_log_dock.py +78 -0
  147. setiastro/saspro/subwindow.py +3267 -0
  148. setiastro/saspro/supernovaasteroidhunter.py +1712 -0
  149. setiastro/saspro/swap_manager.py +99 -0
  150. setiastro/saspro/torch_backend.py +89 -0
  151. setiastro/saspro/torch_rejection.py +434 -0
  152. setiastro/saspro/view_bundle.py +1555 -0
  153. setiastro/saspro/wavescale_hdr.py +624 -0
  154. setiastro/saspro/wavescale_hdr_preset.py +100 -0
  155. setiastro/saspro/wavescalede.py +657 -0
  156. setiastro/saspro/wavescalede_preset.py +228 -0
  157. setiastro/saspro/wcs_update.py +374 -0
  158. setiastro/saspro/whitebalance.py +456 -0
  159. setiastro/saspro/widgets/__init__.py +48 -0
  160. setiastro/saspro/widgets/common_utilities.py +305 -0
  161. setiastro/saspro/widgets/graphics_views.py +122 -0
  162. setiastro/saspro/widgets/image_utils.py +518 -0
  163. setiastro/saspro/widgets/preview_dialogs.py +280 -0
  164. setiastro/saspro/widgets/spinboxes.py +275 -0
  165. setiastro/saspro/widgets/themed_buttons.py +13 -0
  166. setiastro/saspro/widgets/wavelet_utils.py +299 -0
  167. setiastro/saspro/window_shelf.py +185 -0
  168. setiastro/saspro/xisf.py +1123 -0
  169. setiastrosuitepro-1.6.0.dist-info/METADATA +266 -0
  170. setiastrosuitepro-1.6.0.dist-info/RECORD +174 -0
  171. setiastrosuitepro-1.6.0.dist-info/WHEEL +4 -0
  172. setiastrosuitepro-1.6.0.dist-info/entry_points.txt +6 -0
  173. setiastrosuitepro-1.6.0.dist-info/licenses/LICENSE +674 -0
  174. setiastrosuitepro-1.6.0.dist-info/licenses/license.txt +2580 -0
@@ -0,0 +1,33 @@
1
+ # pro/gui/mixins/__init__.py
2
+ """
3
+ GUI Mixins for AstroSuiteProMainWindow.
4
+
5
+ This package contains modular mixins that separate different aspects of the main window
6
+ into logical, maintainable components.
7
+ """
8
+ from __future__ import annotations
9
+
10
+ from .dock_mixin import DockMixin
11
+ from .menu_mixin import MenuMixin
12
+ from .toolbar_mixin import ToolbarMixin
13
+ from .file_mixin import FileMixin
14
+ from .theme_mixin import ThemeMixin
15
+ from .geometry_mixin import GeometryMixin
16
+ from .view_mixin import ViewMixin
17
+ from .header_mixin import HeaderMixin
18
+ from .mask_mixin import MaskMixin
19
+ from .update_mixin import UpdateMixin
20
+
21
+ __all__ = [
22
+ "DockMixin",
23
+ "MenuMixin",
24
+ "ToolbarMixin",
25
+ "FileMixin",
26
+ "ThemeMixin",
27
+ "GeometryMixin",
28
+ "ViewMixin",
29
+ "HeaderMixin",
30
+ "MaskMixin",
31
+ "UpdateMixin",
32
+ ]
33
+
@@ -0,0 +1,263 @@
1
+ # pro/gui/mixins/dock_mixin.py
2
+ """
3
+ Dock management mixin for AstroSuiteProMainWindow.
4
+
5
+ This mixin contains all dock-related functionality: initialization,
6
+ visibility management, and registration in menus.
7
+ """
8
+ from __future__ import annotations
9
+ from typing import TYPE_CHECKING
10
+
11
+ from PyQt6.QtCore import Qt, QTimer
12
+ from PyQt6.QtWidgets import (
13
+ QDockWidget, QPlainTextEdit, QTreeWidget, QTreeWidgetItem,
14
+ QVBoxLayout, QWidget, QTextEdit, QListWidget, QListWidgetItem,
15
+ QAbstractItemView, QApplication
16
+ )
17
+ from PyQt6.QtGui import QTextCursor
18
+
19
+ if TYPE_CHECKING:
20
+ from PyQt6.QtWidgets import QAction
21
+
22
+
23
+ class DockMixin:
24
+ """
25
+ Mixin for dock widget management.
26
+
27
+ Provides methods for creating, managing, and synchronizing dock widgets
28
+ in the main window.
29
+ """
30
+
31
+ def _init_log_dock(self):
32
+ """Initialize the system log dock widget."""
33
+ self.log_dock = QDockWidget("System Log", self)
34
+ self.log_dock.setObjectName("LogDock")
35
+ self.log_dock.setAllowedAreas(
36
+ Qt.DockWidgetArea.BottomDockWidgetArea
37
+ | Qt.DockWidgetArea.TopDockWidgetArea
38
+ )
39
+
40
+ self.log_text = QPlainTextEdit(self.log_dock)
41
+ self.log_text.setReadOnly(True)
42
+ self.log_text.setLineWrapMode(QPlainTextEdit.LineWrapMode.NoWrap)
43
+ self.log_dock.setWidget(self.log_text)
44
+
45
+ self.addDockWidget(Qt.DockWidgetArea.BottomDockWidgetArea, self.log_dock)
46
+
47
+ self.act_toggle_log = self.log_dock.toggleViewAction()
48
+ self.act_toggle_log.setText("Show System Log Panel")
49
+
50
+ def _append_log_text(self, text: str):
51
+ """Append text to the system log dock."""
52
+ if not text:
53
+ return
54
+ # Append to the bottom and keep view scrolled
55
+ cursor = self.log_text.textCursor()
56
+ cursor.movePosition(QTextCursor.MoveOperation.End)
57
+ cursor.insertText(text)
58
+ self.log_text.setTextCursor(cursor)
59
+ self.log_text.ensureCursorVisible()
60
+
61
+ def _hook_stdout_stderr(self):
62
+ """Hook stdout/stderr to redirect to the system log dock."""
63
+ import sys
64
+ from setiastro.saspro.mdi_widgets import QtLogStream
65
+
66
+ # Remember original streams so we still print to real console.
67
+ self._orig_stdout = sys.stdout
68
+ self._orig_stderr = sys.stderr
69
+
70
+ self._qt_stdout = QtLogStream(self._orig_stdout, self)
71
+ self._qt_stderr = QtLogStream(self._orig_stderr, self)
72
+
73
+ self._qt_stdout.text_emitted.connect(self._append_log_text)
74
+ self._qt_stderr.text_emitted.connect(self._append_log_text)
75
+
76
+ sys.stdout = self._qt_stdout
77
+ sys.stderr = self._qt_stderr
78
+
79
+ def _register_dock_in_view_menu(self, dock: QDockWidget, action: QAction | None = None):
80
+ """
81
+ Register a dock widget's toggle action in the View → Panels menu.
82
+
83
+ Args:
84
+ dock: The QDockWidget to register
85
+ action: Optional custom action (if None, uses dock.toggleViewAction())
86
+ """
87
+ if not hasattr(self, "_view_panels_menu"):
88
+ return
89
+
90
+ if action is None:
91
+ action = dock.toggleViewAction()
92
+
93
+ self._view_panels_menu.addAction(action)
94
+
95
+ def _remove_dock_from_view_menu(self, action: QAction):
96
+ """
97
+ Remove a dock's toggle action from the View → Panels menu.
98
+
99
+ Args:
100
+ action: The action to remove
101
+ """
102
+ if not hasattr(self, "_view_panels_menu"):
103
+ return
104
+
105
+ self._view_panels_menu.removeAction(action)
106
+
107
+ def _init_explorer_dock(self):
108
+ self.explorer = QListWidget()
109
+ # Enter/Return or single-activation: focus if open, else open
110
+ self.explorer.itemActivated.connect(self._activate_or_open_from_explorer)
111
+ # Double-click: same behavior
112
+ self.explorer.itemDoubleClicked.connect(self._activate_or_open_from_explorer)
113
+
114
+ dock = QDockWidget("Explorer", self)
115
+ dock.setWidget(self.explorer)
116
+ dock.setObjectName("ExplorerDock")
117
+ self.addDockWidget(Qt.DockWidgetArea.LeftDockWidgetArea, dock)
118
+
119
+ def _init_console_dock(self):
120
+ self.console = QListWidget()
121
+
122
+ # Allow multi-row selection so Select All actually highlights everything
123
+ self.console.setSelectionMode(QAbstractItemView.SelectionMode.ExtendedSelection)
124
+
125
+ # Right-click context menu
126
+ self.console.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu)
127
+ self.console.customContextMenuRequested.connect(self._on_console_context_menu)
128
+
129
+ dock = QDockWidget("Console / Status", self)
130
+ dock.setWidget(self.console)
131
+ dock.setObjectName("ConsoleDock")
132
+ self.addDockWidget(Qt.DockWidgetArea.BottomDockWidgetArea, dock)
133
+
134
+ def _init_status_log_dock(self):
135
+ from setiastro.saspro.status_log_dock import StatusLogDock
136
+ from setiastro.saspro.log_bus import LogBus
137
+
138
+ # Create the dock
139
+ self.status_log_dock = StatusLogDock(self) # your dock widget class
140
+ self.status_log_dock.setObjectName("StatusLogDock") # stable name for restoreState/menu
141
+ self.status_log_dock.setAllowedAreas(
142
+ Qt.DockWidgetArea.LeftDockWidgetArea
143
+ | Qt.DockWidgetArea.RightDockWidgetArea
144
+ | Qt.DockWidgetArea.BottomDockWidgetArea
145
+ | Qt.DockWidgetArea.TopDockWidgetArea
146
+ )
147
+ # Default area (will be overridden by restoreState if present)
148
+ self.addDockWidget(Qt.DockWidgetArea.RightDockWidgetArea, self.status_log_dock)
149
+
150
+ # Expose the dock globally so dialogs can show/raise it
151
+ app = QApplication.instance()
152
+ app._sasd_status_console = self.status_log_dock
153
+
154
+ # Ensure a global log bus and wire bus -> dock (queued; thread-safe)
155
+ if not hasattr(app, "_sasd_log_bus"):
156
+ app._sasd_log_bus = LogBus()
157
+ app._sasd_log_bus.posted.connect(
158
+ self.status_log_dock.append_line,
159
+ type=Qt.ConnectionType.QueuedConnection
160
+ )
161
+
162
+ # First-run placement (only if no prior saved layout)
163
+ self._first_place_status_log_if_needed()
164
+
165
+ def _init_layers_dock(self):
166
+ from setiastro.saspro.layers_dock import LayersDock
167
+
168
+ self.layers_dock = LayersDock(self)
169
+ self.layers_dock.setObjectName("LayersDock")
170
+ # put it on the right, *below* header viewer if you dock that at right too
171
+ self.addDockWidget(Qt.DockWidgetArea.RightDockWidgetArea, self.layers_dock)
172
+ # ensure the header viewer sits above, layers below
173
+ try:
174
+ self.splitDockWidget(self.header_dock, self.layers_dock, Qt.Orientation.Vertical)
175
+ except Exception:
176
+ pass
177
+
178
+ def _init_header_viewer_dock(self):
179
+ from setiastro.saspro.header_viewer import HeaderViewerDock
180
+
181
+ self.header_viewer = HeaderViewerDock(self)
182
+ self.addDockWidget(Qt.DockWidgetArea.RightDockWidgetArea, self.header_viewer)
183
+
184
+ # Bind the dock to DocManager so it tracks the ACTIVE subwindow only.
185
+ # Make sure self.doc_manager.set_mdi_area(mdi) was already called.
186
+ self.header_viewer.attach_doc_manager(self.doc_manager)
187
+
188
+ # Optional: keep it strictly active-only (default). Flip to True to restore hover-follow behavior.
189
+ # self.header_viewer.set_follow_hover(False)
190
+
191
+ # Seed once with whatever is currently active.
192
+ try:
193
+ self.header_viewer.set_document(self.doc_manager.get_active_document())
194
+ except Exception:
195
+ pass
196
+
197
+ # ❌ Remove this old line; it let random mouse-over updates hijack the dock:
198
+ # self.currentDocumentChanged.disconnect(self.header_viewer.set_document) # if previously connected
199
+ # (If you prefer to keep the signal for explicit tab switches, it's fine to leave
200
+ # it connected--the dock's new guard will ignore non-active/hover docs.)
201
+
202
+ def _populate_view_panels_menu(self):
203
+ """Rebuild 'View Panels' with all current dock widgets (ordered nicely)."""
204
+ menu = self._ensure_view_panels_menu()
205
+ menu.clear()
206
+ self._view_panels_actions = {}
207
+
208
+ # Collect every QDockWidget that exists right now
209
+ docks: list[QDockWidget] = self.findChildren(QDockWidget)
210
+
211
+ # Friendly ordering for common ones; others follow alphabetically.
212
+ order_hint = {
213
+ "Explorer": 10,
214
+ "Console / Status": 20,
215
+ "Header Viewer": 30,
216
+ "Layers": 40,
217
+ "Window Shelf": 50,
218
+ "Command Search": 60,
219
+ }
220
+
221
+ def key_fn(d: QDockWidget):
222
+ t = d.windowTitle()
223
+ return (order_hint.get(t, 1000), t.lower())
224
+
225
+ for dock in sorted(docks, key=key_fn):
226
+ self._register_dock_in_view_menu(dock)
227
+
228
+ def _add_doc_to_explorer(self, doc):
229
+ base = self._normalize_base_doc(doc)
230
+
231
+ # de-dupe by identity on base
232
+ for i in range(self.explorer.count()):
233
+ it = self.explorer.item(i)
234
+ if it.data(Qt.ItemDataRole.UserRole) is base:
235
+ # refresh text in case dims/name changed
236
+ it.setText(self._format_explorer_title(base))
237
+ return
238
+
239
+ item = QListWidgetItem(self._format_explorer_title(base))
240
+ item.setData(Qt.ItemDataRole.UserRole, base)
241
+ fp = (base.metadata or {}).get("file_path")
242
+ if fp:
243
+ item.setToolTip(fp)
244
+ self.explorer.addItem(item)
245
+
246
+ # keep row label in sync with edits/resizes/renames
247
+ try:
248
+ base.changed.connect(lambda *_: self._update_explorer_item_for_doc(base))
249
+ except Exception:
250
+ pass
251
+
252
+ def _remove_doc_from_explorer(self, doc):
253
+ """
254
+ Remove either the exact doc or its base (handles ROI proxies).
255
+ """
256
+ base = self._normalize_base_doc(doc)
257
+ for i in range(self.explorer.count()):
258
+ it = self.explorer.item(i)
259
+ d = it.data(Qt.ItemDataRole.UserRole)
260
+ if d is doc or d is base:
261
+ self.explorer.takeItem(i)
262
+ break
263
+