setiastrosuitepro 1.6.4__py3-none-any.whl → 1.7.1.post2__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 (132) hide show
  1. setiastro/images/TextureClarity.svg +56 -0
  2. setiastro/images/abeicon.svg +16 -0
  3. setiastro/images/acv_icon.png +0 -0
  4. setiastro/images/colorwheel.svg +97 -0
  5. setiastro/images/cosmic.svg +40 -0
  6. setiastro/images/cosmicsat.svg +24 -0
  7. setiastro/images/first_quarter.png +0 -0
  8. setiastro/images/full_moon.png +0 -0
  9. setiastro/images/graxpert.svg +19 -0
  10. setiastro/images/last_quarter.png +0 -0
  11. setiastro/images/linearfit.svg +32 -0
  12. setiastro/images/narrowbandnormalization.png +0 -0
  13. setiastro/images/new_moon.png +0 -0
  14. setiastro/images/pixelmath.svg +42 -0
  15. setiastro/images/planetarystacker.png +0 -0
  16. setiastro/images/waning_crescent_1.png +0 -0
  17. setiastro/images/waning_crescent_2.png +0 -0
  18. setiastro/images/waning_crescent_3.png +0 -0
  19. setiastro/images/waning_crescent_4.png +0 -0
  20. setiastro/images/waning_crescent_5.png +0 -0
  21. setiastro/images/waning_gibbous_1.png +0 -0
  22. setiastro/images/waning_gibbous_2.png +0 -0
  23. setiastro/images/waning_gibbous_3.png +0 -0
  24. setiastro/images/waning_gibbous_4.png +0 -0
  25. setiastro/images/waning_gibbous_5.png +0 -0
  26. setiastro/images/waxing_crescent_1.png +0 -0
  27. setiastro/images/waxing_crescent_2.png +0 -0
  28. setiastro/images/waxing_crescent_3.png +0 -0
  29. setiastro/images/waxing_crescent_4.png +0 -0
  30. setiastro/images/waxing_crescent_5.png +0 -0
  31. setiastro/images/waxing_gibbous_1.png +0 -0
  32. setiastro/images/waxing_gibbous_2.png +0 -0
  33. setiastro/images/waxing_gibbous_3.png +0 -0
  34. setiastro/images/waxing_gibbous_4.png +0 -0
  35. setiastro/images/waxing_gibbous_5.png +0 -0
  36. setiastro/qml/ResourceMonitor.qml +84 -82
  37. setiastro/saspro/__main__.py +20 -1
  38. setiastro/saspro/_generated/build_info.py +2 -2
  39. setiastro/saspro/abe.py +37 -4
  40. setiastro/saspro/aberration_ai.py +364 -33
  41. setiastro/saspro/aberration_ai_preset.py +29 -3
  42. setiastro/saspro/acv_exporter.py +379 -0
  43. setiastro/saspro/add_stars.py +33 -6
  44. setiastro/saspro/astrospike_python.py +45 -3
  45. setiastro/saspro/backgroundneutral.py +108 -40
  46. setiastro/saspro/blemish_blaster.py +4 -1
  47. setiastro/saspro/blink_comparator_pro.py +150 -55
  48. setiastro/saspro/clahe.py +4 -1
  49. setiastro/saspro/continuum_subtract.py +4 -1
  50. setiastro/saspro/convo.py +13 -7
  51. setiastro/saspro/cosmicclarity.py +129 -18
  52. setiastro/saspro/crop_dialog_pro.py +123 -7
  53. setiastro/saspro/curve_editor_pro.py +181 -64
  54. setiastro/saspro/curves_preset.py +249 -47
  55. setiastro/saspro/doc_manager.py +245 -15
  56. setiastro/saspro/exoplanet_detector.py +120 -28
  57. setiastro/saspro/frequency_separation.py +1158 -204
  58. setiastro/saspro/ghs_dialog_pro.py +81 -16
  59. setiastro/saspro/graxpert.py +1 -0
  60. setiastro/saspro/gui/main_window.py +706 -264
  61. setiastro/saspro/gui/mixins/dock_mixin.py +245 -24
  62. setiastro/saspro/gui/mixins/file_mixin.py +35 -16
  63. setiastro/saspro/gui/mixins/menu_mixin.py +35 -1
  64. setiastro/saspro/gui/mixins/theme_mixin.py +160 -14
  65. setiastro/saspro/gui/mixins/toolbar_mixin.py +499 -24
  66. setiastro/saspro/gui/mixins/update_mixin.py +138 -36
  67. setiastro/saspro/gui/mixins/view_mixin.py +42 -0
  68. setiastro/saspro/halobgon.py +4 -0
  69. setiastro/saspro/histogram.py +184 -8
  70. setiastro/saspro/image_combine.py +4 -0
  71. setiastro/saspro/image_peeker_pro.py +4 -0
  72. setiastro/saspro/imageops/narrowband_normalization.py +816 -0
  73. setiastro/saspro/imageops/serloader.py +1345 -0
  74. setiastro/saspro/imageops/starbasedwhitebalance.py +23 -52
  75. setiastro/saspro/imageops/stretch.py +582 -62
  76. setiastro/saspro/isophote.py +4 -0
  77. setiastro/saspro/layers.py +13 -9
  78. setiastro/saspro/layers_dock.py +183 -3
  79. setiastro/saspro/legacy/image_manager.py +154 -20
  80. setiastro/saspro/legacy/numba_utils.py +68 -48
  81. setiastro/saspro/legacy/xisf.py +240 -98
  82. setiastro/saspro/live_stacking.py +203 -82
  83. setiastro/saspro/luminancerecombine.py +228 -27
  84. setiastro/saspro/mask_creation.py +174 -15
  85. setiastro/saspro/mfdeconv.py +113 -35
  86. setiastro/saspro/mfdeconvcudnn.py +119 -70
  87. setiastro/saspro/mfdeconvsport.py +112 -35
  88. setiastro/saspro/morphology.py +4 -0
  89. setiastro/saspro/multiscale_decomp.py +81 -29
  90. setiastro/saspro/narrowband_normalization.py +1618 -0
  91. setiastro/saspro/numba_utils.py +72 -57
  92. setiastro/saspro/ops/commands.py +18 -18
  93. setiastro/saspro/ops/script_editor.py +10 -2
  94. setiastro/saspro/ops/scripts.py +122 -0
  95. setiastro/saspro/perfect_palette_picker.py +37 -3
  96. setiastro/saspro/plate_solver.py +84 -49
  97. setiastro/saspro/psf_viewer.py +119 -37
  98. setiastro/saspro/remove_green.py +1 -1
  99. setiastro/saspro/resources.py +73 -0
  100. setiastro/saspro/rgbalign.py +460 -12
  101. setiastro/saspro/selective_color.py +4 -1
  102. setiastro/saspro/ser_stack_config.py +82 -0
  103. setiastro/saspro/ser_stacker.py +2321 -0
  104. setiastro/saspro/ser_stacker_dialog.py +1838 -0
  105. setiastro/saspro/ser_tracking.py +206 -0
  106. setiastro/saspro/serviewer.py +1625 -0
  107. setiastro/saspro/sfcc.py +662 -216
  108. setiastro/saspro/shortcuts.py +171 -33
  109. setiastro/saspro/signature_insert.py +692 -33
  110. setiastro/saspro/stacking_suite.py +1347 -485
  111. setiastro/saspro/star_alignment.py +247 -123
  112. setiastro/saspro/star_spikes.py +4 -0
  113. setiastro/saspro/star_stretch.py +38 -3
  114. setiastro/saspro/stat_stretch.py +892 -129
  115. setiastro/saspro/subwindow.py +787 -363
  116. setiastro/saspro/supernovaasteroidhunter.py +1 -1
  117. setiastro/saspro/texture_clarity.py +593 -0
  118. setiastro/saspro/wavescale_hdr.py +4 -1
  119. setiastro/saspro/wavescalede.py +4 -1
  120. setiastro/saspro/whitebalance.py +84 -12
  121. setiastro/saspro/widgets/common_utilities.py +28 -21
  122. setiastro/saspro/widgets/resource_monitor.py +209 -111
  123. setiastro/saspro/widgets/spinboxes.py +10 -13
  124. setiastro/saspro/wimi.py +27 -656
  125. setiastro/saspro/wims.py +13 -3
  126. setiastro/saspro/xisf.py +101 -11
  127. {setiastrosuitepro-1.6.4.dist-info → setiastrosuitepro-1.7.1.post2.dist-info}/METADATA +4 -2
  128. {setiastrosuitepro-1.6.4.dist-info → setiastrosuitepro-1.7.1.post2.dist-info}/RECORD +132 -87
  129. {setiastrosuitepro-1.6.4.dist-info → setiastrosuitepro-1.7.1.post2.dist-info}/WHEEL +0 -0
  130. {setiastrosuitepro-1.6.4.dist-info → setiastrosuitepro-1.7.1.post2.dist-info}/entry_points.txt +0 -0
  131. {setiastrosuitepro-1.6.4.dist-info → setiastrosuitepro-1.7.1.post2.dist-info}/licenses/LICENSE +0 -0
  132. {setiastrosuitepro-1.6.4.dist-info → setiastrosuitepro-1.7.1.post2.dist-info}/licenses/license.txt +0 -0
@@ -30,10 +30,10 @@ cached_star_sources: Optional[np.ndarray] = None
30
30
  cached_flux_radii: Optional[np.ndarray] = None
31
31
 
32
32
 
33
- def _tone_preserve_bg_neutralize(rgb: np.ndarray) -> np.ndarray:
33
+ def _tone_preserve_bg_neutralize(rgb: np.ndarray, *, return_pivot: bool = False):
34
34
  """
35
35
  Neutralize background using the darkest grid patch in a tone-preserving way.
36
- Operates in-place on a copy; returns the neutralized image (float32 [0,1]).
36
+ Returns float32 RGB in [0,1]. If return_pivot, also returns the patch median (pivot).
37
37
  """
38
38
  h, w = rgb.shape[:2]
39
39
  patch_size = 10
@@ -56,12 +56,15 @@ def _tone_preserve_bg_neutralize(rgb: np.ndarray) -> np.ndarray:
56
56
  out = rgb.copy()
57
57
  if best is not None:
58
58
  avg = float(np.mean(best))
59
- # “tone-preserving” shift+scale channel-wise toward avg
60
59
  for c in range(3):
61
60
  diff = float(best[c] - avg)
62
61
  denom = (1.0 - diff) if abs(1.0 - diff) > 1e-8 else 1e-8
63
62
  out[:, :, c] = np.clip((out[:, :, c] - diff) / denom, 0.0, 1.0)
64
- return out
63
+
64
+ if return_pivot:
65
+ pivot = best.astype(np.float32) if best is not None else np.median(rgb, axis=(0, 1)).astype(np.float32)
66
+ return out.astype(np.float32, copy=False), pivot
67
+ return out.astype(np.float32, copy=False)
65
68
 
66
69
 
67
70
  def apply_star_based_white_balance(
@@ -73,38 +76,16 @@ def apply_star_based_white_balance(
73
76
  ) -> Tuple[np.ndarray, int, np.ndarray, np.ndarray, np.ndarray] | Tuple[np.ndarray, int, np.ndarray]:
74
77
  """
75
78
  Star-based white balance with background neutralization and an RGB overlay of detected stars.
76
-
77
- Parameters
78
- ----------
79
- image : np.ndarray
80
- RGB image (any dtype). Assumed RGB ordering.
81
- threshold : float
82
- SExtractor detection threshold (in background sigma).
83
- autostretch : bool
84
- If True, overlay is built from an autostretched view for visibility.
85
- reuse_cached_sources : bool
86
- If True, reuses star positions measured on a previous call (same scene).
87
- return_star_colors : bool
88
- If True, also returns (raw_star_pixels, after_star_pixels).
89
-
90
- Returns
91
- -------
92
- balanced_rgb : float32 RGB in [0,1]
93
- star_count : int
94
- overlay_rgb : float32 RGB in [0,1] with star ellipses drawn
95
- (optional) raw_star_pixels : (N,3) float array, colors sampled from ORIGINAL image
96
- (optional) after_star_pixels : (N,3) float array, colors sampled after WB
79
+ (Correct version: does NOT crush data below the pivot.)
97
80
  """
98
81
  if image.ndim != 3 or image.shape[2] != 3:
99
82
  raise ValueError("apply_star_based_white_balance: input must be an RGB image (H,W,3).")
100
83
 
101
- # 0) normalize
102
84
  img_rgb = _to_float01(image)
103
85
 
104
- # 1) first background neutralization (tone-preserving)
105
- bg_neutral = _tone_preserve_bg_neutralize(img_rgb)
86
+ # 1) background neutralization + pivot (per-channel medians of darkest patch)
87
+ bg_neutral, pivot = _tone_preserve_bg_neutralize(img_rgb, return_pivot=True)
106
88
 
107
- # 2) detect / reuse star positions
108
89
  if sep is None:
109
90
  raise ImportError(
110
91
  "apply_star_based_white_balance requires the 'sep' package. "
@@ -135,7 +116,6 @@ def apply_star_based_white_balance(
135
116
  cached_star_sources = sources
136
117
  cached_flux_radii = r
137
118
 
138
- # filter: small-ish, star-like
139
119
  mask = (r > 0) & (r <= 10)
140
120
  sources = sources[mask]
141
121
  r = r[mask]
@@ -143,15 +123,14 @@ def apply_star_based_white_balance(
143
123
  raise ValueError("All detected sources were rejected as non-stellar (too large).")
144
124
 
145
125
  h, w = gray.shape
146
- # raw colors from ORIGINAL image - optimized vectorized extraction
147
126
  xs = sources["x"].astype(np.int32)
148
127
  ys = sources["y"].astype(np.int32)
149
128
  valid = (xs >= 0) & (xs < w) & (ys >= 0) & (ys < h)
129
+
150
130
  raw_star_pixels = img_rgb[ys[valid], xs[valid], :]
151
131
 
152
- # 3) build overlay (autostretched if requested) and draw ellipses
132
+ # overlay
153
133
  disp = stretch_color_image(bg_neutral.copy(), 0.25) if autostretch else bg_neutral.copy()
154
-
155
134
  if cv2 is not None:
156
135
  overlay_bgr = cv2.cvtColor((disp * 255).astype(np.uint8), cv2.COLOR_RGB2BGR)
157
136
  for i in range(len(sources)):
@@ -160,41 +139,35 @@ def apply_star_based_white_balance(
160
139
  theta_deg = float(sources["theta"][i] * 180.0 / np.pi)
161
140
  center = (int(round(cx)), int(round(cy)))
162
141
  axes = (max(1, int(round(3 * a))), max(1, int(round(3 * b))))
163
- # red ellipse in BGR
164
142
  cv2.ellipse(overlay_bgr, center, axes, angle=theta_deg, startAngle=0, endAngle=360,
165
143
  color=(0, 0, 255), thickness=1)
166
144
  overlay_rgb = cv2.cvtColor(overlay_bgr, cv2.COLOR_BGR2RGB).astype(np.float32) / 255.0
167
145
  else:
168
- # fallback: no ellipses, just the display image
169
146
  overlay_rgb = disp.astype(np.float32, copy=False)
170
147
 
171
- # 4) compute WB scale using star colors sampled on bg_neutral image
172
- # Optimized: vectorized extraction instead of Python loop (10-50x faster)
173
- xs = sources["x"].astype(np.int32)
174
- ys = sources["y"].astype(np.int32)
175
- valid_mask = (xs >= 0) & (xs < w) & (ys >= 0) & (ys < h)
176
-
148
+ # star pixels for WB
149
+ valid_mask = valid
177
150
  if not np.any(valid_mask):
178
151
  raise ValueError("No stellar samples available for white balance.")
179
-
152
+
180
153
  star_pixels = bg_neutral[ys[valid_mask], xs[valid_mask], :].astype(np.float32)
181
154
  avg_color = np.mean(star_pixels, axis=0)
182
155
  max_val = float(np.max(avg_color))
183
- # protect against divide-by-zero
184
156
  avg_color = np.where(avg_color <= 1e-8, 1e-8, avg_color)
185
- scaling = max_val / avg_color
157
+ scaling = (max_val / avg_color).astype(np.float32) # (3,)
186
158
 
187
- balanced = (bg_neutral * scaling.reshape((1, 1, 3))).clip(0.0, 1.0)
159
+ # Correct median-locked WB (NO hard floor)
160
+ m = pivot.reshape((1, 1, 3)).astype(np.float32)
161
+ g = scaling.reshape((1, 1, 3)).astype(np.float32)
188
162
 
189
- # 5) second background neutralization pass on balanced image
190
- balanced = _tone_preserve_bg_neutralize(balanced)
163
+ balanced = (bg_neutral.astype(np.float32) - m) * g + m
164
+ balanced = np.clip(balanced, 0.0, 1.0).astype(np.float32, copy=False)
191
165
 
192
- # 6) collect after-WB star samples - optimized vectorized extraction
193
166
  after_star_pixels = balanced[ys[valid_mask], xs[valid_mask], :]
194
167
 
195
168
  if return_star_colors:
196
169
  return (
197
- balanced.astype(np.float32, copy=False),
170
+ balanced,
198
171
  int(len(star_pixels)),
199
172
  overlay_rgb.astype(np.float32, copy=False),
200
173
  np.asarray(raw_star_pixels, dtype=np.float32),
@@ -202,9 +175,7 @@ def apply_star_based_white_balance(
202
175
  )
203
176
 
204
177
  return (
205
- balanced.astype(np.float32, copy=False),
178
+ balanced,
206
179
  int(len(star_pixels)),
207
180
  overlay_rgb.astype(np.float32, copy=False),
208
181
  )
209
-
210
-