setiastrosuitepro 1.6.7__py3-none-any.whl → 1.7.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 (68) hide show
  1. setiastro/images/abeicon.svg +16 -0
  2. setiastro/images/colorwheel.svg +97 -0
  3. setiastro/images/cosmic.svg +40 -0
  4. setiastro/images/cosmicsat.svg +24 -0
  5. setiastro/images/graxpert.svg +19 -0
  6. setiastro/images/linearfit.svg +32 -0
  7. setiastro/images/narrowbandnormalization.png +0 -0
  8. setiastro/images/pixelmath.svg +42 -0
  9. setiastro/images/planetarystacker.png +0 -0
  10. setiastro/saspro/__main__.py +1 -1
  11. setiastro/saspro/_generated/build_info.py +2 -2
  12. setiastro/saspro/aberration_ai.py +49 -11
  13. setiastro/saspro/aberration_ai_preset.py +29 -3
  14. setiastro/saspro/add_stars.py +29 -5
  15. setiastro/saspro/backgroundneutral.py +73 -33
  16. setiastro/saspro/blink_comparator_pro.py +150 -55
  17. setiastro/saspro/convo.py +9 -6
  18. setiastro/saspro/cosmicclarity.py +125 -18
  19. setiastro/saspro/crop_dialog_pro.py +96 -2
  20. setiastro/saspro/curve_editor_pro.py +132 -61
  21. setiastro/saspro/curves_preset.py +249 -47
  22. setiastro/saspro/doc_manager.py +178 -11
  23. setiastro/saspro/frequency_separation.py +1159 -208
  24. setiastro/saspro/gui/main_window.py +340 -88
  25. setiastro/saspro/gui/mixins/dock_mixin.py +245 -24
  26. setiastro/saspro/gui/mixins/file_mixin.py +35 -16
  27. setiastro/saspro/gui/mixins/menu_mixin.py +31 -1
  28. setiastro/saspro/gui/mixins/theme_mixin.py +160 -14
  29. setiastro/saspro/gui/mixins/toolbar_mixin.py +132 -10
  30. setiastro/saspro/gui/mixins/update_mixin.py +121 -33
  31. setiastro/saspro/histogram.py +179 -7
  32. setiastro/saspro/imageops/narrowband_normalization.py +816 -0
  33. setiastro/saspro/imageops/serloader.py +769 -0
  34. setiastro/saspro/imageops/starbasedwhitebalance.py +23 -52
  35. setiastro/saspro/imageops/stretch.py +582 -62
  36. setiastro/saspro/layers.py +13 -9
  37. setiastro/saspro/layers_dock.py +183 -3
  38. setiastro/saspro/legacy/numba_utils.py +68 -48
  39. setiastro/saspro/live_stacking.py +181 -73
  40. setiastro/saspro/multiscale_decomp.py +77 -29
  41. setiastro/saspro/narrowband_normalization.py +1618 -0
  42. setiastro/saspro/numba_utils.py +72 -57
  43. setiastro/saspro/ops/commands.py +18 -18
  44. setiastro/saspro/ops/script_editor.py +5 -0
  45. setiastro/saspro/ops/scripts.py +119 -0
  46. setiastro/saspro/remove_green.py +1 -1
  47. setiastro/saspro/resources.py +4 -0
  48. setiastro/saspro/ser_stack_config.py +68 -0
  49. setiastro/saspro/ser_stacker.py +2245 -0
  50. setiastro/saspro/ser_stacker_dialog.py +1481 -0
  51. setiastro/saspro/ser_tracking.py +206 -0
  52. setiastro/saspro/serviewer.py +1242 -0
  53. setiastro/saspro/sfcc.py +602 -214
  54. setiastro/saspro/shortcuts.py +154 -25
  55. setiastro/saspro/signature_insert.py +688 -33
  56. setiastro/saspro/stacking_suite.py +853 -401
  57. setiastro/saspro/star_alignment.py +243 -122
  58. setiastro/saspro/stat_stretch.py +878 -131
  59. setiastro/saspro/subwindow.py +303 -74
  60. setiastro/saspro/whitebalance.py +24 -0
  61. setiastro/saspro/widgets/common_utilities.py +28 -21
  62. setiastro/saspro/widgets/resource_monitor.py +128 -80
  63. {setiastrosuitepro-1.6.7.dist-info → setiastrosuitepro-1.7.0.dist-info}/METADATA +2 -2
  64. {setiastrosuitepro-1.6.7.dist-info → setiastrosuitepro-1.7.0.dist-info}/RECORD +68 -51
  65. {setiastrosuitepro-1.6.7.dist-info → setiastrosuitepro-1.7.0.dist-info}/WHEEL +0 -0
  66. {setiastrosuitepro-1.6.7.dist-info → setiastrosuitepro-1.7.0.dist-info}/entry_points.txt +0 -0
  67. {setiastrosuitepro-1.6.7.dist-info → setiastrosuitepro-1.7.0.dist-info}/licenses/LICENSE +0 -0
  68. {setiastrosuitepro-1.6.7.dist-info → setiastrosuitepro-1.7.0.dist-info}/licenses/license.txt +0 -0
@@ -503,7 +503,6 @@ class DraggableToolBar(QToolBar):
503
503
 
504
504
  m.exec(gpos)
505
505
 
506
-
507
506
  def contextMenuEvent(self, ev):
508
507
  # Right-click on empty toolbar area
509
508
  m = QMenu(self)
@@ -513,12 +512,12 @@ class DraggableToolBar(QToolBar):
513
512
  act_lock = m.addAction(self.tr("Lock Toolbar Icons"))
514
513
  act_lock.setCheckable(True)
515
514
  act_lock.setChecked(is_locked)
516
-
515
+
517
516
  def _toggle_lock(checked):
518
517
  self._set_locked(checked)
519
-
518
+
520
519
  act_lock.triggered.connect(_toggle_lock)
521
-
520
+
522
521
  m.addSeparator()
523
522
 
524
523
  # Submenu listing hidden actions for this toolbar
@@ -529,12 +528,13 @@ class DraggableToolBar(QToolBar):
529
528
  any_hidden = False
530
529
  if tb_hidden:
531
530
  for act in tb_hidden.actions():
532
- # Skip separators
533
531
  if act.isSeparator():
534
532
  continue
535
533
  any_hidden = True
536
- sub.addAction(act.text() or (act.property("command_id") or act.objectName() or "item"),
537
- lambda a=act: mw._unhide_action_from_hidden_toolbar(a))
534
+ sub.addAction(
535
+ act.text() or (act.property("command_id") or act.objectName() or "item"),
536
+ lambda a=act: mw._unhide_action_from_hidden_toolbar(a)
537
+ )
538
538
 
539
539
  if not any_hidden:
540
540
  sub.setEnabled(False)
@@ -542,8 +542,15 @@ class DraggableToolBar(QToolBar):
542
542
  m.addSeparator()
543
543
  m.addAction(self.tr("Reset hidden icons"), self._reset_hidden_icons)
544
544
 
545
+ # ✅ NEW: Factory reset for all toolbars
546
+ m.addSeparator()
547
+ reset_all = m.addAction(self.tr("Reset ALL Toolbars (Factory Layout)"))
548
+ reset_all.setStatusTip(self.tr("Clears saved toolbar positions/orders/hidden state and restores defaults"))
549
+ reset_all.triggered.connect(lambda: getattr(self.window(), "_reset_all_toolbars_to_factory", lambda: None)())
550
+
545
551
  m.exec(ev.globalPos())
546
552
 
553
+
547
554
  def _reset_hidden_icons(self):
548
555
  mw = self.window()
549
556
  tb_hidden = getattr(mw, "_hidden_toolbar", lambda: None)()
@@ -1033,17 +1040,14 @@ class ShortcutCanvas(QWidget):
1033
1040
  return False
1034
1041
  sw = self._top_subwindow_at(e.position().toPoint())
1035
1042
  if sw is None:
1036
- print("[ShortcutCanvas] _forward_command_drop: no subwindow under cursor", flush=True)
1037
- QApplication.processEvents()
1043
+
1038
1044
  return False
1039
1045
  try:
1040
1046
  raw = bytes(md.data(MIME_CMD))
1041
1047
  payload = _unpack_cmd_payload(raw) # your existing helper
1042
- print(f"[ShortcutCanvas] _forward_command_drop → subwin={sw}, payload={payload!r}", flush=True)
1043
- QApplication.processEvents()
1048
+
1044
1049
  except Exception as ex:
1045
- print(f"[ShortcutCanvas] _forward_command_drop: failed to unpack payload: {ex!r}", flush=True)
1046
- QApplication.processEvents()
1050
+
1047
1051
  return False
1048
1052
  self._mgr.apply_command_to_subwindow(sw, payload)
1049
1053
  e.acceptProposedAction()
@@ -1545,6 +1549,7 @@ class ShortcutManager:
1545
1549
 
1546
1550
  # ---- persistence (QSettings JSON blob) ----
1547
1551
  def save_shortcuts(self):
1552
+
1548
1553
  data = []
1549
1554
  for sid, w in list(self.widgets.items()):
1550
1555
  if _is_dead(w):
@@ -1845,6 +1850,7 @@ class ShortcutManager:
1845
1850
 
1846
1851
 
1847
1852
  def clear(self):
1853
+
1848
1854
  for sid, w in list(self.widgets.items()):
1849
1855
  try:
1850
1856
  if not _is_dead(w):
@@ -1919,50 +1925,173 @@ class ShortcutManager:
1919
1925
  # legacy single-remove (kept for callers)
1920
1926
  self.delete_by_id(sid, persist=True)
1921
1927
 
1922
-
1923
1928
  class _StatStretchPresetDialog(QDialog):
1929
+ """
1930
+ Preset editor for headless replay: command_id="stat_stretch"
1931
+
1932
+ Keys supported:
1933
+ target_median: float
1934
+ linked: bool
1935
+ normalize: bool
1936
+ apply_curves: bool
1937
+ curves_boost: float # 0..1
1938
+ blackpoint_sigma: float # 0..1 (matches your slider/100)
1939
+ no_black_clip: bool
1940
+ hdr_compress: bool
1941
+ hdr_amount: float # 0..1
1942
+ hdr_knee: float # 0..1
1943
+ luma_only: bool
1944
+ luma_mode: str # e.g. "rec709"
1945
+ luma_blend: float #0..1 (0=normal linked, 1=pure luma-only)
1946
+ """
1924
1947
  def __init__(self, parent=None, initial: dict | None = None):
1925
1948
  super().__init__(parent)
1926
1949
  self.setWindowTitle("Statistical Stretch — Preset")
1927
1950
  init = dict(initial or {})
1928
1951
 
1952
+ # --- Target median ---
1929
1953
  self.spin_target = QDoubleSpinBox()
1930
- self.spin_target.setRange(0.0, 1.0); self.spin_target.setDecimals(3)
1954
+ self.spin_target.setRange(0.0, 1.0)
1955
+ self.spin_target.setDecimals(3)
1931
1956
  self.spin_target.setSingleStep(0.01)
1932
1957
  self.spin_target.setValue(float(init.get("target_median", 0.25)))
1933
1958
 
1959
+ # --- Linked / Normalize ---
1934
1960
  self.chk_linked = QCheckBox("Linked RGB channels")
1935
1961
  self.chk_linked.setChecked(bool(init.get("linked", False)))
1936
1962
 
1937
1963
  self.chk_normalize = QCheckBox("Normalize to [0..1]")
1938
1964
  self.chk_normalize.setChecked(bool(init.get("normalize", False)))
1939
1965
 
1966
+ # --- Curves ---
1967
+ self.chk_curves = QCheckBox("Apply Curves")
1968
+ self.chk_curves.setChecked(bool(init.get("apply_curves", False)))
1969
+
1940
1970
  self.spin_curves = QDoubleSpinBox()
1941
- self.spin_curves.setRange(0.0, 1.0); self.spin_curves.setDecimals(2)
1971
+ self.spin_curves.setRange(0.0, 1.0)
1972
+ self.spin_curves.setDecimals(2)
1942
1973
  self.spin_curves.setSingleStep(0.05)
1943
- self.spin_curves.setValue(float(init.get("curves_boost", 0.0 if not init.get("apply_curves") else 0.20)))
1974
+ self.spin_curves.setValue(float(init.get("curves_boost", 0.0)))
1975
+ self.spin_curves.setEnabled(self.chk_curves.isChecked())
1976
+ self.chk_curves.toggled.connect(self.spin_curves.setEnabled)
1977
+
1978
+ # --- Blackpoint sigma ---
1979
+ self.spin_bp = QDoubleSpinBox()
1980
+ self.spin_bp.setRange(0.0, 1.0)
1981
+ self.spin_bp.setDecimals(2)
1982
+ self.spin_bp.setSingleStep(0.05)
1983
+ self.spin_bp.setValue(float(init.get("blackpoint_sigma", 0.0)))
1984
+
1985
+ self.chk_no_black_clip = QCheckBox("No black clip")
1986
+ self.chk_no_black_clip.setChecked(bool(init.get("no_black_clip", False)))
1987
+
1988
+ # --- HDR compress ---
1989
+ self.chk_hdr = QCheckBox("HDR compression")
1990
+ self.chk_hdr.setChecked(bool(init.get("hdr_compress", False)))
1991
+
1992
+ self.spin_hdr_amt = QDoubleSpinBox()
1993
+ self.spin_hdr_amt.setRange(0.0, 1.0)
1994
+ self.spin_hdr_amt.setDecimals(2)
1995
+ self.spin_hdr_amt.setSingleStep(0.05)
1996
+ self.spin_hdr_amt.setValue(float(init.get("hdr_amount", 0.0)))
1997
+
1998
+ self.spin_hdr_knee = QDoubleSpinBox()
1999
+ self.spin_hdr_knee.setRange(0.0, 1.0)
2000
+ self.spin_hdr_knee.setDecimals(2)
2001
+ self.spin_hdr_knee.setSingleStep(0.05)
2002
+ self.spin_hdr_knee.setValue(float(init.get("hdr_knee", 0.5)))
2003
+
2004
+ def _set_hdr_enabled(on: bool):
2005
+ on = bool(on)
2006
+ self.spin_hdr_amt.setEnabled(on)
2007
+ self.spin_hdr_knee.setEnabled(on)
2008
+
2009
+ _set_hdr_enabled(self.chk_hdr.isChecked())
2010
+ self.chk_hdr.toggled.connect(_set_hdr_enabled)
2011
+
2012
+ # --- Luma only ---
2013
+ self.chk_luma_only = QCheckBox("Luma-only mode")
2014
+ self.chk_luma_only.setChecked(bool(init.get("luma_only", False)))
2015
+
2016
+ self.cmb_luma = QComboBox()
2017
+ # keep in sync with your tool’s supported modes
2018
+ self.cmb_luma.addItems(["rec709", "avg", "hsp", "max"])
2019
+ init_mode = str(init.get("luma_mode", "rec709") or "rec709")
2020
+ idx = self.cmb_luma.findText(init_mode)
2021
+ if idx >= 0:
2022
+ self.cmb_luma.setCurrentIndex(idx)
2023
+
2024
+ self.spin_luma_blend = QDoubleSpinBox()
2025
+ self.spin_luma_blend.setRange(0.0, 1.0)
2026
+ self.spin_luma_blend.setDecimals(2)
2027
+ self.spin_luma_blend.setSingleStep(0.05)
2028
+ self.spin_luma_blend.setValue(float(init.get("luma_blend", 0.70)))
2029
+
2030
+ def _set_luma_enabled(on: bool):
2031
+ on = bool(on)
2032
+ self.cmb_luma.setEnabled(on)
2033
+ self.spin_luma_blend.setEnabled(on)
2034
+
2035
+ _set_luma_enabled(self.chk_luma_only.isChecked())
2036
+ self.chk_luma_only.toggled.connect(_set_luma_enabled)
2037
+
2038
+ # --- Layout ---
2039
+ form = QFormLayout()
1944
2040
 
1945
- form = QFormLayout(self)
1946
2041
  form.addRow("Target median:", self.spin_target)
1947
2042
  form.addRow("", self.chk_linked)
1948
2043
  form.addRow("", self.chk_normalize)
2044
+
2045
+ form.addRow("", QLabel("— Tone shaping —"))
2046
+ form.addRow("", self.chk_curves)
1949
2047
  form.addRow("Curves boost (0–1):", self.spin_curves)
1950
- form.addRow(QLabel("Curves are applied only if boost > 0."))
1951
2048
 
1952
- btns = QDialogButtonBox(QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel, parent=self)
1953
- btns.accepted.connect(self.accept); btns.rejected.connect(self.reject)
2049
+ form.addRow("", QLabel("— Blackpoint / HDR —"))
2050
+ form.addRow("Blackpoint σ (0–1):", self.spin_bp)
2051
+ form.addRow("", self.chk_no_black_clip)
2052
+
2053
+ form.addRow("", self.chk_hdr)
2054
+ form.addRow("HDR amount (0–1):", self.spin_hdr_amt)
2055
+ form.addRow("HDR knee (0–1):", self.spin_hdr_knee)
2056
+
2057
+ form.addRow("", QLabel("— Luma mode —"))
2058
+ form.addRow("", self.chk_luma_only)
2059
+ form.addRow("Luma mode:", self.cmb_luma)
2060
+ form.addRow("Luma blend (0–1):", self.spin_luma_blend)
2061
+ btns = QDialogButtonBox(
2062
+ QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel,
2063
+ parent=self
2064
+ )
2065
+ btns.accepted.connect(self.accept)
2066
+ btns.rejected.connect(self.reject)
1954
2067
  form.addRow(btns)
1955
2068
 
2069
+ self.setLayout(form)
2070
+
1956
2071
  def result_dict(self) -> dict:
1957
- boost = float(self.spin_curves.value())
2072
+ hdr_on = bool(self.chk_hdr.isChecked())
2073
+ curves_on = bool(self.chk_curves.isChecked())
2074
+ luma_on = bool(self.chk_luma_only.isChecked())
2075
+
1958
2076
  return {
1959
2077
  "target_median": float(self.spin_target.value()),
1960
2078
  "linked": bool(self.chk_linked.isChecked()),
1961
2079
  "normalize": bool(self.chk_normalize.isChecked()),
1962
- "apply_curves": bool(boost > 0.0),
1963
- "curves_boost": boost,
2080
+
2081
+ "apply_curves": curves_on,
2082
+ "curves_boost": float(self.spin_curves.value()) if curves_on else 0.0,
2083
+
2084
+ "blackpoint_sigma": float(self.spin_bp.value()),
2085
+ "no_black_clip": bool(self.chk_no_black_clip.isChecked()),
2086
+
2087
+ "hdr_compress": hdr_on,
2088
+ "hdr_amount": float(self.spin_hdr_amt.value()) if hdr_on else 0.0,
2089
+ "hdr_knee": float(self.spin_hdr_knee.value()) if hdr_on else 0.0,
2090
+
2091
+ "luma_only": luma_on,
2092
+ "luma_mode": str(self.cmb_luma.currentText()) if luma_on else "rec709",
2093
+ "luma_blend": float(self.spin_luma_blend.value()) if luma_on else 0.0,
1964
2094
  }
1965
-
1966
2095
 
1967
2096
  class _StarStretchPresetDialog(QDialog):
1968
2097
  def __init__(self, parent=None, initial: dict | None = None):