setiastrosuitepro 1.6.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.
- setiastro/__init__.py +2 -0
- setiastro/saspro/__init__.py +20 -0
- setiastro/saspro/__main__.py +784 -0
- setiastro/saspro/_generated/__init__.py +7 -0
- setiastro/saspro/_generated/build_info.py +2 -0
- setiastro/saspro/abe.py +1295 -0
- setiastro/saspro/abe_preset.py +196 -0
- setiastro/saspro/aberration_ai.py +694 -0
- setiastro/saspro/aberration_ai_preset.py +224 -0
- setiastro/saspro/accel_installer.py +218 -0
- setiastro/saspro/accel_workers.py +30 -0
- setiastro/saspro/add_stars.py +621 -0
- setiastro/saspro/astrobin_exporter.py +1007 -0
- setiastro/saspro/astrospike.py +153 -0
- setiastro/saspro/astrospike_python.py +1839 -0
- setiastro/saspro/autostretch.py +196 -0
- setiastro/saspro/backgroundneutral.py +560 -0
- setiastro/saspro/batch_convert.py +325 -0
- setiastro/saspro/batch_renamer.py +519 -0
- setiastro/saspro/blemish_blaster.py +488 -0
- setiastro/saspro/blink_comparator_pro.py +2923 -0
- setiastro/saspro/bundles.py +61 -0
- setiastro/saspro/bundles_dock.py +114 -0
- setiastro/saspro/cheat_sheet.py +168 -0
- setiastro/saspro/clahe.py +342 -0
- setiastro/saspro/comet_stacking.py +1377 -0
- setiastro/saspro/config.py +38 -0
- setiastro/saspro/config_bootstrap.py +40 -0
- setiastro/saspro/config_manager.py +316 -0
- setiastro/saspro/continuum_subtract.py +1617 -0
- setiastro/saspro/convo.py +1397 -0
- setiastro/saspro/convo_preset.py +414 -0
- setiastro/saspro/copyastro.py +187 -0
- setiastro/saspro/cosmicclarity.py +1564 -0
- setiastro/saspro/cosmicclarity_preset.py +407 -0
- setiastro/saspro/crop_dialog_pro.py +948 -0
- setiastro/saspro/crop_preset.py +189 -0
- setiastro/saspro/curve_editor_pro.py +2544 -0
- setiastro/saspro/curves_preset.py +375 -0
- setiastro/saspro/debayer.py +670 -0
- setiastro/saspro/debug_utils.py +29 -0
- setiastro/saspro/dnd_mime.py +35 -0
- setiastro/saspro/doc_manager.py +2634 -0
- setiastro/saspro/exoplanet_detector.py +2166 -0
- setiastro/saspro/file_utils.py +284 -0
- setiastro/saspro/fitsmodifier.py +744 -0
- setiastro/saspro/free_torch_memory.py +48 -0
- setiastro/saspro/frequency_separation.py +1343 -0
- setiastro/saspro/function_bundle.py +1594 -0
- setiastro/saspro/ghs_dialog_pro.py +660 -0
- setiastro/saspro/ghs_preset.py +284 -0
- setiastro/saspro/graxpert.py +634 -0
- setiastro/saspro/graxpert_preset.py +287 -0
- setiastro/saspro/gui/__init__.py +0 -0
- setiastro/saspro/gui/main_window.py +8494 -0
- setiastro/saspro/gui/mixins/__init__.py +33 -0
- setiastro/saspro/gui/mixins/dock_mixin.py +263 -0
- setiastro/saspro/gui/mixins/file_mixin.py +445 -0
- setiastro/saspro/gui/mixins/geometry_mixin.py +403 -0
- setiastro/saspro/gui/mixins/header_mixin.py +441 -0
- setiastro/saspro/gui/mixins/mask_mixin.py +421 -0
- setiastro/saspro/gui/mixins/menu_mixin.py +361 -0
- setiastro/saspro/gui/mixins/theme_mixin.py +367 -0
- setiastro/saspro/gui/mixins/toolbar_mixin.py +1324 -0
- setiastro/saspro/gui/mixins/update_mixin.py +309 -0
- setiastro/saspro/gui/mixins/view_mixin.py +435 -0
- setiastro/saspro/halobgon.py +462 -0
- setiastro/saspro/header_viewer.py +445 -0
- setiastro/saspro/headless_utils.py +88 -0
- setiastro/saspro/histogram.py +753 -0
- setiastro/saspro/history_explorer.py +939 -0
- setiastro/saspro/image_combine.py +414 -0
- setiastro/saspro/image_peeker_pro.py +1596 -0
- setiastro/saspro/imageops/__init__.py +37 -0
- setiastro/saspro/imageops/mdi_snap.py +292 -0
- setiastro/saspro/imageops/scnr.py +36 -0
- setiastro/saspro/imageops/starbasedwhitebalance.py +210 -0
- setiastro/saspro/imageops/stretch.py +244 -0
- setiastro/saspro/isophote.py +1179 -0
- setiastro/saspro/layers.py +208 -0
- setiastro/saspro/layers_dock.py +714 -0
- setiastro/saspro/lazy_imports.py +193 -0
- setiastro/saspro/legacy/__init__.py +2 -0
- setiastro/saspro/legacy/image_manager.py +2226 -0
- setiastro/saspro/legacy/numba_utils.py +3659 -0
- setiastro/saspro/legacy/xisf.py +1071 -0
- setiastro/saspro/linear_fit.py +534 -0
- setiastro/saspro/live_stacking.py +1830 -0
- setiastro/saspro/log_bus.py +5 -0
- setiastro/saspro/logging_config.py +460 -0
- setiastro/saspro/luminancerecombine.py +309 -0
- setiastro/saspro/main_helpers.py +201 -0
- setiastro/saspro/mask_creation.py +928 -0
- setiastro/saspro/masks_core.py +56 -0
- setiastro/saspro/mdi_widgets.py +353 -0
- setiastro/saspro/memory_utils.py +666 -0
- setiastro/saspro/metadata_patcher.py +75 -0
- setiastro/saspro/mfdeconv.py +3826 -0
- setiastro/saspro/mfdeconv_earlystop.py +71 -0
- setiastro/saspro/mfdeconvcudnn.py +3263 -0
- setiastro/saspro/mfdeconvsport.py +2382 -0
- setiastro/saspro/minorbodycatalog.py +567 -0
- setiastro/saspro/morphology.py +382 -0
- setiastro/saspro/multiscale_decomp.py +1290 -0
- setiastro/saspro/nbtorgb_stars.py +531 -0
- setiastro/saspro/numba_utils.py +3044 -0
- setiastro/saspro/numba_warmup.py +141 -0
- setiastro/saspro/ops/__init__.py +9 -0
- setiastro/saspro/ops/command_help_dialog.py +623 -0
- setiastro/saspro/ops/command_runner.py +217 -0
- setiastro/saspro/ops/commands.py +1594 -0
- setiastro/saspro/ops/script_editor.py +1102 -0
- setiastro/saspro/ops/scripts.py +1413 -0
- setiastro/saspro/ops/settings.py +560 -0
- setiastro/saspro/parallel_utils.py +554 -0
- setiastro/saspro/pedestal.py +121 -0
- setiastro/saspro/perfect_palette_picker.py +1053 -0
- setiastro/saspro/pipeline.py +110 -0
- setiastro/saspro/pixelmath.py +1600 -0
- setiastro/saspro/plate_solver.py +2435 -0
- setiastro/saspro/project_io.py +797 -0
- setiastro/saspro/psf_utils.py +136 -0
- setiastro/saspro/psf_viewer.py +549 -0
- setiastro/saspro/pyi_rthook_astroquery.py +95 -0
- setiastro/saspro/remove_green.py +314 -0
- setiastro/saspro/remove_stars.py +1625 -0
- setiastro/saspro/remove_stars_preset.py +404 -0
- setiastro/saspro/resources.py +472 -0
- setiastro/saspro/rgb_combination.py +207 -0
- setiastro/saspro/rgb_extract.py +19 -0
- setiastro/saspro/rgbalign.py +723 -0
- setiastro/saspro/runtime_imports.py +7 -0
- setiastro/saspro/runtime_torch.py +754 -0
- setiastro/saspro/save_options.py +72 -0
- setiastro/saspro/selective_color.py +1552 -0
- setiastro/saspro/sfcc.py +1425 -0
- setiastro/saspro/shortcuts.py +2807 -0
- setiastro/saspro/signature_insert.py +1099 -0
- setiastro/saspro/stacking_suite.py +17712 -0
- setiastro/saspro/star_alignment.py +7420 -0
- setiastro/saspro/star_alignment_preset.py +329 -0
- setiastro/saspro/star_metrics.py +49 -0
- setiastro/saspro/star_spikes.py +681 -0
- setiastro/saspro/star_stretch.py +470 -0
- setiastro/saspro/stat_stretch.py +502 -0
- setiastro/saspro/status_log_dock.py +78 -0
- setiastro/saspro/subwindow.py +3267 -0
- setiastro/saspro/supernovaasteroidhunter.py +1712 -0
- setiastro/saspro/swap_manager.py +99 -0
- setiastro/saspro/torch_backend.py +89 -0
- setiastro/saspro/torch_rejection.py +434 -0
- setiastro/saspro/view_bundle.py +1555 -0
- setiastro/saspro/wavescale_hdr.py +624 -0
- setiastro/saspro/wavescale_hdr_preset.py +100 -0
- setiastro/saspro/wavescalede.py +657 -0
- setiastro/saspro/wavescalede_preset.py +228 -0
- setiastro/saspro/wcs_update.py +374 -0
- setiastro/saspro/whitebalance.py +456 -0
- setiastro/saspro/widgets/__init__.py +48 -0
- setiastro/saspro/widgets/common_utilities.py +305 -0
- setiastro/saspro/widgets/graphics_views.py +122 -0
- setiastro/saspro/widgets/image_utils.py +518 -0
- setiastro/saspro/widgets/preview_dialogs.py +280 -0
- setiastro/saspro/widgets/spinboxes.py +275 -0
- setiastro/saspro/widgets/themed_buttons.py +13 -0
- setiastro/saspro/widgets/wavelet_utils.py +299 -0
- setiastro/saspro/window_shelf.py +185 -0
- setiastro/saspro/xisf.py +1123 -0
- setiastrosuitepro-1.6.0.dist-info/METADATA +266 -0
- setiastrosuitepro-1.6.0.dist-info/RECORD +174 -0
- setiastrosuitepro-1.6.0.dist-info/WHEEL +4 -0
- setiastrosuitepro-1.6.0.dist-info/entry_points.txt +6 -0
- setiastrosuitepro-1.6.0.dist-info/licenses/LICENSE +674 -0
- setiastrosuitepro-1.6.0.dist-info/licenses/license.txt +2580 -0
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
# pro/abe_preset.py
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
import os
|
|
4
|
+
import numpy as np
|
|
5
|
+
|
|
6
|
+
from .abe import abe_run # core engine
|
|
7
|
+
|
|
8
|
+
# ---------- mask helpers (match ABEDialog semantics) ----------
|
|
9
|
+
def _active_mask_layer(doc):
|
|
10
|
+
mid = getattr(doc, "active_mask_id", None)
|
|
11
|
+
if not mid: return None, None, None
|
|
12
|
+
layer = getattr(doc, "masks", {}).get(mid)
|
|
13
|
+
if layer is None: return None, None, None
|
|
14
|
+
m = np.asarray(getattr(layer, "data", None))
|
|
15
|
+
if m is None or m.size == 0: return None, None, None
|
|
16
|
+
m = m.astype(np.float32, copy=False)
|
|
17
|
+
if m.dtype.kind in "ui":
|
|
18
|
+
m /= float(np.iinfo(m.dtype).max)
|
|
19
|
+
else:
|
|
20
|
+
mx = float(m.max()) if m.size else 1.0
|
|
21
|
+
if mx > 1.0: m /= mx
|
|
22
|
+
return np.clip(m, 0.0, 1.0), mid, getattr(layer, "name", "Mask")
|
|
23
|
+
|
|
24
|
+
def _resample_mask(mask: np.ndarray, out_hw: tuple[int,int]) -> np.ndarray:
|
|
25
|
+
mh, mw = mask.shape[:2]
|
|
26
|
+
th, tw = out_hw
|
|
27
|
+
if (mh, mw) == (th, tw): return mask
|
|
28
|
+
yi = np.linspace(0, mh - 1, th).astype(np.int32)
|
|
29
|
+
xi = np.linspace(0, mw - 1, tw).astype(np.int32)
|
|
30
|
+
return mask[yi][:, xi]
|
|
31
|
+
|
|
32
|
+
def _blend_with_mask_float(processed: np.ndarray, src: np.ndarray, doc) -> np.ndarray:
|
|
33
|
+
mask, _mid, _mname = _active_mask_layer(doc)
|
|
34
|
+
if mask is None:
|
|
35
|
+
return processed
|
|
36
|
+
out = processed.astype(np.float32, copy=False)
|
|
37
|
+
s = src.astype(np.float32, copy=False)
|
|
38
|
+
|
|
39
|
+
m = _resample_mask(mask, out.shape[:2])
|
|
40
|
+
# reconcile channels
|
|
41
|
+
if out.ndim == 2 and s.ndim == 3:
|
|
42
|
+
out = out[..., None]
|
|
43
|
+
if s.ndim == 2 and out.ndim == 3:
|
|
44
|
+
s = s[..., None]
|
|
45
|
+
if out.ndim == 3 and out.shape[2] == 3 and m.ndim == 2:
|
|
46
|
+
m = m[..., None]
|
|
47
|
+
blended = (m * out + (1.0 - m) * s).astype(np.float32, copy=False)
|
|
48
|
+
if blended.ndim == 3 and blended.shape[2] == 1:
|
|
49
|
+
blended = blended[..., 0]
|
|
50
|
+
return np.clip(blended, 0.0, 1.0)
|
|
51
|
+
|
|
52
|
+
# ---------- I/O helpers ----------
|
|
53
|
+
def _doc_image_float01(doc) -> np.ndarray | None:
|
|
54
|
+
img = getattr(doc, "image", None)
|
|
55
|
+
if img is None:
|
|
56
|
+
return None
|
|
57
|
+
arr = np.asarray(img)
|
|
58
|
+
if arr.dtype.kind in "ui":
|
|
59
|
+
return (arr.astype(np.float32) / np.iinfo(arr.dtype).max).clip(0.0, 1.0)
|
|
60
|
+
return np.clip(arr.astype(np.float32, copy=False), 0.0, 1.0)
|
|
61
|
+
|
|
62
|
+
# ---------- headless apply (NO EXCLUSION AREA) ----------
|
|
63
|
+
def apply_abe_via_preset(main_window, doc, preset: dict | None = None):
|
|
64
|
+
"""
|
|
65
|
+
Run ABE headlessly (no exclusion polygons; exclusion_mask=None) using preset params.
|
|
66
|
+
Blends with the active mask layer (m*out + (1-m)*src) before committing.
|
|
67
|
+
"""
|
|
68
|
+
p = dict(preset or {})
|
|
69
|
+
# NOTE: allow degree 0 (RBF-only) to match ABEDialog
|
|
70
|
+
degree = int(np.clip(p.get("degree", 2), 0, 6))
|
|
71
|
+
num_samples = int(np.clip(p.get("samples", 120), 20, 100000))
|
|
72
|
+
downsample = int(np.clip(p.get("downsample", 6), 1, 64))
|
|
73
|
+
patch_size = int(np.clip(p.get("patch", 15), 5, 151))
|
|
74
|
+
use_rbf = bool(p.get("rbf", True))
|
|
75
|
+
rbf_smooth = float(p.get("rbf_smooth", 1.0)) # dialog default = 100 × 0.01 = 1.0
|
|
76
|
+
make_bg_doc = bool(p.get("make_background_doc", False))
|
|
77
|
+
|
|
78
|
+
src01 = _doc_image_float01(doc)
|
|
79
|
+
if src01 is None:
|
|
80
|
+
return
|
|
81
|
+
|
|
82
|
+
# Sanitize params we actually used (this is what we’ll store for Replay)
|
|
83
|
+
params = {
|
|
84
|
+
"degree": degree,
|
|
85
|
+
"samples": num_samples,
|
|
86
|
+
"downsample": downsample,
|
|
87
|
+
"patch": patch_size,
|
|
88
|
+
"rbf": use_rbf,
|
|
89
|
+
"rbf_smooth": rbf_smooth,
|
|
90
|
+
"make_background_doc": make_bg_doc,
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
# 🔁 Remember this as the last headless command for Replay
|
|
94
|
+
try:
|
|
95
|
+
remember = getattr(main_window, "remember_last_headless_command", None)
|
|
96
|
+
if remember is None:
|
|
97
|
+
remember = getattr(main_window, "_remember_last_headless_command", None)
|
|
98
|
+
if callable(remember):
|
|
99
|
+
remember("abe", params, description="Automatic Background Extraction")
|
|
100
|
+
try:
|
|
101
|
+
if hasattr(main_window, "_log"):
|
|
102
|
+
main_window._log(
|
|
103
|
+
f"[Replay] ABE headless stored: command_id='abe', "
|
|
104
|
+
f"preset_keys={list(params.keys())}"
|
|
105
|
+
)
|
|
106
|
+
except Exception:
|
|
107
|
+
pass
|
|
108
|
+
except Exception:
|
|
109
|
+
# Do not block ABE if remembering fails
|
|
110
|
+
pass
|
|
111
|
+
|
|
112
|
+
# 🚫 No exclusion polygons in headless mode
|
|
113
|
+
corrected, bg = abe_run(
|
|
114
|
+
src01,
|
|
115
|
+
degree=degree, num_samples=num_samples, downsample=downsample, patch_size=patch_size,
|
|
116
|
+
use_rbf=use_rbf, rbf_smooth=rbf_smooth,
|
|
117
|
+
exclusion_mask=None, # ← force NO EXCLUSION AREA
|
|
118
|
+
return_background=True,
|
|
119
|
+
progress_cb=None
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
# Preserve mono vs color wrt original doc
|
|
123
|
+
out = corrected
|
|
124
|
+
if (
|
|
125
|
+
out.ndim == 3 and out.shape[2] == 3
|
|
126
|
+
and (doc.image.ndim == 2 or (doc.image.ndim == 3 and doc.image.shape[2] == 1))
|
|
127
|
+
):
|
|
128
|
+
out = out[..., 0]
|
|
129
|
+
|
|
130
|
+
# mask-aware blend (like dialog)
|
|
131
|
+
out_masked = _blend_with_mask_float(out, src01, doc)
|
|
132
|
+
|
|
133
|
+
# Clean mask metadata
|
|
134
|
+
_marr, mid, mname = _active_mask_layer(doc)
|
|
135
|
+
|
|
136
|
+
meta = {
|
|
137
|
+
"step_name": "ABE",
|
|
138
|
+
"abe": {
|
|
139
|
+
"degree": degree,
|
|
140
|
+
"samples": num_samples,
|
|
141
|
+
"downsample": downsample,
|
|
142
|
+
"patch": patch_size,
|
|
143
|
+
"rbf": use_rbf,
|
|
144
|
+
"rbf_smooth": rbf_smooth,
|
|
145
|
+
"exclusion": "none", # explicit marker for audit/history
|
|
146
|
+
},
|
|
147
|
+
"masked": bool(mid),
|
|
148
|
+
"mask_id": mid,
|
|
149
|
+
"mask_name": mname,
|
|
150
|
+
"mask_blend": "m*out + (1-m)*src",
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
step_name = (
|
|
154
|
+
f"ABE (deg={degree}, samples={num_samples}, ds={downsample}, "
|
|
155
|
+
f"patch={patch_size}, rbf={'on' if use_rbf else 'off'}, s={rbf_smooth:.3f})"
|
|
156
|
+
)
|
|
157
|
+
doc.apply_edit(out_masked.astype(np.float32, copy=False),
|
|
158
|
+
step_name=step_name, metadata=meta)
|
|
159
|
+
|
|
160
|
+
if make_bg_doc and bg is not None:
|
|
161
|
+
dm = getattr(main_window, "docman", None)
|
|
162
|
+
if dm is not None:
|
|
163
|
+
base = os.path.splitext(doc.display_name())[0]
|
|
164
|
+
meta_bg = {
|
|
165
|
+
"bit_depth": "32-bit floating point",
|
|
166
|
+
"is_mono": (bg.ndim == 2),
|
|
167
|
+
"source": "ABE background (headless)",
|
|
168
|
+
"from_step": step_name,
|
|
169
|
+
}
|
|
170
|
+
doc_bg = dm.open_array(bg.astype(np.float32, copy=False),
|
|
171
|
+
metadata=meta_bg,
|
|
172
|
+
title=f"{base}_ABE_BG")
|
|
173
|
+
if hasattr(main_window, "_spawn_subwindow_for"):
|
|
174
|
+
main_window._spawn_subwindow_for(doc_bg)
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
# ---------- open dialog seeded from preset ----------
|
|
178
|
+
def open_abe_with_preset(main_window, preset: dict | None = None):
|
|
179
|
+
dm = getattr(main_window, "doc_manager", getattr(main_window, "docman", None))
|
|
180
|
+
doc = dm.get_active_document() if (dm and hasattr(dm, "get_active_document")) else getattr(dm, "active_document", None)
|
|
181
|
+
if doc is None:
|
|
182
|
+
return
|
|
183
|
+
from .abe import ABEDialog
|
|
184
|
+
dlg = ABEDialog(main_window, doc)
|
|
185
|
+
p = dict(preset or {})
|
|
186
|
+
try:
|
|
187
|
+
dlg.sp_degree.setValue(int(np.clip(p.get("degree", 2), 1, 6)))
|
|
188
|
+
dlg.sp_samples.setValue(int(np.clip(p.get("samples", 120), 20, 100000)))
|
|
189
|
+
dlg.sp_down.setValue(int(np.clip(p.get("downsample", 6), 1, 64)))
|
|
190
|
+
dlg.sp_patch.setValue(int(np.clip(p.get("patch", 15), 5, 151)))
|
|
191
|
+
dlg.chk_use_rbf.setChecked(bool(p.get("rbf", True)))
|
|
192
|
+
dlg.sp_rbf.setValue(int(np.clip(float(p.get("rbf_smooth", 1.0)) * 100.0, 0, 100000)))
|
|
193
|
+
# polygons intentionally untouched (== none)
|
|
194
|
+
except Exception:
|
|
195
|
+
pass
|
|
196
|
+
dlg.show(); dlg.raise_(); dlg.activateWindow()
|