setiastrosuitepro 1.6.4__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 (115) 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/waning_crescent_1.png +0 -0
  14. setiastro/images/waning_crescent_2.png +0 -0
  15. setiastro/images/waning_crescent_3.png +0 -0
  16. setiastro/images/waning_crescent_4.png +0 -0
  17. setiastro/images/waning_crescent_5.png +0 -0
  18. setiastro/images/waning_gibbous_1.png +0 -0
  19. setiastro/images/waning_gibbous_2.png +0 -0
  20. setiastro/images/waning_gibbous_3.png +0 -0
  21. setiastro/images/waning_gibbous_4.png +0 -0
  22. setiastro/images/waning_gibbous_5.png +0 -0
  23. setiastro/images/waxing_crescent_1.png +0 -0
  24. setiastro/images/waxing_crescent_2.png +0 -0
  25. setiastro/images/waxing_crescent_3.png +0 -0
  26. setiastro/images/waxing_crescent_4.png +0 -0
  27. setiastro/images/waxing_crescent_5.png +0 -0
  28. setiastro/images/waxing_gibbous_1.png +0 -0
  29. setiastro/images/waxing_gibbous_2.png +0 -0
  30. setiastro/images/waxing_gibbous_3.png +0 -0
  31. setiastro/images/waxing_gibbous_4.png +0 -0
  32. setiastro/images/waxing_gibbous_5.png +0 -0
  33. setiastro/qml/ResourceMonitor.qml +84 -82
  34. setiastro/saspro/__main__.py +20 -1
  35. setiastro/saspro/_generated/build_info.py +2 -2
  36. setiastro/saspro/abe.py +37 -4
  37. setiastro/saspro/aberration_ai.py +237 -21
  38. setiastro/saspro/acv_exporter.py +379 -0
  39. setiastro/saspro/add_stars.py +33 -6
  40. setiastro/saspro/backgroundneutral.py +108 -40
  41. setiastro/saspro/blemish_blaster.py +4 -1
  42. setiastro/saspro/blink_comparator_pro.py +74 -24
  43. setiastro/saspro/clahe.py +4 -1
  44. setiastro/saspro/continuum_subtract.py +4 -1
  45. setiastro/saspro/convo.py +13 -7
  46. setiastro/saspro/cosmicclarity.py +129 -18
  47. setiastro/saspro/crop_dialog_pro.py +123 -7
  48. setiastro/saspro/curve_editor_pro.py +109 -42
  49. setiastro/saspro/doc_manager.py +245 -15
  50. setiastro/saspro/exoplanet_detector.py +120 -28
  51. setiastro/saspro/frequency_separation.py +1158 -204
  52. setiastro/saspro/ghs_dialog_pro.py +81 -16
  53. setiastro/saspro/graxpert.py +1 -0
  54. setiastro/saspro/gui/main_window.py +429 -228
  55. setiastro/saspro/gui/mixins/dock_mixin.py +245 -24
  56. setiastro/saspro/gui/mixins/menu_mixin.py +27 -1
  57. setiastro/saspro/gui/mixins/theme_mixin.py +160 -14
  58. setiastro/saspro/gui/mixins/toolbar_mixin.py +384 -18
  59. setiastro/saspro/gui/mixins/update_mixin.py +138 -36
  60. setiastro/saspro/gui/mixins/view_mixin.py +42 -0
  61. setiastro/saspro/halobgon.py +4 -0
  62. setiastro/saspro/histogram.py +5 -1
  63. setiastro/saspro/image_combine.py +4 -0
  64. setiastro/saspro/image_peeker_pro.py +4 -0
  65. setiastro/saspro/imageops/starbasedwhitebalance.py +23 -52
  66. setiastro/saspro/imageops/stretch.py +582 -62
  67. setiastro/saspro/isophote.py +4 -0
  68. setiastro/saspro/layers.py +13 -9
  69. setiastro/saspro/layers_dock.py +183 -3
  70. setiastro/saspro/legacy/image_manager.py +154 -20
  71. setiastro/saspro/legacy/numba_utils.py +67 -47
  72. setiastro/saspro/legacy/xisf.py +240 -98
  73. setiastro/saspro/live_stacking.py +180 -79
  74. setiastro/saspro/luminancerecombine.py +228 -27
  75. setiastro/saspro/mask_creation.py +174 -15
  76. setiastro/saspro/mfdeconv.py +113 -35
  77. setiastro/saspro/mfdeconvcudnn.py +119 -70
  78. setiastro/saspro/mfdeconvsport.py +112 -35
  79. setiastro/saspro/morphology.py +4 -0
  80. setiastro/saspro/multiscale_decomp.py +51 -12
  81. setiastro/saspro/numba_utils.py +72 -57
  82. setiastro/saspro/ops/commands.py +18 -18
  83. setiastro/saspro/ops/script_editor.py +10 -2
  84. setiastro/saspro/ops/scripts.py +122 -0
  85. setiastro/saspro/perfect_palette_picker.py +37 -3
  86. setiastro/saspro/plate_solver.py +84 -49
  87. setiastro/saspro/psf_viewer.py +119 -37
  88. setiastro/saspro/resources.py +67 -0
  89. setiastro/saspro/rgbalign.py +4 -0
  90. setiastro/saspro/selective_color.py +4 -1
  91. setiastro/saspro/sfcc.py +364 -152
  92. setiastro/saspro/shortcuts.py +160 -29
  93. setiastro/saspro/signature_insert.py +692 -33
  94. setiastro/saspro/stacking_suite.py +1331 -484
  95. setiastro/saspro/star_alignment.py +247 -123
  96. setiastro/saspro/star_spikes.py +4 -0
  97. setiastro/saspro/star_stretch.py +38 -3
  98. setiastro/saspro/stat_stretch.py +743 -128
  99. setiastro/saspro/subwindow.py +786 -360
  100. setiastro/saspro/supernovaasteroidhunter.py +1 -1
  101. setiastro/saspro/wavescale_hdr.py +4 -1
  102. setiastro/saspro/wavescalede.py +4 -1
  103. setiastro/saspro/whitebalance.py +84 -12
  104. setiastro/saspro/widgets/common_utilities.py +28 -21
  105. setiastro/saspro/widgets/resource_monitor.py +109 -59
  106. setiastro/saspro/widgets/spinboxes.py +10 -13
  107. setiastro/saspro/wimi.py +27 -656
  108. setiastro/saspro/wims.py +13 -3
  109. setiastro/saspro/xisf.py +101 -11
  110. {setiastrosuitepro-1.6.4.dist-info → setiastrosuitepro-1.6.12.dist-info}/METADATA +2 -1
  111. {setiastrosuitepro-1.6.4.dist-info → setiastrosuitepro-1.6.12.dist-info}/RECORD +115 -82
  112. {setiastrosuitepro-1.6.4.dist-info → setiastrosuitepro-1.6.12.dist-info}/WHEEL +0 -0
  113. {setiastrosuitepro-1.6.4.dist-info → setiastrosuitepro-1.6.12.dist-info}/entry_points.txt +0 -0
  114. {setiastrosuitepro-1.6.4.dist-info → setiastrosuitepro-1.6.12.dist-info}/licenses/LICENSE +0 -0
  115. {setiastrosuitepro-1.6.4.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-27T00:14:44Z"
3
- APP_VERSION = "1.6.4"
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.