setiastrosuitepro 1.6.1.post1__py3-none-any.whl → 1.6.4__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.
Files changed (139) hide show
  1. setiastro/images/Background_startup.jpg +0 -0
  2. setiastro/images/rotatearbitrary.png +0 -0
  3. setiastro/qml/ResourceMonitor.qml +126 -0
  4. setiastro/saspro/__main__.py +162 -25
  5. setiastro/saspro/_generated/build_info.py +2 -1
  6. setiastro/saspro/abe.py +62 -11
  7. setiastro/saspro/aberration_ai.py +3 -3
  8. setiastro/saspro/add_stars.py +5 -2
  9. setiastro/saspro/astrobin_exporter.py +3 -0
  10. setiastro/saspro/astrospike_python.py +3 -1
  11. setiastro/saspro/autostretch.py +4 -2
  12. setiastro/saspro/backgroundneutral.py +60 -9
  13. setiastro/saspro/batch_convert.py +3 -0
  14. setiastro/saspro/batch_renamer.py +3 -0
  15. setiastro/saspro/blemish_blaster.py +3 -0
  16. setiastro/saspro/blink_comparator_pro.py +474 -251
  17. setiastro/saspro/cheat_sheet.py +50 -15
  18. setiastro/saspro/clahe.py +27 -1
  19. setiastro/saspro/comet_stacking.py +103 -38
  20. setiastro/saspro/convo.py +3 -0
  21. setiastro/saspro/copyastro.py +3 -0
  22. setiastro/saspro/cosmicclarity.py +70 -45
  23. setiastro/saspro/crop_dialog_pro.py +28 -1
  24. setiastro/saspro/curve_editor_pro.py +18 -0
  25. setiastro/saspro/debayer.py +3 -0
  26. setiastro/saspro/doc_manager.py +40 -17
  27. setiastro/saspro/fitsmodifier.py +3 -0
  28. setiastro/saspro/frequency_separation.py +8 -2
  29. setiastro/saspro/function_bundle.py +18 -16
  30. setiastro/saspro/generate_translations.py +715 -1
  31. setiastro/saspro/ghs_dialog_pro.py +3 -0
  32. setiastro/saspro/graxpert.py +3 -0
  33. setiastro/saspro/gui/main_window.py +364 -92
  34. setiastro/saspro/gui/mixins/dock_mixin.py +119 -7
  35. setiastro/saspro/gui/mixins/file_mixin.py +7 -0
  36. setiastro/saspro/gui/mixins/geometry_mixin.py +105 -5
  37. setiastro/saspro/gui/mixins/menu_mixin.py +29 -0
  38. setiastro/saspro/gui/mixins/toolbar_mixin.py +33 -10
  39. setiastro/saspro/gui/statistics_dialog.py +47 -0
  40. setiastro/saspro/halobgon.py +29 -3
  41. setiastro/saspro/histogram.py +3 -0
  42. setiastro/saspro/history_explorer.py +2 -0
  43. setiastro/saspro/i18n.py +22 -10
  44. setiastro/saspro/image_combine.py +3 -0
  45. setiastro/saspro/image_peeker_pro.py +3 -0
  46. setiastro/saspro/imageops/stretch.py +5 -13
  47. setiastro/saspro/isophote.py +3 -0
  48. setiastro/saspro/legacy/numba_utils.py +64 -47
  49. setiastro/saspro/linear_fit.py +3 -0
  50. setiastro/saspro/live_stacking.py +13 -2
  51. setiastro/saspro/mask_creation.py +3 -0
  52. setiastro/saspro/mfdeconv.py +5 -0
  53. setiastro/saspro/morphology.py +30 -5
  54. setiastro/saspro/multiscale_decomp.py +713 -256
  55. setiastro/saspro/nbtorgb_stars.py +12 -2
  56. setiastro/saspro/numba_utils.py +148 -47
  57. setiastro/saspro/ops/scripts.py +77 -17
  58. setiastro/saspro/ops/settings.py +1 -43
  59. setiastro/saspro/perfect_palette_picker.py +1 -0
  60. setiastro/saspro/pixelmath.py +6 -2
  61. setiastro/saspro/plate_solver.py +1 -0
  62. setiastro/saspro/remove_green.py +18 -1
  63. setiastro/saspro/remove_stars.py +136 -162
  64. setiastro/saspro/remove_stars_preset.py +55 -13
  65. setiastro/saspro/resources.py +36 -10
  66. setiastro/saspro/rgb_combination.py +1 -0
  67. setiastro/saspro/rgbalign.py +4 -4
  68. setiastro/saspro/save_options.py +1 -0
  69. setiastro/saspro/selective_color.py +79 -20
  70. setiastro/saspro/sfcc.py +50 -8
  71. setiastro/saspro/shortcuts.py +94 -21
  72. setiastro/saspro/signature_insert.py +3 -0
  73. setiastro/saspro/stacking_suite.py +924 -446
  74. setiastro/saspro/star_alignment.py +291 -331
  75. setiastro/saspro/star_spikes.py +116 -32
  76. setiastro/saspro/star_stretch.py +38 -1
  77. setiastro/saspro/stat_stretch.py +35 -3
  78. setiastro/saspro/status_log_dock.py +1 -1
  79. setiastro/saspro/subwindow.py +63 -2
  80. setiastro/saspro/supernovaasteroidhunter.py +3 -0
  81. setiastro/saspro/swap_manager.py +77 -42
  82. setiastro/saspro/translations/all_source_strings.json +4726 -0
  83. setiastro/saspro/translations/ar_translations.py +4096 -0
  84. setiastro/saspro/translations/de_translations.py +441 -446
  85. setiastro/saspro/translations/es_translations.py +278 -32
  86. setiastro/saspro/translations/fr_translations.py +280 -32
  87. setiastro/saspro/translations/hi_translations.py +3803 -0
  88. setiastro/saspro/translations/integrate_translations.py +38 -1
  89. setiastro/saspro/translations/it_translations.py +1211 -145
  90. setiastro/saspro/translations/ja_translations.py +556 -307
  91. setiastro/saspro/translations/pt_translations.py +3316 -3322
  92. setiastro/saspro/translations/ru_translations.py +3082 -0
  93. setiastro/saspro/translations/saspro_ar.qm +0 -0
  94. setiastro/saspro/translations/saspro_ar.ts +16019 -0
  95. setiastro/saspro/translations/saspro_de.qm +0 -0
  96. setiastro/saspro/translations/saspro_de.ts +14428 -133
  97. setiastro/saspro/translations/saspro_es.qm +0 -0
  98. setiastro/saspro/translations/saspro_es.ts +11503 -7821
  99. setiastro/saspro/translations/saspro_fr.qm +0 -0
  100. setiastro/saspro/translations/saspro_fr.ts +11168 -7812
  101. setiastro/saspro/translations/saspro_hi.qm +0 -0
  102. setiastro/saspro/translations/saspro_hi.ts +14855 -0
  103. setiastro/saspro/translations/saspro_it.qm +0 -0
  104. setiastro/saspro/translations/saspro_it.ts +14347 -7821
  105. setiastro/saspro/translations/saspro_ja.qm +0 -0
  106. setiastro/saspro/translations/saspro_ja.ts +14860 -137
  107. setiastro/saspro/translations/saspro_pt.qm +0 -0
  108. setiastro/saspro/translations/saspro_pt.ts +14904 -137
  109. setiastro/saspro/translations/saspro_ru.qm +0 -0
  110. setiastro/saspro/translations/saspro_ru.ts +11835 -0
  111. setiastro/saspro/translations/saspro_sw.qm +0 -0
  112. setiastro/saspro/translations/saspro_sw.ts +15237 -0
  113. setiastro/saspro/translations/saspro_uk.qm +0 -0
  114. setiastro/saspro/translations/saspro_uk.ts +15248 -0
  115. setiastro/saspro/translations/saspro_zh.qm +0 -0
  116. setiastro/saspro/translations/saspro_zh.ts +10581 -7812
  117. setiastro/saspro/translations/sw_translations.py +3897 -0
  118. setiastro/saspro/translations/uk_translations.py +3929 -0
  119. setiastro/saspro/translations/zh_translations.py +283 -32
  120. setiastro/saspro/versioning.py +36 -5
  121. setiastro/saspro/view_bundle.py +20 -17
  122. setiastro/saspro/wavescale_hdr.py +22 -1
  123. setiastro/saspro/wavescalede.py +23 -1
  124. setiastro/saspro/whitebalance.py +39 -3
  125. setiastro/saspro/widgets/minigame/game.js +991 -0
  126. setiastro/saspro/widgets/minigame/index.html +53 -0
  127. setiastro/saspro/widgets/minigame/style.css +241 -0
  128. setiastro/saspro/widgets/resource_monitor.py +263 -0
  129. setiastro/saspro/widgets/spinboxes.py +18 -0
  130. setiastro/saspro/widgets/wavelet_utils.py +52 -20
  131. setiastro/saspro/wimi.py +100 -80
  132. setiastro/saspro/wims.py +33 -33
  133. setiastro/saspro/window_shelf.py +2 -2
  134. {setiastrosuitepro-1.6.1.post1.dist-info → setiastrosuitepro-1.6.4.dist-info}/METADATA +15 -4
  135. {setiastrosuitepro-1.6.1.post1.dist-info → setiastrosuitepro-1.6.4.dist-info}/RECORD +139 -115
  136. {setiastrosuitepro-1.6.1.post1.dist-info → setiastrosuitepro-1.6.4.dist-info}/WHEEL +0 -0
  137. {setiastrosuitepro-1.6.1.post1.dist-info → setiastrosuitepro-1.6.4.dist-info}/entry_points.txt +0 -0
  138. {setiastrosuitepro-1.6.1.post1.dist-info → setiastrosuitepro-1.6.4.dist-info}/licenses/LICENSE +0 -0
  139. {setiastrosuitepro-1.6.1.post1.dist-info → setiastrosuitepro-1.6.4.dist-info}/licenses/license.txt +0 -0
@@ -42,12 +42,23 @@ def background_neutralize_rgb(img: np.ndarray, rect_xywh: tuple[int, int, int, i
42
42
 
43
43
  out = img.copy()
44
44
  eps = 1e-8
45
- for c in range(3):
46
- diff = float(medians[c] - avg_med)
47
- denom = 1.0 - diff
48
- if abs(denom) < eps:
49
- denom = eps if denom >= 0 else -eps
50
- out[..., c] = np.clip((out[..., c] - diff) / denom, 0.0, 1.0)
45
+
46
+ # Vectorized neutralization
47
+ # diff shape: (3,) -> (1, 1, 3)
48
+ diffs = (medians - avg_med).reshape(1, 1, 3)
49
+
50
+ # denom shape: (1, 1, 3)
51
+ denoms = 1.0 - diffs
52
+
53
+ # Avoid div-by-zero (vectorized)
54
+ # logic: if abs(denom) < eps, set to eps (sign matched)
55
+ # We can do this efficiently:
56
+ small_mask = np.abs(denoms) < eps
57
+ denoms[small_mask] = np.where(denoms[small_mask] >= 0, eps, -eps)
58
+
59
+ # Apply formula: (pixel - diff) / denom
60
+ out = (out - diffs) / denoms
61
+ out = np.clip(out, 0.0, 1.0)
51
62
 
52
63
  return out.astype(np.float32, copy=False)
53
64
 
@@ -237,14 +248,21 @@ def apply_background_neutral_to_doc(doc, preset: dict | None = None):
237
248
  class BackgroundNeutralizationDialog(QDialog):
238
249
  def __init__(self, parent, doc, icon: QIcon | None = None):
239
250
  super().__init__(parent)
251
+ self._main = parent
240
252
  self.doc = doc
253
+
254
+ # Connect to active document change signal
255
+ if hasattr(self._main, "currentDocumentChanged"):
256
+ self._main.currentDocumentChanged.connect(self._on_active_doc_changed)
257
+
241
258
  if icon:
242
259
  self.setWindowIcon(icon)
243
260
  self.setWindowTitle(self.tr("Background Neutralization"))
244
261
  self.resize(900, 600)
245
262
 
246
263
  self.setWindowFlag(Qt.WindowType.Window, True)
247
- self.setWindowModality(Qt.WindowModality.ApplicationModal)
264
+ # Non-modal: allow user to switch between images while dialog is open
265
+ self.setWindowModality(Qt.WindowModality.NonModal)
248
266
  self.setModal(False)
249
267
  #self.setAttribute(Qt.WidgetAttribute.WA_DeleteOnClose, True)
250
268
 
@@ -313,7 +331,14 @@ class BackgroundNeutralizationDialog(QDialog):
313
331
 
314
332
  self._load_image()
315
333
 
316
-
334
+ # ---- active document change ------------------------------------
335
+ def _on_active_doc_changed(self, doc):
336
+ """Called when user clicks a different image window."""
337
+ if doc is None or getattr(doc, "image", None) is None:
338
+ return
339
+ self.doc = doc
340
+ self.selection_item = None
341
+ self._load_image()
317
342
 
318
343
  # ---------- image display ----------
319
344
  def _doc_image_normalized(self) -> np.ndarray:
@@ -509,9 +534,35 @@ class BackgroundNeutralizationDialog(QDialog):
509
534
  metadata=meta,
510
535
  step_name="Background Neutralization",
511
536
  )
512
- self.accept()
537
+ # Dialog stays open so user can apply to other images
538
+ # Refresh to use the now-active document for next operation
539
+ self.accept() # or: self.close()
540
+
541
+ def closeEvent(self, e):
542
+ try:
543
+ if hasattr(self._main, "currentDocumentChanged"):
544
+ self._main.currentDocumentChanged.disconnect(self._on_active_doc_changed)
545
+ except Exception:
546
+ pass
547
+ super().closeEvent(e)
513
548
 
514
549
 
550
+ def _refresh_document_from_active(self):
551
+ """
552
+ Refresh the dialog's document reference to the currently active document.
553
+ This allows reusing the same dialog on different images.
554
+ """
555
+ try:
556
+ main = self.parent()
557
+ if main and hasattr(main, "_active_doc"):
558
+ new_doc = main._active_doc()
559
+ if new_doc is not None and new_doc is not self.doc:
560
+ self.doc = new_doc
561
+ # Refresh the preview image
562
+ self._load_preview()
563
+ except Exception:
564
+ pass
565
+
515
566
  def _zoom(self, factor: float):
516
567
  self._user_zoomed = True
517
568
  cur = self.graphics_view.transform().m11()
@@ -169,6 +169,9 @@ class BatchConvertDialog(QDialog):
169
169
  def __init__(self, parent=None):
170
170
  super().__init__(parent)
171
171
  self.setWindowTitle(self.tr("Batch Convert"))
172
+ self.setWindowFlag(Qt.WindowType.Window, True)
173
+ self.setWindowModality(Qt.WindowModality.NonModal)
174
+ self.setModal(False)
172
175
  self.setMinimumWidth(560)
173
176
  self.worker: _BatchWorker | None = None
174
177
 
@@ -46,6 +46,9 @@ class BatchRenamerDialog(QDialog):
46
46
  self.setWindowFlag(Qt.WindowType.WindowTitleHint, True)
47
47
  self.setWindowFlag(Qt.WindowType.WindowMinMaxButtonsHint, True)
48
48
  self.setWindowFlag(Qt.WindowType.WindowContextHelpButtonHint, False)
49
+ self.setWindowFlag(Qt.WindowType.Window, True)
50
+ self.setWindowModality(Qt.WindowModality.NonModal)
51
+ self.setModal(False)
49
52
  self.setSizeGripEnabled(True)
50
53
 
51
54
  self._build_ui()
@@ -155,6 +155,9 @@ class BlemishBlasterDialogPro(QDialog):
155
155
  def __init__(self, parent, doc):
156
156
  super().__init__(parent)
157
157
  self.setWindowTitle(self.tr("Blemish Blaster"))
158
+ self.setWindowFlag(Qt.WindowType.Window, True)
159
+ self.setWindowModality(Qt.WindowModality.NonModal)
160
+ self.setModal(False)
158
161
  self.setMinimumSize(900, 650)
159
162
 
160
163
  self._doc = doc