setiastrosuitepro 1.6.2__py3-none-any.whl → 1.6.12__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 (162) hide show
  1. setiastro/images/abeicon.svg +16 -0
  2. setiastro/images/acv_icon.png +0 -0
  3. setiastro/images/colorwheel.svg +97 -0
  4. setiastro/images/cosmic.svg +40 -0
  5. setiastro/images/cosmicsat.svg +24 -0
  6. setiastro/images/first_quarter.png +0 -0
  7. setiastro/images/full_moon.png +0 -0
  8. setiastro/images/graxpert.svg +19 -0
  9. setiastro/images/last_quarter.png +0 -0
  10. setiastro/images/linearfit.svg +32 -0
  11. setiastro/images/new_moon.png +0 -0
  12. setiastro/images/pixelmath.svg +42 -0
  13. setiastro/images/rotatearbitrary.png +0 -0
  14. setiastro/images/waning_crescent_1.png +0 -0
  15. setiastro/images/waning_crescent_2.png +0 -0
  16. setiastro/images/waning_crescent_3.png +0 -0
  17. setiastro/images/waning_crescent_4.png +0 -0
  18. setiastro/images/waning_crescent_5.png +0 -0
  19. setiastro/images/waning_gibbous_1.png +0 -0
  20. setiastro/images/waning_gibbous_2.png +0 -0
  21. setiastro/images/waning_gibbous_3.png +0 -0
  22. setiastro/images/waning_gibbous_4.png +0 -0
  23. setiastro/images/waning_gibbous_5.png +0 -0
  24. setiastro/images/waxing_crescent_1.png +0 -0
  25. setiastro/images/waxing_crescent_2.png +0 -0
  26. setiastro/images/waxing_crescent_3.png +0 -0
  27. setiastro/images/waxing_crescent_4.png +0 -0
  28. setiastro/images/waxing_crescent_5.png +0 -0
  29. setiastro/images/waxing_gibbous_1.png +0 -0
  30. setiastro/images/waxing_gibbous_2.png +0 -0
  31. setiastro/images/waxing_gibbous_3.png +0 -0
  32. setiastro/images/waxing_gibbous_4.png +0 -0
  33. setiastro/images/waxing_gibbous_5.png +0 -0
  34. setiastro/qml/ResourceMonitor.qml +84 -82
  35. setiastro/saspro/__main__.py +20 -1
  36. setiastro/saspro/_generated/build_info.py +2 -2
  37. setiastro/saspro/abe.py +37 -4
  38. setiastro/saspro/aberration_ai.py +237 -21
  39. setiastro/saspro/acv_exporter.py +379 -0
  40. setiastro/saspro/add_stars.py +33 -6
  41. setiastro/saspro/backgroundneutral.py +114 -37
  42. setiastro/saspro/blemish_blaster.py +4 -1
  43. setiastro/saspro/blink_comparator_pro.py +548 -275
  44. setiastro/saspro/clahe.py +4 -1
  45. setiastro/saspro/continuum_subtract.py +4 -1
  46. setiastro/saspro/convo.py +13 -7
  47. setiastro/saspro/cosmicclarity.py +129 -18
  48. setiastro/saspro/crop_dialog_pro.py +134 -8
  49. setiastro/saspro/curve_editor_pro.py +109 -42
  50. setiastro/saspro/doc_manager.py +246 -16
  51. setiastro/saspro/exoplanet_detector.py +120 -28
  52. setiastro/saspro/frequency_separation.py +1158 -204
  53. setiastro/saspro/function_bundle.py +16 -16
  54. setiastro/saspro/ghs_dialog_pro.py +81 -16
  55. setiastro/saspro/graxpert.py +1 -0
  56. setiastro/saspro/gui/main_window.py +519 -289
  57. setiastro/saspro/gui/mixins/dock_mixin.py +276 -42
  58. setiastro/saspro/gui/mixins/geometry_mixin.py +105 -5
  59. setiastro/saspro/gui/mixins/menu_mixin.py +28 -1
  60. setiastro/saspro/gui/mixins/theme_mixin.py +160 -14
  61. setiastro/saspro/gui/mixins/toolbar_mixin.py +416 -27
  62. setiastro/saspro/gui/mixins/update_mixin.py +138 -36
  63. setiastro/saspro/gui/mixins/view_mixin.py +42 -0
  64. setiastro/saspro/halobgon.py +4 -0
  65. setiastro/saspro/histogram.py +5 -1
  66. setiastro/saspro/image_combine.py +4 -0
  67. setiastro/saspro/image_peeker_pro.py +4 -0
  68. setiastro/saspro/imageops/starbasedwhitebalance.py +23 -52
  69. setiastro/saspro/imageops/stretch.py +582 -62
  70. setiastro/saspro/isophote.py +4 -0
  71. setiastro/saspro/layers.py +13 -9
  72. setiastro/saspro/layers_dock.py +183 -3
  73. setiastro/saspro/legacy/image_manager.py +154 -20
  74. setiastro/saspro/legacy/numba_utils.py +67 -47
  75. setiastro/saspro/legacy/xisf.py +240 -98
  76. setiastro/saspro/live_stacking.py +180 -79
  77. setiastro/saspro/luminancerecombine.py +228 -27
  78. setiastro/saspro/mask_creation.py +174 -15
  79. setiastro/saspro/mfdeconv.py +113 -35
  80. setiastro/saspro/mfdeconvcudnn.py +119 -70
  81. setiastro/saspro/mfdeconvsport.py +112 -35
  82. setiastro/saspro/morphology.py +4 -0
  83. setiastro/saspro/multiscale_decomp.py +748 -255
  84. setiastro/saspro/numba_utils.py +72 -57
  85. setiastro/saspro/ops/commands.py +18 -18
  86. setiastro/saspro/ops/script_editor.py +10 -2
  87. setiastro/saspro/ops/scripts.py +122 -0
  88. setiastro/saspro/perfect_palette_picker.py +37 -3
  89. setiastro/saspro/plate_solver.py +84 -49
  90. setiastro/saspro/psf_viewer.py +119 -37
  91. setiastro/saspro/remove_stars_preset.py +55 -13
  92. setiastro/saspro/resources.py +97 -11
  93. setiastro/saspro/rgbalign.py +4 -0
  94. setiastro/saspro/selective_color.py +83 -21
  95. setiastro/saspro/sfcc.py +364 -152
  96. setiastro/saspro/shortcuts.py +253 -49
  97. setiastro/saspro/signature_insert.py +692 -33
  98. setiastro/saspro/stacking_suite.py +1610 -574
  99. setiastro/saspro/star_alignment.py +522 -453
  100. setiastro/saspro/star_spikes.py +4 -0
  101. setiastro/saspro/star_stretch.py +38 -3
  102. setiastro/saspro/stat_stretch.py +743 -128
  103. setiastro/saspro/status_log_dock.py +1 -1
  104. setiastro/saspro/subwindow.py +786 -360
  105. setiastro/saspro/supernovaasteroidhunter.py +1 -1
  106. setiastro/saspro/swap_manager.py +77 -42
  107. setiastro/saspro/translations/all_source_strings.json +1588 -516
  108. setiastro/saspro/translations/ar_translations.py +915 -684
  109. setiastro/saspro/translations/de_translations.py +442 -463
  110. setiastro/saspro/translations/es_translations.py +277 -47
  111. setiastro/saspro/translations/fr_translations.py +279 -47
  112. setiastro/saspro/translations/hi_translations.py +253 -21
  113. setiastro/saspro/translations/integrate_translations.py +3 -2
  114. setiastro/saspro/translations/it_translations.py +1211 -161
  115. setiastro/saspro/translations/ja_translations.py +3340 -3107
  116. setiastro/saspro/translations/pt_translations.py +3315 -3337
  117. setiastro/saspro/translations/ru_translations.py +351 -117
  118. setiastro/saspro/translations/saspro_ar.qm +0 -0
  119. setiastro/saspro/translations/saspro_ar.ts +15902 -138
  120. setiastro/saspro/translations/saspro_de.qm +0 -0
  121. setiastro/saspro/translations/saspro_de.ts +14428 -133
  122. setiastro/saspro/translations/saspro_es.qm +0 -0
  123. setiastro/saspro/translations/saspro_es.ts +11503 -7821
  124. setiastro/saspro/translations/saspro_fr.qm +0 -0
  125. setiastro/saspro/translations/saspro_fr.ts +11168 -7812
  126. setiastro/saspro/translations/saspro_hi.qm +0 -0
  127. setiastro/saspro/translations/saspro_hi.ts +14733 -135
  128. setiastro/saspro/translations/saspro_it.qm +0 -0
  129. setiastro/saspro/translations/saspro_it.ts +14347 -7821
  130. setiastro/saspro/translations/saspro_ja.qm +0 -0
  131. setiastro/saspro/translations/saspro_ja.ts +14860 -137
  132. setiastro/saspro/translations/saspro_pt.qm +0 -0
  133. setiastro/saspro/translations/saspro_pt.ts +14904 -137
  134. setiastro/saspro/translations/saspro_ru.qm +0 -0
  135. setiastro/saspro/translations/saspro_ru.ts +11766 -168
  136. setiastro/saspro/translations/saspro_sw.qm +0 -0
  137. setiastro/saspro/translations/saspro_sw.ts +15115 -135
  138. setiastro/saspro/translations/saspro_uk.qm +0 -0
  139. setiastro/saspro/translations/saspro_uk.ts +11206 -6729
  140. setiastro/saspro/translations/saspro_zh.qm +0 -0
  141. setiastro/saspro/translations/saspro_zh.ts +10581 -7812
  142. setiastro/saspro/translations/sw_translations.py +282 -56
  143. setiastro/saspro/translations/uk_translations.py +264 -35
  144. setiastro/saspro/translations/zh_translations.py +282 -47
  145. setiastro/saspro/view_bundle.py +17 -17
  146. setiastro/saspro/wavescale_hdr.py +4 -1
  147. setiastro/saspro/wavescalede.py +4 -1
  148. setiastro/saspro/whitebalance.py +84 -12
  149. setiastro/saspro/widgets/common_utilities.py +28 -21
  150. setiastro/saspro/widgets/minigame/game.js +11 -6
  151. setiastro/saspro/widgets/resource_monitor.py +133 -57
  152. setiastro/saspro/widgets/spinboxes.py +28 -13
  153. setiastro/saspro/wimi.py +92 -721
  154. setiastro/saspro/wims.py +46 -36
  155. setiastro/saspro/window_shelf.py +2 -2
  156. setiastro/saspro/xisf.py +101 -11
  157. {setiastrosuitepro-1.6.2.dist-info → setiastrosuitepro-1.6.12.dist-info}/METADATA +8 -7
  158. {setiastrosuitepro-1.6.2.dist-info → setiastrosuitepro-1.6.12.dist-info}/RECORD +162 -128
  159. {setiastrosuitepro-1.6.2.dist-info → setiastrosuitepro-1.6.12.dist-info}/WHEEL +0 -0
  160. {setiastrosuitepro-1.6.2.dist-info → setiastrosuitepro-1.6.12.dist-info}/entry_points.txt +0 -0
  161. {setiastrosuitepro-1.6.2.dist-info → setiastrosuitepro-1.6.12.dist-info}/licenses/LICENSE +0 -0
  162. {setiastrosuitepro-1.6.2.dist-info → setiastrosuitepro-1.6.12.dist-info}/licenses/license.txt +0 -0
@@ -1,124 +1,126 @@
1
1
  import QtQuick 2.15
2
2
  import QtQuick.Controls 2.15
3
3
  import QtQuick.Layouts 1.15
4
+ import QtQuick.Window 2.15 // ✅ gives us access to the attached Window handle
4
5
 
5
6
  Rectangle {
6
7
  id: root
7
- // Wider to fit 3 gauges + spacing
8
8
  width: 200
9
9
  height: 60
10
- // 50% opacity black
11
10
  color: "#80000000"
12
11
  radius: 30
13
12
  border.color: "#555"
14
13
  border.width: 1
15
14
 
16
- property double cpuUsage: 0.0
17
- property double ramUsage: 0.0
18
- property double gpuUsage: 0.0
19
- property double appRamUsage: 0.0
20
- property string appRamString: "0 MB"
21
-
22
- // Helper component for gauges
23
- component MiniGauge: Item {
24
- Layout.preferredWidth: 40
25
- Layout.preferredHeight: 40
26
- property string label: ""
27
- property color barColor: "#0f0"
28
- property double value: 0
29
-
30
- // Trigger repaint when value changes
31
- onValueChanged: if (gaugeCanvas) gaugeCanvas.requestPaint()
32
-
33
- Canvas {
34
- id: gaugeCanvas
35
- anchors.fill: parent
36
- antialiasing: true
37
- onPaint: {
38
- var ctx = getContext("2d");
39
- var cx = width / 2;
40
- var cy = height / 2;
41
- var r = (width / 2) - 3;
42
-
43
- ctx.reset();
44
-
45
- // Track
46
- ctx.beginPath();
47
- ctx.arc(cx, cy, r, 0, 2*Math.PI);
48
- ctx.lineWidth = 4;
49
- ctx.strokeStyle = "#444";
50
- ctx.stroke();
51
-
52
- // Value Arc
53
- // start at -90 deg (top)
54
- var start = -Math.PI/2;
55
- var end = start + (value/100 * 2*Math.PI);
56
-
57
- ctx.beginPath();
58
- ctx.arc(cx, cy, r, start, end);
59
- ctx.lineWidth = 4;
60
- ctx.lineCap = "round";
61
- ctx.strokeStyle = barColor;
62
- ctx.stroke();
63
- }
15
+ // Bind directly to the injected Python object (context property "backend")
16
+ property double cpuUsage: backend ? backend.cpuUsage : 0.0
17
+ property double ramUsage: backend ? backend.ramUsage : 0.0
18
+ property double gpuUsage: backend ? backend.gpuUsage : 0.0
19
+ property string appRamString: backend ? backend.appRamString : "0 MB"
20
+
21
+ // ─── Wayland-friendly drag (works if we have a real QQuickWindow) ───
22
+ MouseArea {
23
+ anchors.fill: parent
24
+ hoverEnabled: true
25
+ cursorShape: Qt.OpenHandCursor
26
+
27
+ onPressed: {
28
+ // Window-attached handle: root.Window.window is the QQuickWindow
29
+ var w = root.Window ? root.Window.window : null;
30
+ if (w && w.startSystemMove) {
31
+ // Wayland: this is the correct, compositor-approved move
32
+ w.startSystemMove();
33
+ } else {
34
+ // Fallback (Windows embed, or platforms where startSystemMove isn't exposed)
35
+ // Do nothing; your existing Windows behavior remains unchanged.
64
36
  }
65
-
66
- // Numeric Percent in center
67
- Text {
68
- anchors.centerIn: parent
69
- text: Math.round(value) + "%"
70
- font.pixelSize: 10
71
- font.bold: true
72
- color: "#fff"
37
+ }
38
+ }
39
+
40
+ component MiniGauge: Item {
41
+ Layout.preferredWidth: 40
42
+ Layout.preferredHeight: 40
43
+ property string label: ""
44
+ property color barColor: "#0f0"
45
+ property double value: 0
46
+
47
+ onValueChanged: if (gaugeCanvas) gaugeCanvas.requestPaint()
48
+
49
+ Canvas {
50
+ id: gaugeCanvas
51
+ anchors.fill: parent
52
+ antialiasing: true
53
+ onPaint: {
54
+ var ctx = getContext("2d");
55
+ var cx = width / 2;
56
+ var cy = height / 2;
57
+ var r = (width / 2) - 3;
58
+
59
+ ctx.reset();
60
+
61
+ ctx.beginPath();
62
+ ctx.arc(cx, cy, r, 0, 2*Math.PI);
63
+ ctx.lineWidth = 4;
64
+ ctx.strokeStyle = "#444";
65
+ ctx.stroke();
66
+
67
+ var start = -Math.PI/2;
68
+ var end = start + (value/100 * 2*Math.PI);
69
+
70
+ ctx.beginPath();
71
+ ctx.arc(cx, cy, r, start, end);
72
+ ctx.lineWidth = 4;
73
+ ctx.lineCap = "round";
74
+ ctx.strokeStyle = barColor;
75
+ ctx.stroke();
73
76
  }
74
77
  }
75
78
 
79
+ Text {
80
+ anchors.centerIn: parent
81
+ text: Math.round(value) + "%"
82
+ font.pixelSize: 10
83
+ font.bold: true
84
+ color: "#fff"
85
+ }
86
+ }
87
+
76
88
  RowLayout {
77
89
  anchors.centerIn: parent
78
90
  spacing: 15
79
91
 
80
- // --- CPU ---
81
92
  ColumnLayout {
82
93
  spacing: 2
83
94
  MiniGauge {
84
95
  value: root.cpuUsage
85
- // Dynamic color
86
96
  barColor: root.cpuUsage > 80 ? "#ff4444" : (root.cpuUsage > 50 ? "#ffbb33" : "#00C851")
87
97
  }
88
- Text {
89
- Layout.alignment: Qt.AlignHCenter
90
- text: "CPU"
91
- color: "#aaaaaa"
98
+ Text {
99
+ Layout.alignment: Qt.AlignHCenter
100
+ text: "CPU"
101
+ color: "#aaaaaa"
92
102
  font.pixelSize: 9
93
103
  }
94
104
  }
95
105
 
96
- // --- RAM ---
97
106
  ColumnLayout {
98
107
  spacing: 2
99
- MiniGauge {
100
- value: root.ramUsage
101
- barColor: "#33b5e5"
102
- }
103
- Text {
104
- Layout.alignment: Qt.AlignHCenter
105
- text: "RAM"
106
- color: "#aaaaaa"
108
+ MiniGauge { value: root.ramUsage; barColor: "#33b5e5" }
109
+ Text {
110
+ Layout.alignment: Qt.AlignHCenter
111
+ text: "RAM"
112
+ color: "#aaaaaa"
107
113
  font.pixelSize: 9
108
114
  }
109
115
  }
110
116
 
111
- // --- GPU ---
112
117
  ColumnLayout {
113
118
  spacing: 2
114
- MiniGauge {
115
- value: root.gpuUsage
116
- barColor: "#aa66cc"
117
- }
118
- Text {
119
- Layout.alignment: Qt.AlignHCenter
120
- text: "GPU"
121
- color: "#aaaaaa"
119
+ MiniGauge { value: root.gpuUsage; barColor: "#aa66cc" }
120
+ Text {
121
+ Layout.alignment: Qt.AlignHCenter
122
+ text: "GPU"
123
+ color: "#aaaaaa"
122
124
  font.pixelSize: 9
123
125
  }
124
126
  }
@@ -11,6 +11,19 @@ called via the `main()` function when invoked as an entry point.
11
11
 
12
12
  import sys
13
13
  import os
14
+
15
+ from pathlib import Path
16
+
17
+ if sys.platform.startswith("win"):
18
+ exe_dir = Path(sys.executable).resolve().parent
19
+ internal = exe_dir / "_internal"
20
+ if internal.is_dir():
21
+ try:
22
+ os.add_dll_directory(str(internal))
23
+ except Exception:
24
+ pass
25
+ os.environ["PATH"] = str(internal) + os.pathsep + os.environ.get("PATH", "")
26
+
14
27
  from PyQt6.QtCore import QCoreApplication
15
28
 
16
29
  # ---- Linux Qt stability guard (must run BEFORE any PyQt6 import) ----
@@ -79,9 +92,15 @@ def _init_splash():
79
92
  # Create QApplication
80
93
  _app = QApplication(sys.argv)
81
94
 
95
+ try:
96
+ _app.setQuitOnLastWindowClosed(True)
97
+ except Exception:
98
+ pass
99
+
82
100
  if sys.platform.startswith("linux"):
83
101
  try:
84
102
  print("Qt platform:", _app.platformName())
103
+ print("QuitOnLastWindowClosed:", _app.quitOnLastWindowClosed())
85
104
  print("XDG_SESSION_TYPE:", os.environ.get("XDG_SESSION_TYPE"))
86
105
  print("QT_QPA_PLATFORM:", os.environ.get("QT_QPA_PLATFORM"))
87
106
  print("QT_OPENGL:", os.environ.get("QT_OPENGL"))
@@ -382,7 +401,7 @@ def _init_splash():
382
401
  # --- Copyright ---
383
402
  painter.setFont(self.copyright_font)
384
403
  painter.setPen(QColor(100, 100, 130))
385
- copyright_text = "© 2024-2025 Franklin Marek (Seti Astro) • All Rights Reserved"
404
+ copyright_text = "© 2024-2026 Franklin Marek (Seti Astro) • All Rights Reserved"
386
405
  copyright_rect = QRect(0, h - 30, w, 20)
387
406
  painter.drawText(copyright_rect, Qt.AlignmentFlag.AlignCenter, copyright_text)
388
407
 
@@ -1,3 +1,3 @@
1
1
  # Auto-generated at build time. Do not edit.
2
- BUILD_TIMESTAMP = "2025-12-22T00:35:11Z"
3
- APP_VERSION = "1.6.2"
2
+ BUILD_TIMESTAMP = "2026-01-07T16:45:00Z"
3
+ APP_VERSION = "1.6.12"
setiastro/saspro/abe.py CHANGED
@@ -491,14 +491,21 @@ class ABEDialog(QDialog):
491
491
  # Non-modal: allow user to switch between images while dialog is open
492
492
  self.setWindowModality(Qt.WindowModality.NonModal)
493
493
  self.setModal(False)
494
- #self.setAttribute(Qt.WidgetAttribute.WA_DeleteOnClose, True)
494
+ try:
495
+ self.setAttribute(Qt.WidgetAttribute.WA_DeleteOnClose, True)
496
+ except Exception:
497
+ pass # older PyQt6 versions
495
498
 
496
499
  self._main = parent
497
500
  self.doc = document
498
501
 
499
- # Connect to active document change signal
502
+ self._connected_current_doc_changed = False
500
503
  if hasattr(self._main, "currentDocumentChanged"):
501
- self._main.currentDocumentChanged.connect(self._on_active_doc_changed)
504
+ try:
505
+ self._main.currentDocumentChanged.connect(self._on_active_doc_changed)
506
+ self._connected_current_doc_changed = True
507
+ except Exception:
508
+ self._connected_current_doc_changed = False
502
509
 
503
510
  self._preview_scale = 1.0
504
511
  self._preview_qimg = None
@@ -844,12 +851,38 @@ class ABEDialog(QDialog):
844
851
  self._set_status("Done")
845
852
  # Dialog stays open so user can apply to other images
846
853
  # Refresh to use the now-active document for next operation
847
- self._refresh_document_from_active()
854
+ self.close()
855
+ return
848
856
 
849
857
  except Exception as e:
850
858
  self._set_status("Error")
851
859
  QMessageBox.critical(self, "Apply failed", str(e))
852
860
 
861
+ def closeEvent(self, ev):
862
+ # 1) Disconnect active-doc tracking (Fabio hook)
863
+ try:
864
+ if self._connected_current_doc_changed and hasattr(self._main, "currentDocumentChanged"):
865
+ self._main.currentDocumentChanged.disconnect(self._on_active_doc_changed)
866
+ except Exception:
867
+ pass
868
+ self._connected_current_doc_changed = False
869
+
870
+ # 2) Stop any background preview worker/thread if you have one
871
+ # (names may differ in your file; keep what matches your implementation)
872
+ try:
873
+ if getattr(self, "_worker", None) is not None:
874
+ try:
875
+ self._worker.requestInterruption()
876
+ except Exception:
877
+ pass
878
+ if getattr(self, "_thread", None) is not None:
879
+ self._thread.quit()
880
+ self._thread.wait(500)
881
+ except Exception:
882
+ pass
883
+
884
+ super().closeEvent(ev)
885
+
853
886
  def _refresh_document_from_active(self):
854
887
  """
855
888
  Refresh the dialog's document reference to the currently active document.