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
@@ -202,7 +202,7 @@ class FunctionBundleChip(QWidget):
202
202
  from PyQt6.QtWidgets import QMenu # already imported at top, but safe
203
203
 
204
204
  m = QMenu(self)
205
- act_del = m.addAction("Delete Chip")
205
+ act_del = m.addAction(self._panel.tr("Delete Chip"))
206
206
  act = m.exec(ev.globalPos())
207
207
  if act is act_del:
208
208
  try:
@@ -333,7 +333,7 @@ class FunctionBundleDialog(QDialog):
333
333
  def __init__(self, parent: QWidget | None = None):
334
334
  super().__init__(parent)
335
335
  _pin_on_top_mac(self)
336
- self.setWindowTitle("Function Bundles")
336
+ self.setWindowTitle(self.tr("Function Bundles"))
337
337
  self.setWindowFlag(Qt.WindowType.Window, True)
338
338
  self.setWindowModality(Qt.WindowModality.NonModal)
339
339
  self.setModal(False)
@@ -350,9 +350,9 @@ class FunctionBundleDialog(QDialog):
350
350
  self.list.setSelectionMode(QAbstractItemView.SelectionMode.SingleSelection)
351
351
  self.list.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu)
352
352
 
353
- self.btn_new = QPushButton("New")
354
- self.btn_dup = QPushButton("Duplicate")
355
- self.btn_del = QPushButton("Delete")
353
+ self.btn_new = QPushButton(self.tr("New"))
354
+ self.btn_dup = QPushButton(self.tr("Duplicate"))
355
+ self.btn_del = QPushButton(self.tr("Delete"))
356
356
 
357
357
  # right: steps
358
358
  self.steps = QListWidget()
@@ -368,26 +368,26 @@ class FunctionBundleDialog(QDialog):
368
368
  self.steps.setResizeMode(QListView.ResizeMode.Adjust) # recompute item layout on width change
369
369
  self.steps.setUniformItemSizes(False)
370
370
 
371
- self.add_hint = QLabel("Drop shortcuts here to add steps")
371
+ self.add_hint = QLabel(self.tr("Drop shortcuts here to add steps"))
372
372
  self.add_hint.setAlignment(Qt.AlignmentFlag.AlignCenter)
373
373
  self.add_hint.setStyleSheet("color:#aaa; padding:6px; border:1px dashed #666; border-radius:6px;")
374
374
 
375
- self.btn_edit_preset = QPushButton("Edit Preset…")
375
+ self.btn_edit_preset = QPushButton(self.tr("Edit Preset…"))
376
376
  self.btn_edit_preset.setEnabled(False) # enabled when exactly one step is selected
377
377
 
378
- self.btn_remove = QPushButton("Remove Selected")
379
- self.btn_clear = QPushButton("Clear Steps")
380
- self.btn_up = QPushButton("▲ Move Up")
381
- self.btn_down = QPushButton("▼ Move Down")
378
+ self.btn_remove = QPushButton(self.tr("Remove Selected"))
379
+ self.btn_clear = QPushButton(self.tr("Clear Steps"))
380
+ self.btn_up = QPushButton(self.tr("▲ Move Up"))
381
+ self.btn_down = QPushButton(self.tr("▼ Move Down"))
382
382
 
383
- self.btn_drag_bundle = QPushButton("Drag Bundle")
384
- self.btn_run_active = QPushButton("Apply to Active View")
385
- self.btn_apply_to_vbundle = QPushButton("Apply to View Bundle…")
386
- self.btn_chip = QPushButton("Compress to Chip")
383
+ self.btn_drag_bundle = QPushButton(self.tr("Drag Bundle"))
384
+ self.btn_run_active = QPushButton(self.tr("Apply to Active View"))
385
+ self.btn_apply_to_vbundle = QPushButton(self.tr("Apply to View Bundle…"))
386
+ self.btn_chip = QPushButton(self.tr("Compress to Chip"))
387
387
 
388
388
  # layout
389
389
  left = QVBoxLayout()
390
- left.addWidget(QLabel("Function Bundles"))
390
+ left.addWidget(QLabel(self.tr("Function Bundles")))
391
391
  left.addWidget(self.list, 1)
392
392
  row = QHBoxLayout()
393
393
  row.addWidget(self.btn_new); row.addWidget(self.btn_dup); row.addWidget(self.btn_del)
@@ -27,6 +27,10 @@ class GhsDialogPro(QDialog):
27
27
  self.setWindowFlag(Qt.WindowType.Window, True)
28
28
  self.setWindowModality(Qt.WindowModality.NonModal)
29
29
  self.setModal(False)
30
+ try:
31
+ self.setAttribute(Qt.WidgetAttribute.WA_DeleteOnClose, True)
32
+ except Exception:
33
+ pass # older PyQt6 versions
30
34
  self.doc = document
31
35
  self._preview_img = None
32
36
  self._full_img = None
@@ -123,14 +127,16 @@ class GhsDialogPro(QDialog):
123
127
  main.addLayout(right, 1)
124
128
 
125
129
  # ---------- wiring ----------
126
- self.editor.setPreviewCallback(lambda _lut8: self._quick_preview())
130
+ self._suppress_editor_preview = False
131
+ self.editor.setPreviewCallback(lambda _lut8: self._on_editor_preview())
127
132
  self.editor.setSymmetryCallback(self._on_symmetry_pick)
128
133
 
129
- self.sA.valueChanged.connect(self._rebuild_from_params)
130
- self.sB.valueChanged.connect(self._rebuild_from_params)
131
- self.sG.valueChanged.connect(self._rebuild_from_params)
132
- self.sLP.valueChanged.connect(self._rebuild_from_params)
133
- self.sHP.valueChanged.connect(self._rebuild_from_params)
134
+ for s in (self.sA, self.sB, self.sG, self.sLP, self.sHP):
135
+ s.valueChanged.connect(self._schedule_rebuild_from_params)
136
+
137
+ # Track dragging so we can “flush” on release
138
+ s.sliderPressed.connect(self._on_any_slider_pressed)
139
+ s.sliderReleased.connect(self._on_any_slider_released)
134
140
  self.cmb_ch.currentTextChanged.connect(self._recolor_curve)
135
141
 
136
142
  self.btn_apply.clicked.connect(self._apply)
@@ -148,6 +154,12 @@ class GhsDialogPro(QDialog):
148
154
  # start with Fit to Preview (avoids offset issues)
149
155
  QTimer.singleShot(0, self._fit)
150
156
 
157
+ self._rebuild_debounce = QTimer(self)
158
+ self._rebuild_debounce.setSingleShot(True)
159
+ self._rebuild_debounce.setInterval(75) # 50–120ms feels good; 75 is a nice default
160
+ self._rebuild_debounce.timeout.connect(self._rebuild_from_params_now)
161
+
162
+ self._slider_dragging = False
151
163
 
152
164
  # first curve
153
165
  self._rebuild_from_params()
@@ -194,12 +206,53 @@ class GhsDialogPro(QDialog):
194
206
  self.editor.setSymmetryPoint(u * 360.0, 0.0)
195
207
  self._rebuild_from_params()
196
208
 
209
+ def _on_editor_preview(self):
210
+ if getattr(self, "_suppress_editor_preview", False):
211
+ return
212
+ self._quick_preview()
213
+
214
+ def _on_any_slider_pressed(self):
215
+ self._slider_dragging = True
216
+
217
+ def _on_any_slider_released(self):
218
+ self._slider_dragging = False
219
+ # Flush immediately to final value
220
+ if self._rebuild_debounce.isActive():
221
+ self._rebuild_debounce.stop()
222
+ self._rebuild_from_params_now()
223
+
224
+ def _schedule_rebuild_from_params(self):
225
+ """
226
+ Called on every valueChanged tick. Updates labels fast, but defers the heavy work.
227
+ """
228
+ # lightweight label updates (no LUT/preview work here)
229
+ a = self.sA.value() / 50.0
230
+ b = self.sB.value() / 50.0
231
+ g = self.sG.value() / 100.0
232
+ self.labA.setText(f"{a:.2f}")
233
+ self.labB.setText(f"{b:.2f}")
234
+ self.labG.setText(f"{g:.2f}")
235
+ self.labLP.setText(f"{self.sLP.value()/360.0:.2f}")
236
+ self.labHP.setText(f"{self.sHP.value()/360.0:.2f}")
237
+
238
+ # debounce heavy rebuild
239
+ self._rebuild_debounce.start()
240
+
241
+ def _rebuild_from_params(self):
242
+ """
243
+ Keep existing call sites working (hist pivot, symmetry pick, etc).
244
+ For non-slider callers we generally WANT immediate rebuild.
245
+ """
246
+ if self._rebuild_debounce.isActive():
247
+ self._rebuild_debounce.stop()
248
+ self._rebuild_from_params_now()
249
+
197
250
 
198
251
  def _on_symmetry_pick(self, u, v):
199
252
  self._sym_u = float(u)
200
253
  self._rebuild_from_params()
201
254
 
202
- def _rebuild_from_params(self):
255
+ def _rebuild_from_params_now(self):
203
256
  a = self.sA.value()/50.0
204
257
  b = self.sB.value()/50.0
205
258
  g = self.sG.value()/100.0
@@ -267,12 +320,17 @@ class GhsDialogPro(QDialog):
267
320
  ys = (1.0 - vp) * 360.0
268
321
  pts = list(zip(xs.astype(float), ys.astype(float)))
269
322
 
270
- cps_sorted = sorted(self.editor.control_points, key=lambda p: p.scenePos().x())
271
- for p, (x, y) in zip(cps_sorted, pts):
272
- p.setPos(x, y)
323
+ self._suppress_editor_preview = True
324
+ try:
325
+ cps_sorted = sorted(self.editor.control_points, key=lambda p: p.scenePos().x())
326
+ for p, (x, y) in zip(cps_sorted, pts):
327
+ p.setPos(x, y)
328
+
329
+ self._recolor_curve()
330
+ self.editor.updateCurve()
331
+ finally:
332
+ self._suppress_editor_preview = False
273
333
 
274
- self._recolor_curve()
275
- self.editor.updateCurve()
276
334
  self._quick_preview()
277
335
 
278
336
 
@@ -654,10 +712,17 @@ class GhsDialogPro(QDialog):
654
712
 
655
713
  return (m * out + (1.0 - m) * src).astype(np.float32, copy=False)
656
714
 
657
-
658
715
  def _reset(self):
659
- self.sA.setValue(50); self.sB.setValue(50); self.sG.setValue(100)
660
- self.sLP.setValue(0); self.sHP.setValue(0)
716
+ for s in (self.sA, self.sB, self.sG, self.sLP, self.sHP):
717
+ s.blockSignals(True)
718
+ try:
719
+ self.sA.setValue(50); self.sB.setValue(50); self.sG.setValue(100)
720
+ self.sLP.setValue(0); self.sHP.setValue(0)
721
+ finally:
722
+ for s in (self.sA, self.sB, self.sG, self.sLP, self.sHP):
723
+ s.blockSignals(False)
724
+
661
725
  self._sym_u = 0.5
662
726
  self.editor.clearSymmetryLine()
663
- self._rebuild_from_params()
727
+ self._rebuild_from_params() # immediate
728
+
@@ -34,6 +34,7 @@ class GraXpertOperationDialog(QDialog):
34
34
  self.setWindowFlag(Qt.WindowType.Window, True)
35
35
  self.setWindowModality(Qt.WindowModality.NonModal)
36
36
  self.setModal(False)
37
+
37
38
  root = QVBoxLayout(self)
38
39
 
39
40
  # radios