setiastrosuitepro 1.6.0__py3-none-any.whl → 1.6.4.post1__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/data/SASP_data.fits +0 -0
- setiastro/data/catalogs/List_of_Galaxies_with_Distances_Gly.csv +488 -0
- setiastro/data/catalogs/astrobin_filters.csv +890 -0
- setiastro/data/catalogs/astrobin_filters_page1_local.csv +51 -0
- setiastro/data/catalogs/cali2.csv +63 -0
- setiastro/data/catalogs/cali2color.csv +65 -0
- setiastro/data/catalogs/celestial_catalog - original.csv +16471 -0
- setiastro/data/catalogs/celestial_catalog.csv +24031 -0
- setiastro/data/catalogs/detected_stars.csv +24784 -0
- setiastro/data/catalogs/fits_header_data.csv +46 -0
- setiastro/data/catalogs/test.csv +8 -0
- setiastro/data/catalogs/updated_celestial_catalog.csv +16471 -0
- setiastro/images/Astro_Spikes.png +0 -0
- setiastro/images/Background_startup.jpg +0 -0
- setiastro/images/HRDiagram.png +0 -0
- setiastro/images/LExtract.png +0 -0
- setiastro/images/LInsert.png +0 -0
- setiastro/images/Oxygenation-atm-2.svg.png +0 -0
- setiastro/images/RGB080604.png +0 -0
- setiastro/images/abeicon.png +0 -0
- setiastro/images/aberration.png +0 -0
- setiastro/images/andromedatry.png +0 -0
- setiastro/images/andromedatry_satellited.png +0 -0
- setiastro/images/annotated.png +0 -0
- setiastro/images/aperture.png +0 -0
- setiastro/images/astrosuite.ico +0 -0
- setiastro/images/astrosuite.png +0 -0
- setiastro/images/astrosuitepro.icns +0 -0
- setiastro/images/astrosuitepro.ico +0 -0
- setiastro/images/astrosuitepro.png +0 -0
- setiastro/images/background.png +0 -0
- setiastro/images/background2.png +0 -0
- setiastro/images/benchmark.png +0 -0
- setiastro/images/big_moon_stabilizer_timeline.png +0 -0
- setiastro/images/big_moon_stabilizer_timeline_clean.png +0 -0
- setiastro/images/blaster.png +0 -0
- setiastro/images/blink.png +0 -0
- setiastro/images/clahe.png +0 -0
- setiastro/images/collage.png +0 -0
- setiastro/images/colorwheel.png +0 -0
- setiastro/images/contsub.png +0 -0
- setiastro/images/convo.png +0 -0
- setiastro/images/copyslot.png +0 -0
- setiastro/images/cosmic.png +0 -0
- setiastro/images/cosmicsat.png +0 -0
- setiastro/images/crop1.png +0 -0
- setiastro/images/cropicon.png +0 -0
- setiastro/images/curves.png +0 -0
- setiastro/images/cvs.png +0 -0
- setiastro/images/debayer.png +0 -0
- setiastro/images/denoise_cnn_custom.png +0 -0
- setiastro/images/denoise_cnn_graph.png +0 -0
- setiastro/images/disk.png +0 -0
- setiastro/images/dse.png +0 -0
- setiastro/images/exoicon.png +0 -0
- setiastro/images/eye.png +0 -0
- setiastro/images/fliphorizontal.png +0 -0
- setiastro/images/flipvertical.png +0 -0
- setiastro/images/font.png +0 -0
- setiastro/images/freqsep.png +0 -0
- setiastro/images/functionbundle.png +0 -0
- setiastro/images/graxpert.png +0 -0
- setiastro/images/green.png +0 -0
- setiastro/images/gridicon.png +0 -0
- setiastro/images/halo.png +0 -0
- setiastro/images/hdr.png +0 -0
- setiastro/images/histogram.png +0 -0
- setiastro/images/hubble.png +0 -0
- setiastro/images/imagecombine.png +0 -0
- setiastro/images/invert.png +0 -0
- setiastro/images/isophote.png +0 -0
- setiastro/images/isophote_demo_figure.png +0 -0
- setiastro/images/isophote_demo_image.png +0 -0
- setiastro/images/isophote_demo_model.png +0 -0
- setiastro/images/isophote_demo_residual.png +0 -0
- setiastro/images/jwstpupil.png +0 -0
- setiastro/images/linearfit.png +0 -0
- setiastro/images/livestacking.png +0 -0
- setiastro/images/mask.png +0 -0
- setiastro/images/maskapply.png +0 -0
- setiastro/images/maskcreate.png +0 -0
- setiastro/images/maskremove.png +0 -0
- setiastro/images/morpho.png +0 -0
- setiastro/images/mosaic.png +0 -0
- setiastro/images/multiscale_decomp.png +0 -0
- setiastro/images/nbtorgb.png +0 -0
- setiastro/images/neutral.png +0 -0
- setiastro/images/nuke.png +0 -0
- setiastro/images/openfile.png +0 -0
- setiastro/images/pedestal.png +0 -0
- setiastro/images/pen.png +0 -0
- setiastro/images/pixelmath.png +0 -0
- setiastro/images/platesolve.png +0 -0
- setiastro/images/ppp.png +0 -0
- setiastro/images/pro.png +0 -0
- setiastro/images/project.png +0 -0
- setiastro/images/psf.png +0 -0
- setiastro/images/redo.png +0 -0
- setiastro/images/redoicon.png +0 -0
- setiastro/images/rescale.png +0 -0
- setiastro/images/rgbalign.png +0 -0
- setiastro/images/rgbcombo.png +0 -0
- setiastro/images/rgbextract.png +0 -0
- setiastro/images/rotate180.png +0 -0
- setiastro/images/rotatearbitrary.png +0 -0
- setiastro/images/rotateclockwise.png +0 -0
- setiastro/images/rotatecounterclockwise.png +0 -0
- setiastro/images/satellite.png +0 -0
- setiastro/images/script.png +0 -0
- setiastro/images/selectivecolor.png +0 -0
- setiastro/images/simbad.png +0 -0
- setiastro/images/slot0.png +0 -0
- setiastro/images/slot1.png +0 -0
- setiastro/images/slot2.png +0 -0
- setiastro/images/slot3.png +0 -0
- setiastro/images/slot4.png +0 -0
- setiastro/images/slot5.png +0 -0
- setiastro/images/slot6.png +0 -0
- setiastro/images/slot7.png +0 -0
- setiastro/images/slot8.png +0 -0
- setiastro/images/slot9.png +0 -0
- setiastro/images/spcc.png +0 -0
- setiastro/images/spin_precession_vs_lunar_distance.png +0 -0
- setiastro/images/spinner.gif +0 -0
- setiastro/images/stacking.png +0 -0
- setiastro/images/staradd.png +0 -0
- setiastro/images/staralign.png +0 -0
- setiastro/images/starnet.png +0 -0
- setiastro/images/starregistration.png +0 -0
- setiastro/images/starspike.png +0 -0
- setiastro/images/starstretch.png +0 -0
- setiastro/images/statstretch.png +0 -0
- setiastro/images/supernova.png +0 -0
- setiastro/images/uhs.png +0 -0
- setiastro/images/undoicon.png +0 -0
- setiastro/images/upscale.png +0 -0
- setiastro/images/viewbundle.png +0 -0
- setiastro/images/whitebalance.png +0 -0
- setiastro/images/wimi_icon_256x256.png +0 -0
- setiastro/images/wimilogo.png +0 -0
- setiastro/images/wims.png +0 -0
- setiastro/images/wrench_icon.png +0 -0
- setiastro/images/xisfliberator.png +0 -0
- setiastro/qml/ResourceMonitor.qml +126 -0
- setiastro/saspro/__main__.py +228 -67
- setiastro/saspro/_generated/build_info.py +2 -1
- setiastro/saspro/abe.py +76 -25
- setiastro/saspro/aberration_ai.py +14 -14
- setiastro/saspro/add_stars.py +15 -12
- setiastro/saspro/astrobin_exporter.py +61 -58
- setiastro/saspro/astrospike_python.py +3 -1
- setiastro/saspro/autostretch.py +4 -2
- setiastro/saspro/backgroundneutral.py +65 -14
- setiastro/saspro/batch_convert.py +8 -5
- setiastro/saspro/batch_renamer.py +39 -36
- setiastro/saspro/blemish_blaster.py +15 -12
- setiastro/saspro/blink_comparator_pro.py +605 -379
- setiastro/saspro/cheat_sheet.py +62 -17
- setiastro/saspro/clahe.py +34 -8
- setiastro/saspro/comet_stacking.py +103 -38
- setiastro/saspro/common_tr.py +107 -0
- setiastro/saspro/continuum_subtract.py +7 -7
- setiastro/saspro/convo.py +12 -9
- setiastro/saspro/copyastro.py +3 -0
- setiastro/saspro/cosmicclarity.py +77 -52
- setiastro/saspro/crop_dialog_pro.py +80 -45
- setiastro/saspro/curve_editor_pro.py +51 -33
- setiastro/saspro/debayer.py +6 -3
- setiastro/saspro/doc_manager.py +49 -19
- setiastro/saspro/exoplanet_detector.py +11 -11
- setiastro/saspro/fitsmodifier.py +48 -44
- setiastro/saspro/fix_bom.py +32 -0
- setiastro/saspro/frequency_separation.py +18 -12
- setiastro/saspro/function_bundle.py +18 -16
- setiastro/saspro/generate_translations.py +3092 -0
- setiastro/saspro/ghs_dialog_pro.py +19 -16
- setiastro/saspro/graxpert.py +3 -0
- setiastro/saspro/gui/main_window.py +471 -126
- setiastro/saspro/gui/mixins/dock_mixin.py +123 -11
- setiastro/saspro/gui/mixins/file_mixin.py +25 -20
- setiastro/saspro/gui/mixins/geometry_mixin.py +115 -15
- setiastro/saspro/gui/mixins/header_mixin.py +6 -6
- setiastro/saspro/gui/mixins/mask_mixin.py +8 -8
- setiastro/saspro/gui/mixins/menu_mixin.py +62 -33
- setiastro/saspro/gui/mixins/toolbar_mixin.py +382 -226
- setiastro/saspro/gui/mixins/update_mixin.py +26 -26
- setiastro/saspro/gui/statistics_dialog.py +47 -0
- setiastro/saspro/halobgon.py +29 -3
- setiastro/saspro/header_viewer.py +21 -18
- setiastro/saspro/histogram.py +29 -26
- setiastro/saspro/history_explorer.py +2 -0
- setiastro/saspro/i18n.py +168 -0
- setiastro/saspro/image_combine.py +3 -0
- setiastro/saspro/image_peeker_pro.py +52 -44
- setiastro/saspro/imageops/stretch.py +5 -13
- setiastro/saspro/isophote.py +3 -0
- setiastro/saspro/legacy/numba_utils.py +64 -47
- setiastro/saspro/linear_fit.py +3 -0
- setiastro/saspro/live_stacking.py +13 -2
- setiastro/saspro/mask_creation.py +180 -22
- setiastro/saspro/mfdeconv.py +5 -0
- setiastro/saspro/morphology.py +38 -13
- setiastro/saspro/multiscale_decomp.py +713 -256
- setiastro/saspro/nbtorgb_stars.py +12 -2
- setiastro/saspro/numba_utils.py +149 -48
- setiastro/saspro/ops/scripts.py +77 -17
- setiastro/saspro/ops/settings.py +177 -100
- setiastro/saspro/perfect_palette_picker.py +25 -7
- setiastro/saspro/pixelmath.py +114 -110
- setiastro/saspro/plate_solver.py +118 -108
- setiastro/saspro/remove_green.py +24 -7
- setiastro/saspro/remove_stars.py +136 -162
- setiastro/saspro/remove_stars_preset.py +55 -13
- setiastro/saspro/resources.py +46 -15
- setiastro/saspro/rgb_combination.py +19 -18
- setiastro/saspro/rgbalign.py +11 -11
- setiastro/saspro/save_options.py +5 -4
- setiastro/saspro/selective_color.py +84 -25
- setiastro/saspro/sfcc.py +119 -72
- setiastro/saspro/shortcuts.py +345 -36
- setiastro/saspro/signature_insert.py +4 -1
- setiastro/saspro/stacking_suite.py +2066 -1119
- setiastro/saspro/star_alignment.py +291 -331
- setiastro/saspro/star_spikes.py +137 -53
- setiastro/saspro/star_stretch.py +47 -10
- setiastro/saspro/stat_stretch.py +52 -16
- setiastro/saspro/status_log_dock.py +1 -1
- setiastro/saspro/subwindow.py +97 -36
- setiastro/saspro/supernovaasteroidhunter.py +68 -61
- setiastro/saspro/swap_manager.py +77 -42
- setiastro/saspro/translations/all_source_strings.json +4726 -0
- setiastro/saspro/translations/ar_translations.py +4096 -0
- setiastro/saspro/translations/de_translations.py +3728 -0
- setiastro/saspro/translations/es_translations.py +4169 -0
- setiastro/saspro/translations/fr_translations.py +4090 -0
- setiastro/saspro/translations/hi_translations.py +3803 -0
- setiastro/saspro/translations/integrate_translations.py +271 -0
- setiastro/saspro/translations/it_translations.py +4728 -0
- setiastro/saspro/translations/ja_translations.py +3834 -0
- setiastro/saspro/translations/pt_translations.py +3847 -0
- setiastro/saspro/translations/ru_translations.py +3082 -0
- setiastro/saspro/translations/saspro_ar.qm +0 -0
- setiastro/saspro/translations/saspro_ar.ts +16019 -0
- setiastro/saspro/translations/saspro_de.qm +0 -0
- setiastro/saspro/translations/saspro_de.ts +14548 -0
- setiastro/saspro/translations/saspro_es.qm +0 -0
- setiastro/saspro/translations/saspro_es.ts +16202 -0
- setiastro/saspro/translations/saspro_fr.qm +0 -0
- setiastro/saspro/translations/saspro_fr.ts +15870 -0
- setiastro/saspro/translations/saspro_hi.qm +0 -0
- setiastro/saspro/translations/saspro_hi.ts +14855 -0
- setiastro/saspro/translations/saspro_it.qm +0 -0
- setiastro/saspro/translations/saspro_it.ts +19046 -0
- setiastro/saspro/translations/saspro_ja.qm +0 -0
- setiastro/saspro/translations/saspro_ja.ts +14980 -0
- setiastro/saspro/translations/saspro_pt.qm +0 -0
- setiastro/saspro/translations/saspro_pt.ts +15024 -0
- setiastro/saspro/translations/saspro_ru.qm +0 -0
- setiastro/saspro/translations/saspro_ru.ts +11835 -0
- setiastro/saspro/translations/saspro_sw.qm +0 -0
- setiastro/saspro/translations/saspro_sw.ts +15237 -0
- setiastro/saspro/translations/saspro_uk.qm +0 -0
- setiastro/saspro/translations/saspro_uk.ts +15248 -0
- setiastro/saspro/translations/saspro_zh.qm +0 -0
- setiastro/saspro/translations/saspro_zh.ts +15289 -0
- setiastro/saspro/translations/sw_translations.py +3897 -0
- setiastro/saspro/translations/uk_translations.py +3929 -0
- setiastro/saspro/translations/zh_translations.py +3910 -0
- setiastro/saspro/versioning.py +77 -0
- setiastro/saspro/view_bundle.py +20 -17
- setiastro/saspro/wavescale_hdr.py +54 -33
- setiastro/saspro/wavescale_hdr_preset.py +6 -5
- setiastro/saspro/wavescalede.py +54 -31
- setiastro/saspro/wavescalede_preset.py +9 -7
- setiastro/saspro/whitebalance.py +58 -22
- setiastro/saspro/widgets/common_utilities.py +12 -11
- setiastro/saspro/widgets/minigame/game.js +991 -0
- setiastro/saspro/widgets/minigame/index.html +53 -0
- setiastro/saspro/widgets/minigame/style.css +241 -0
- setiastro/saspro/widgets/preview_dialogs.py +8 -8
- setiastro/saspro/widgets/resource_monitor.py +263 -0
- setiastro/saspro/widgets/spinboxes.py +18 -0
- setiastro/saspro/widgets/wavelet_utils.py +52 -20
- setiastro/saspro/wimi.py +7996 -0
- setiastro/saspro/wims.py +578 -0
- setiastro/saspro/window_shelf.py +2 -2
- {setiastrosuitepro-1.6.0.dist-info → setiastrosuitepro-1.6.4.post1.dist-info}/METADATA +15 -3
- setiastrosuitepro-1.6.4.post1.dist-info/RECORD +368 -0
- setiastrosuitepro-1.6.0.dist-info/RECORD +0 -174
- {setiastrosuitepro-1.6.0.dist-info → setiastrosuitepro-1.6.4.post1.dist-info}/WHEEL +0 -0
- {setiastrosuitepro-1.6.0.dist-info → setiastrosuitepro-1.6.4.post1.dist-info}/entry_points.txt +0 -0
- {setiastrosuitepro-1.6.0.dist-info → setiastrosuitepro-1.6.4.post1.dist-info}/licenses/LICENSE +0 -0
- {setiastrosuitepro-1.6.0.dist-info → setiastrosuitepro-1.6.4.post1.dist-info}/licenses/license.txt +0 -0
setiastro/saspro/abe.py
CHANGED
|
@@ -75,15 +75,28 @@ def _fit_poly_on_small(small: np.ndarray, points: np.ndarray, degree: int, patch
|
|
|
75
75
|
|
|
76
76
|
if small.ndim == 3 and small.shape[2] == 3:
|
|
77
77
|
bg_small = np.zeros_like(small, dtype=np.float32)
|
|
78
|
+
|
|
79
|
+
# Batch collect samples: (num_samples, 3)
|
|
80
|
+
# We need N samples. z will be list of (3,) arrays
|
|
81
|
+
|
|
82
|
+
# Pre-allocate Z: (N, 3)
|
|
83
|
+
Z = np.zeros((len(xs), 3), dtype=np.float32)
|
|
84
|
+
|
|
85
|
+
for k, (x, y) in enumerate(zip(xs, ys)):
|
|
86
|
+
x0, x1 = max(0, x - half), min(W, x + half + 1)
|
|
87
|
+
y0, y1 = max(0, y - half), min(H, y + half + 1)
|
|
88
|
+
# Efficiently compute median for all channels in this patch
|
|
89
|
+
patch = small[y0:y1, x0:x1, :]
|
|
90
|
+
Z[k] = np.median(patch, axis=(0, 1))
|
|
91
|
+
|
|
92
|
+
# Solve once: A is (N, terms), Z is (N, 3) -> coeffs is (terms, 3)
|
|
93
|
+
coeffs_all, *_ = np.linalg.lstsq(A, Z, rcond=None)
|
|
94
|
+
|
|
95
|
+
# Evaluate per channel
|
|
78
96
|
for c in range(3):
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
y0, y1 = max(0, y - half), min(H, y + half + 1)
|
|
83
|
-
z.append(np.median(small[y0:y1, x0:x1, c]))
|
|
84
|
-
z = np.asarray(z, dtype=np.float32)
|
|
85
|
-
coeffs, *_ = np.linalg.lstsq(A, z, rcond=None)
|
|
86
|
-
bg_small[..., c] = evaluate_polynomial(H, W, coeffs.astype(np.float32), degree)
|
|
97
|
+
# coeffs_all[:, c] gives the terms for channel c
|
|
98
|
+
bg_small[..., c] = evaluate_polynomial(H, W, coeffs_all[:, c].astype(np.float32), degree)
|
|
99
|
+
|
|
87
100
|
return bg_small
|
|
88
101
|
else:
|
|
89
102
|
z = []
|
|
@@ -471,17 +484,22 @@ class ABEDialog(QDialog):
|
|
|
471
484
|
"""
|
|
472
485
|
def __init__(self, parent, document: ImageDocument):
|
|
473
486
|
super().__init__(parent)
|
|
474
|
-
self.setWindowTitle("Automatic Background Extraction (ABE)")
|
|
487
|
+
self.setWindowTitle(self.tr("Automatic Background Extraction (ABE)"))
|
|
475
488
|
|
|
476
489
|
# IMPORTANT: avoid “attached modal sheet” behavior on some Linux WMs
|
|
477
490
|
self.setWindowFlag(Qt.WindowType.Window, True)
|
|
478
|
-
#
|
|
479
|
-
self.setWindowModality(Qt.WindowModality.
|
|
491
|
+
# Non-modal: allow user to switch between images while dialog is open
|
|
492
|
+
self.setWindowModality(Qt.WindowModality.NonModal)
|
|
480
493
|
self.setModal(False)
|
|
481
494
|
#self.setAttribute(Qt.WidgetAttribute.WA_DeleteOnClose, True)
|
|
482
495
|
|
|
496
|
+
self._main = parent
|
|
483
497
|
self.doc = document
|
|
484
498
|
|
|
499
|
+
# Connect to active document change signal
|
|
500
|
+
if hasattr(self._main, "currentDocumentChanged"):
|
|
501
|
+
self._main.currentDocumentChanged.connect(self._on_active_doc_changed)
|
|
502
|
+
|
|
485
503
|
self._preview_scale = 1.0
|
|
486
504
|
self._preview_qimg = None
|
|
487
505
|
self._last_preview = None # backing ndarray for QImage lifetime
|
|
@@ -500,10 +518,10 @@ class ABEDialog(QDialog):
|
|
|
500
518
|
self.sp_samples = QSpinBox(); self.sp_samples.setRange(20, 10000); self.sp_samples.setSingleStep(20); self.sp_samples.setValue(120)
|
|
501
519
|
self.sp_down = QSpinBox(); self.sp_down.setRange(1, 32); self.sp_down.setValue(4)
|
|
502
520
|
self.sp_patch = QSpinBox(); self.sp_patch.setRange(5, 151); self.sp_patch.setSingleStep(2); self.sp_patch.setValue(15)
|
|
503
|
-
self.chk_use_rbf = QCheckBox("Enable RBF refinement (after polynomial)"); self.chk_use_rbf.setChecked(True)
|
|
521
|
+
self.chk_use_rbf = QCheckBox(self.tr("Enable RBF refinement (after polynomial)")); self.chk_use_rbf.setChecked(True)
|
|
504
522
|
self.sp_rbf = QSpinBox(); self.sp_rbf.setRange(0, 1000); self.sp_rbf.setValue(100) # shown as ×0.01 below
|
|
505
|
-
self.chk_make_bg_doc = QCheckBox("Create background document"); self.chk_make_bg_doc.setChecked(False)
|
|
506
|
-
self.chk_preview_bg = QCheckBox("Preview background instead of corrected"); self.chk_preview_bg.setChecked(False)
|
|
523
|
+
self.chk_make_bg_doc = QCheckBox(self.tr("Create background document")); self.chk_make_bg_doc.setChecked(False)
|
|
524
|
+
self.chk_preview_bg = QCheckBox(self.tr("Preview background instead of corrected")); self.chk_preview_bg.setChecked(False)
|
|
507
525
|
|
|
508
526
|
# Preview area
|
|
509
527
|
self.preview_label = QLabel(alignment=Qt.AlignmentFlag.AlignCenter)
|
|
@@ -516,10 +534,10 @@ class ABEDialog(QDialog):
|
|
|
516
534
|
self.preview_scroll.setVerticalScrollBarPolicy(Qt.ScrollBarPolicy.ScrollBarAsNeeded)
|
|
517
535
|
|
|
518
536
|
# Buttons
|
|
519
|
-
self.btn_preview = QPushButton("Preview")
|
|
520
|
-
self.btn_apply = QPushButton("Apply")
|
|
521
|
-
self.btn_close = QPushButton("Close")
|
|
522
|
-
self.btn_clear = QPushButton("Clear Exclusions")
|
|
537
|
+
self.btn_preview = QPushButton(self.tr("Preview"))
|
|
538
|
+
self.btn_apply = QPushButton(self.tr("Apply"))
|
|
539
|
+
self.btn_close = QPushButton(self.tr("Close"))
|
|
540
|
+
self.btn_clear = QPushButton(self.tr("Clear Exclusions"))
|
|
523
541
|
self.btn_preview.clicked.connect(self._do_preview)
|
|
524
542
|
self.btn_apply.clicked.connect(self._do_apply)
|
|
525
543
|
self.btn_close.clicked.connect(self.close)
|
|
@@ -527,15 +545,15 @@ class ABEDialog(QDialog):
|
|
|
527
545
|
|
|
528
546
|
# Layout
|
|
529
547
|
params = QFormLayout()
|
|
530
|
-
params.addRow("Polynomial degree:", self.sp_degree)
|
|
531
|
-
params.addRow("# sample points:", self.sp_samples)
|
|
532
|
-
params.addRow("Downsample factor:", self.sp_down)
|
|
533
|
-
params.addRow("Patch size (px):", self.sp_patch)
|
|
548
|
+
params.addRow(self.tr("Polynomial degree:"), self.sp_degree)
|
|
549
|
+
params.addRow(self.tr("# sample points:"), self.sp_samples)
|
|
550
|
+
params.addRow(self.tr("Downsample factor:"), self.sp_down)
|
|
551
|
+
params.addRow(self.tr("Patch size (px):"), self.sp_patch)
|
|
534
552
|
|
|
535
|
-
rbf_box = QGroupBox("RBF Refinement")
|
|
553
|
+
rbf_box = QGroupBox(self.tr("RBF Refinement"))
|
|
536
554
|
rbf_form = QFormLayout()
|
|
537
555
|
rbf_form.addRow(self.chk_use_rbf)
|
|
538
|
-
rbf_form.addRow("Smooth (
|
|
556
|
+
rbf_form.addRow(self.tr("Smooth (x0.01):"), self.sp_rbf)
|
|
539
557
|
rbf_box.setLayout(rbf_form)
|
|
540
558
|
|
|
541
559
|
opts = QVBoxLayout()
|
|
@@ -612,6 +630,17 @@ class ABEDialog(QDialog):
|
|
|
612
630
|
bar.addWidget(self.btn_autostr)
|
|
613
631
|
return bar
|
|
614
632
|
|
|
633
|
+
# ----- active document change -----
|
|
634
|
+
def _on_active_doc_changed(self, doc):
|
|
635
|
+
"""Called when user clicks a different image window."""
|
|
636
|
+
if doc is None or getattr(doc, "image", None) is None:
|
|
637
|
+
return
|
|
638
|
+
self.doc = doc
|
|
639
|
+
self._polygons.clear()
|
|
640
|
+
self._drawing_poly = None
|
|
641
|
+
self._preview_source_f01 = None
|
|
642
|
+
self._populate_initial_preview()
|
|
643
|
+
|
|
615
644
|
# ----- data helpers -----
|
|
616
645
|
def _get_source_float(self) -> np.ndarray | None:
|
|
617
646
|
src = np.asarray(self.doc.image)
|
|
@@ -813,12 +842,34 @@ class ABEDialog(QDialog):
|
|
|
813
842
|
pass
|
|
814
843
|
|
|
815
844
|
self._set_status("Done")
|
|
816
|
-
|
|
845
|
+
# Dialog stays open so user can apply to other images
|
|
846
|
+
# Refresh to use the now-active document for next operation
|
|
847
|
+
self._refresh_document_from_active()
|
|
817
848
|
|
|
818
849
|
except Exception as e:
|
|
819
850
|
self._set_status("Error")
|
|
820
851
|
QMessageBox.critical(self, "Apply failed", str(e))
|
|
821
852
|
|
|
853
|
+
def _refresh_document_from_active(self):
|
|
854
|
+
"""
|
|
855
|
+
Refresh the dialog's document reference to the currently active document.
|
|
856
|
+
This allows reusing the same dialog on different images.
|
|
857
|
+
"""
|
|
858
|
+
try:
|
|
859
|
+
main = self.parent()
|
|
860
|
+
if main and hasattr(main, "_active_doc"):
|
|
861
|
+
new_doc = main._active_doc()
|
|
862
|
+
if new_doc is not None and new_doc is not self.doc:
|
|
863
|
+
self.doc = new_doc
|
|
864
|
+
# Reset preview state for new document
|
|
865
|
+
self._preview_source_f01 = None
|
|
866
|
+
self._last_preview = None
|
|
867
|
+
self._preview_qimg = None
|
|
868
|
+
# Clear polygons since they were for old image
|
|
869
|
+
self._clear_polys()
|
|
870
|
+
except Exception:
|
|
871
|
+
pass
|
|
872
|
+
|
|
822
873
|
|
|
823
874
|
# ----- exclusion polygons & mask -----
|
|
824
875
|
def _clear_polys(self):
|
|
@@ -292,14 +292,14 @@ class _ONNXWorker(QThread):
|
|
|
292
292
|
class AberrationAIDialog(QDialog):
|
|
293
293
|
def __init__(self, parent, docman, get_active_doc_callable, icon: QIcon | None = None):
|
|
294
294
|
super().__init__(parent)
|
|
295
|
-
self.setWindowTitle("R.A.'s Aberration Correction (AI)")
|
|
295
|
+
self.setWindowTitle(self.tr("R.A.'s Aberration Correction (AI)"))
|
|
296
296
|
if icon is not None:
|
|
297
297
|
self.setWindowIcon(icon)
|
|
298
298
|
|
|
299
299
|
# Normalize window behavior across platforms
|
|
300
300
|
self.setWindowFlag(Qt.WindowType.Window, True)
|
|
301
|
-
#
|
|
302
|
-
self.setWindowModality(Qt.WindowModality.
|
|
301
|
+
# Non-modal: allow user to switch between images while dialog is open
|
|
302
|
+
self.setWindowModality(Qt.WindowModality.NonModal)
|
|
303
303
|
self.setModal(False)
|
|
304
304
|
#self.setAttribute(Qt.WidgetAttribute.WA_DeleteOnClose, True)
|
|
305
305
|
|
|
@@ -312,40 +312,40 @@ class AberrationAIDialog(QDialog):
|
|
|
312
312
|
|
|
313
313
|
# Model row
|
|
314
314
|
row = QHBoxLayout()
|
|
315
|
-
row.addWidget(QLabel("Model:"))
|
|
315
|
+
row.addWidget(QLabel(self.tr("Model:")))
|
|
316
316
|
self.model_label = QLabel("—")
|
|
317
317
|
self.model_label.setToolTip("")
|
|
318
|
-
btn_browse = QPushButton("Browse…"); btn_browse.clicked.connect(self._browse_model)
|
|
318
|
+
btn_browse = QPushButton(self.tr("Browse…")); btn_browse.clicked.connect(self._browse_model)
|
|
319
319
|
row.addWidget(self.model_label, 1)
|
|
320
320
|
row.addWidget(btn_browse)
|
|
321
321
|
v.addLayout(row)
|
|
322
322
|
|
|
323
323
|
# Providers row
|
|
324
324
|
row2 = QHBoxLayout()
|
|
325
|
-
self.chk_auto = QCheckBox("Auto GPU (if available)")
|
|
325
|
+
self.chk_auto = QCheckBox(self.tr("Auto GPU (if available)"))
|
|
326
326
|
self.chk_auto.setChecked(True)
|
|
327
327
|
row2.addWidget(self.chk_auto)
|
|
328
328
|
self.cmb_provider = QComboBox()
|
|
329
|
-
row2.addWidget(QLabel("Provider:"))
|
|
329
|
+
row2.addWidget(QLabel(self.tr("Provider:")))
|
|
330
330
|
row2.addWidget(self.cmb_provider, 1)
|
|
331
331
|
v.addLayout(row2)
|
|
332
332
|
|
|
333
333
|
# Params row
|
|
334
334
|
row3 = QHBoxLayout()
|
|
335
|
-
row3.addWidget(QLabel("Patch"))
|
|
335
|
+
row3.addWidget(QLabel(self.tr("Patch")))
|
|
336
336
|
self.spin_patch = QSpinBox(minimum=128, maximum=2048); self.spin_patch.setValue(512)
|
|
337
337
|
row3.addWidget(self.spin_patch)
|
|
338
|
-
row3.addWidget(QLabel("Overlap"))
|
|
338
|
+
row3.addWidget(QLabel(self.tr("Overlap")))
|
|
339
339
|
self.spin_overlap = QSpinBox(minimum=16, maximum=512); self.spin_overlap.setValue(64)
|
|
340
340
|
row3.addWidget(self.spin_overlap)
|
|
341
341
|
v.addLayout(row3)
|
|
342
342
|
|
|
343
343
|
# Download / Open folder
|
|
344
344
|
row4 = QHBoxLayout()
|
|
345
|
-
btn_latest = QPushButton("Download latest model…")
|
|
345
|
+
btn_latest = QPushButton(self.tr("Download latest model…"))
|
|
346
346
|
btn_latest.clicked.connect(self._download_latest_model)
|
|
347
347
|
row4.addWidget(btn_latest)
|
|
348
|
-
btn_openfolder = QPushButton("Open model folder")
|
|
348
|
+
btn_openfolder = QPushButton(self.tr("Open model folder"))
|
|
349
349
|
btn_openfolder.clicked.connect(self._open_model_folder)
|
|
350
350
|
row4.addWidget(btn_openfolder)
|
|
351
351
|
row4.addStretch(1)
|
|
@@ -354,8 +354,8 @@ class AberrationAIDialog(QDialog):
|
|
|
354
354
|
# Progress + actions
|
|
355
355
|
self.progress = QProgressBar(); self.progress.setRange(0, 100); v.addWidget(self.progress)
|
|
356
356
|
row5 = QHBoxLayout()
|
|
357
|
-
self.btn_run = QPushButton("Run"); self.btn_run.clicked.connect(self._run)
|
|
358
|
-
btn_close = QPushButton("Close"); btn_close.clicked.connect(self.reject)
|
|
357
|
+
self.btn_run = QPushButton(self.tr("Run")); self.btn_run.clicked.connect(self._run)
|
|
358
|
+
btn_close = QPushButton(self.tr("Close")); btn_close.clicked.connect(self.reject)
|
|
359
359
|
row5.addStretch(1); row5.addWidget(self.btn_run); row5.addWidget(btn_close)
|
|
360
360
|
v.addLayout(row5)
|
|
361
361
|
|
|
@@ -680,7 +680,7 @@ class AberrationAIDialog(QDialog):
|
|
|
680
680
|
)
|
|
681
681
|
|
|
682
682
|
self.progress.setValue(100)
|
|
683
|
-
|
|
683
|
+
# Dialog stays open so user can apply to other images
|
|
684
684
|
|
|
685
685
|
def _on_worker_finished(self):
|
|
686
686
|
# If dialog is already gone, this method is never called because the receiver (self)
|
setiastro/saspro/add_stars.py
CHANGED
|
@@ -224,10 +224,11 @@ class AddStarsDialog(QDialog):
|
|
|
224
224
|
stars_added = pyqtSignal(object, object)
|
|
225
225
|
def __init__(self, main, parent=None):
|
|
226
226
|
super().__init__(parent)
|
|
227
|
-
self.setWindowTitle("Add Stars to Image")
|
|
227
|
+
self.setWindowTitle(self.tr("Add Stars to Image"))
|
|
228
228
|
|
|
229
229
|
self.setWindowFlag(Qt.WindowType.Window, True)
|
|
230
|
-
|
|
230
|
+
# Non-modal: allow user to switch between images while dialog is open
|
|
231
|
+
self.setWindowModality(Qt.WindowModality.NonModal)
|
|
231
232
|
self.setModal(False)
|
|
232
233
|
#self.setAttribute(Qt.WidgetAttribute.WA_DeleteOnClose, True)
|
|
233
234
|
|
|
@@ -277,27 +278,27 @@ class AddStarsDialog(QDialog):
|
|
|
277
278
|
grid = QGridLayout()
|
|
278
279
|
|
|
279
280
|
# Blend type
|
|
280
|
-
grid.addWidget(QLabel("Blend Type:"), 0, 0)
|
|
281
|
+
grid.addWidget(QLabel(self.tr("Blend Type:")), 0, 0)
|
|
281
282
|
self.cmb_blend = QComboBox(); self.cmb_blend.addItems(["Screen", "Add"])
|
|
282
283
|
self.cmb_blend.currentIndexChanged.connect(self.update_preview)
|
|
283
284
|
grid.addWidget(self.cmb_blend, 0, 1)
|
|
284
285
|
|
|
285
286
|
# Starless source
|
|
286
|
-
grid.addWidget(QLabel("Starless View:"), 1, 0)
|
|
287
|
+
grid.addWidget(QLabel(self.tr("Starless View:")), 1, 0)
|
|
287
288
|
self.cmb_starless = QComboBox(); grid.addWidget(self.cmb_starless, 1, 1)
|
|
288
|
-
btn_sless_file = QPushButton("Load from File"); btn_sless_file.clicked.connect(lambda: self._load_from_file('starless'))
|
|
289
|
+
btn_sless_file = QPushButton(self.tr("Load from File")); btn_sless_file.clicked.connect(lambda: self._load_from_file('starless'))
|
|
289
290
|
grid.addWidget(btn_sless_file, 1, 2)
|
|
290
291
|
|
|
291
292
|
# Stars-only source
|
|
292
|
-
grid.addWidget(QLabel("Stars-Only View:"), 2, 0)
|
|
293
|
+
grid.addWidget(QLabel(self.tr("Stars-Only View:")), 2, 0)
|
|
293
294
|
self.cmb_stars = QComboBox(); grid.addWidget(self.cmb_stars, 2, 1)
|
|
294
|
-
btn_stars_file = QPushButton("Load from File"); btn_stars_file.clicked.connect(lambda: self._load_from_file('stars'))
|
|
295
|
+
btn_stars_file = QPushButton(self.tr("Load from File")); btn_stars_file.clicked.connect(lambda: self._load_from_file('stars'))
|
|
295
296
|
grid.addWidget(btn_stars_file, 2, 2)
|
|
296
297
|
|
|
297
298
|
layout.addLayout(grid)
|
|
298
299
|
|
|
299
300
|
refresh_row = QHBoxLayout()
|
|
300
|
-
btn_refresh = QPushButton("Refresh Views")
|
|
301
|
+
btn_refresh = QPushButton(self.tr("Refresh Views"))
|
|
301
302
|
btn_refresh.clicked.connect(self._populate_doc_combos)
|
|
302
303
|
refresh_row.addStretch(1)
|
|
303
304
|
refresh_row.addWidget(btn_refresh)
|
|
@@ -305,7 +306,7 @@ class AddStarsDialog(QDialog):
|
|
|
305
306
|
|
|
306
307
|
# Ratio slider
|
|
307
308
|
row = QHBoxLayout()
|
|
308
|
-
row.addWidget(QLabel("Blend Ratio (Screen/Add Intensity):"))
|
|
309
|
+
row.addWidget(QLabel(self.tr("Blend Ratio (Screen/Add Intensity):")))
|
|
309
310
|
self.slider_ratio = QSlider(Qt.Orientation.Horizontal)
|
|
310
311
|
self.slider_ratio.setRange(0, 100); self.slider_ratio.setValue(100)
|
|
311
312
|
self.slider_ratio.setTickInterval(10); self.slider_ratio.setTickPosition(QSlider.TickPosition.TicksBelow)
|
|
@@ -315,8 +316,8 @@ class AddStarsDialog(QDialog):
|
|
|
315
316
|
|
|
316
317
|
# Buttons
|
|
317
318
|
brow = QHBoxLayout(); brow.addStretch(1)
|
|
318
|
-
btn_apply = QPushButton("Apply"); btn_apply.clicked.connect(self._apply)
|
|
319
|
-
btn_cancel= QPushButton("Cancel"); btn_cancel.clicked.connect(self.reject)
|
|
319
|
+
btn_apply = QPushButton(self.tr("Apply")); btn_apply.clicked.connect(self._apply)
|
|
320
|
+
btn_cancel= QPushButton(self.tr("Cancel")); btn_cancel.clicked.connect(self.reject)
|
|
320
321
|
brow.addWidget(btn_apply); brow.addWidget(btn_cancel)
|
|
321
322
|
layout.addLayout(brow)
|
|
322
323
|
|
|
@@ -574,7 +575,9 @@ class AddStarsDialog(QDialog):
|
|
|
574
575
|
|
|
575
576
|
# Emit (target_doc, blended_image)
|
|
576
577
|
self.stars_added.emit(target_doc, self.blended_image.astype(np.float32, copy=False))
|
|
577
|
-
|
|
578
|
+
# Dialog stays open so user can apply to other images
|
|
579
|
+
# Refresh combo boxes for next operation
|
|
580
|
+
self._populate_doc_combos()
|
|
578
581
|
|
|
579
582
|
|
|
580
583
|
# Ensure initial fit once shown
|