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
|
@@ -176,7 +176,7 @@ class CurveEditor(QGraphicsView):
|
|
|
176
176
|
def _on_symmetry_pick(self, u: float, _v: float):
|
|
177
177
|
# editor already drew the yellow line; now redistribute handles
|
|
178
178
|
self.redistributeHandlesByPivot(u)
|
|
179
|
-
self._set_status(
|
|
179
|
+
self._set_status(self.tr("Inflection @ K={0:.3f}").format(u))
|
|
180
180
|
self._quick_preview()
|
|
181
181
|
|
|
182
182
|
def initGrid(self):
|
|
@@ -1015,8 +1015,17 @@ class CurvesDialogPro(QDialog):
|
|
|
1015
1015
|
"""
|
|
1016
1016
|
def __init__(self, parent, document):
|
|
1017
1017
|
super().__init__(parent)
|
|
1018
|
-
self.setWindowTitle("Curves Editor")
|
|
1018
|
+
self.setWindowTitle(self.tr("Curves Editor"))
|
|
1019
|
+
self.setWindowFlag(Qt.WindowType.Window, True)
|
|
1020
|
+
self.setWindowModality(Qt.WindowModality.NonModal)
|
|
1021
|
+
self.setModal(False)
|
|
1022
|
+
self._main = parent
|
|
1019
1023
|
self.doc = document
|
|
1024
|
+
|
|
1025
|
+
# Connect to active document change signal
|
|
1026
|
+
if hasattr(self._main, "currentDocumentChanged"):
|
|
1027
|
+
self._main.currentDocumentChanged.connect(self._on_active_doc_changed)
|
|
1028
|
+
|
|
1020
1029
|
self._preview_img = None # downsampled float01
|
|
1021
1030
|
self._full_img = None # full-res float01
|
|
1022
1031
|
self._pix = None
|
|
@@ -1085,12 +1094,12 @@ class CurvesDialogPro(QDialog):
|
|
|
1085
1094
|
|
|
1086
1095
|
rowp = QHBoxLayout()
|
|
1087
1096
|
self.btn_presets = QToolButton(self)
|
|
1088
|
-
self.btn_presets.setText("Presets")
|
|
1097
|
+
self.btn_presets.setText(self.tr("Presets"))
|
|
1089
1098
|
self.btn_presets.setPopupMode(QToolButton.ToolButtonPopupMode.InstantPopup)
|
|
1090
1099
|
rowp.addWidget(self.btn_presets)
|
|
1091
1100
|
|
|
1092
1101
|
self.btn_save_preset = QToolButton(self)
|
|
1093
|
-
self.btn_save_preset.setText("Save as Preset
|
|
1102
|
+
self.btn_save_preset.setText(self.tr("Save as Preset..."))
|
|
1094
1103
|
self.btn_save_preset.clicked.connect(self._save_current_as_preset)
|
|
1095
1104
|
rowp.addWidget(self.btn_save_preset)
|
|
1096
1105
|
left.addLayout(rowp)
|
|
@@ -1103,10 +1112,10 @@ class CurvesDialogPro(QDialog):
|
|
|
1103
1112
|
# buttons
|
|
1104
1113
|
rowb = QHBoxLayout()
|
|
1105
1114
|
self.btn_preview = QToolButton(self)
|
|
1106
|
-
self.btn_preview.setText("Toggle Preview")
|
|
1115
|
+
self.btn_preview.setText(self.tr("Toggle Preview"))
|
|
1107
1116
|
self.btn_preview.setCheckable(True) # ⬅️ toggle
|
|
1108
|
-
self.btn_apply = QPushButton("Apply to Document")
|
|
1109
|
-
self.btn_reset = QToolButton(); self.btn_reset.setText("Reset")
|
|
1117
|
+
self.btn_apply = QPushButton(self.tr("Apply to Document"))
|
|
1118
|
+
self.btn_reset = QToolButton(); self.btn_reset.setText(self.tr("Reset"))
|
|
1110
1119
|
rowb.addWidget(self.btn_preview); rowb.addWidget(self.btn_apply); rowb.addWidget(self.btn_reset)
|
|
1111
1120
|
left.addLayout(rowb)
|
|
1112
1121
|
left.addStretch(1)
|
|
@@ -1117,9 +1126,9 @@ class CurvesDialogPro(QDialog):
|
|
|
1117
1126
|
zoombar = QHBoxLayout()
|
|
1118
1127
|
zoombar.addStretch(1)
|
|
1119
1128
|
|
|
1120
|
-
self.btn_zoom_out = themed_toolbtn("zoom-out", "Zoom Out")
|
|
1121
|
-
self.btn_zoom_in = themed_toolbtn("zoom-in", "Zoom In")
|
|
1122
|
-
self.btn_zoom_fit = themed_toolbtn("zoom-fit-best", "Fit to Preview")
|
|
1129
|
+
self.btn_zoom_out = themed_toolbtn("zoom-out", self.tr("Zoom Out"))
|
|
1130
|
+
self.btn_zoom_in = themed_toolbtn("zoom-in", self.tr("Zoom In"))
|
|
1131
|
+
self.btn_zoom_fit = themed_toolbtn("zoom-fit-best", self.tr("Fit to Preview"))
|
|
1123
1132
|
|
|
1124
1133
|
zoombar.addWidget(self.btn_zoom_out)
|
|
1125
1134
|
zoombar.addWidget(self.btn_zoom_in)
|
|
@@ -1601,7 +1610,7 @@ class CurvesDialogPro(QDialog):
|
|
|
1601
1610
|
|
|
1602
1611
|
def _on_symmetry_pick(self, u: float, _v: float):
|
|
1603
1612
|
self.editor.redistributeHandlesByPivot(u)
|
|
1604
|
-
self._set_status(
|
|
1613
|
+
self._set_status(self.tr("Inflection @ K={0:.3f}").format(u))
|
|
1605
1614
|
self._quick_preview()
|
|
1606
1615
|
|
|
1607
1616
|
def _fit_once(self):
|
|
@@ -1641,7 +1650,7 @@ class CurvesDialogPro(QDialog):
|
|
|
1641
1650
|
v = float(img[iy, ix] if img.ndim == 2 else img[iy, ix, 0])
|
|
1642
1651
|
v = 0.0 if not np.isfinite(v) else float(np.clip(v, 0.0, 1.0))
|
|
1643
1652
|
self.editor.updateValueLines(v, 0.0, 0.0, grayscale=True)
|
|
1644
|
-
self._set_status(
|
|
1653
|
+
self._set_status(self.tr("Cursor ({0}, {1}) K: {2:.3f}").format(ix, iy, v))
|
|
1645
1654
|
else:
|
|
1646
1655
|
C = img.shape[2]
|
|
1647
1656
|
if C >= 3:
|
|
@@ -1656,7 +1665,7 @@ class CurvesDialogPro(QDialog):
|
|
|
1656
1665
|
g = 0.0 if not np.isfinite(g) else float(np.clip(g, 0.0, 1.0))
|
|
1657
1666
|
b = 0.0 if not np.isfinite(b) else float(np.clip(b, 0.0, 1.0))
|
|
1658
1667
|
self.editor.updateValueLines(r, g, b, grayscale=False)
|
|
1659
|
-
self._set_status(
|
|
1668
|
+
self._set_status(self.tr("Cursor ({0}, {1}) R: {2:.3f} G: {3:.3f} B: {4:.3f}").format(ix, iy, r, g, b))
|
|
1660
1669
|
|
|
1661
1670
|
|
|
1662
1671
|
# 1) Put this helper inside CurvesDialogPro (near other helpers)
|
|
@@ -1728,16 +1737,16 @@ class CurvesDialogPro(QDialog):
|
|
|
1728
1737
|
|
|
1729
1738
|
def _save_current_as_preset(self):
|
|
1730
1739
|
# get name
|
|
1731
|
-
name, ok = QInputDialog.getText(self, "Save Curves Preset", "Preset name:")
|
|
1740
|
+
name, ok = QInputDialog.getText(self, self.tr("Save Curves Preset"), self.tr("Preset name:"))
|
|
1732
1741
|
if not ok or not name.strip():
|
|
1733
1742
|
return
|
|
1734
1743
|
pts_norm = self._collect_points_norm_from_editor()
|
|
1735
1744
|
mode = self._current_mode()
|
|
1736
1745
|
if save_custom_preset(name.strip(), mode, pts_norm):
|
|
1737
|
-
self._set_status(
|
|
1746
|
+
self._set_status(self.tr("Saved preset “{0}”.").format(name.strip()))
|
|
1738
1747
|
self._rebuild_presets_menu()
|
|
1739
1748
|
else:
|
|
1740
|
-
QMessageBox.warning(self, "Save failed", "Could not save preset.")
|
|
1749
|
+
QMessageBox.warning(self, self.tr("Save failed"), self.tr("Could not save preset."))
|
|
1741
1750
|
|
|
1742
1751
|
def _rebuild_presets_menu(self):
|
|
1743
1752
|
m = QMenu(self)
|
|
@@ -1754,7 +1763,7 @@ class CurvesDialogPro(QDialog):
|
|
|
1754
1763
|
("Flatten", {"mode": "K (Brightness)", "shape": "flatten", "amount": 1.0}),
|
|
1755
1764
|
]
|
|
1756
1765
|
if builtins:
|
|
1757
|
-
mb = m.addMenu("Built-ins")
|
|
1766
|
+
mb = m.addMenu(self.tr("Built-ins"))
|
|
1758
1767
|
for label, preset in builtins:
|
|
1759
1768
|
act = mb.addAction(label)
|
|
1760
1769
|
act.triggered.connect(lambda _=False, p=preset: self._apply_preset_dict(p))
|
|
@@ -1762,15 +1771,15 @@ class CurvesDialogPro(QDialog):
|
|
|
1762
1771
|
# Custom presets (from QSettings)
|
|
1763
1772
|
customs = list_custom_presets()
|
|
1764
1773
|
if customs:
|
|
1765
|
-
mc = m.addMenu("Custom")
|
|
1774
|
+
mc = m.addMenu(self.tr("Custom"))
|
|
1766
1775
|
for p in sorted(customs, key=lambda d: d.get("name","").lower()):
|
|
1767
1776
|
act = mc.addAction(p.get("name","(unnamed)"))
|
|
1768
1777
|
act.triggered.connect(lambda _=False, pp=p: self._apply_preset_dict(pp))
|
|
1769
1778
|
mc.addSeparator()
|
|
1770
|
-
act_manage = mc.addAction("Manage…")
|
|
1779
|
+
act_manage = mc.addAction(self.tr("Manage…"))
|
|
1771
1780
|
act_manage.triggered.connect(self._open_manage_customs_dialog) # optional (see below)
|
|
1772
1781
|
else:
|
|
1773
|
-
m.addAction("(No custom presets yet)").setEnabled(False)
|
|
1782
|
+
m.addAction(self.tr("(No custom presets yet)")).setEnabled(False)
|
|
1774
1783
|
|
|
1775
1784
|
self.btn_presets.setMenu(m)
|
|
1776
1785
|
|
|
@@ -1778,21 +1787,30 @@ class CurvesDialogPro(QDialog):
|
|
|
1778
1787
|
# optional: quick-and-dirty remover
|
|
1779
1788
|
customs = list_custom_presets()
|
|
1780
1789
|
if not customs:
|
|
1781
|
-
QMessageBox.information(self, "Manage Presets", "No custom presets.")
|
|
1790
|
+
QMessageBox.information(self, self.tr("Manage Presets"), self.tr("No custom presets."))
|
|
1782
1791
|
return
|
|
1783
1792
|
names = [p.get("name","") for p in customs]
|
|
1784
|
-
name, ok = QInputDialog.getItem(self, "Delete Preset", "Choose preset to delete:", names, 0, False)
|
|
1793
|
+
name, ok = QInputDialog.getItem(self, self.tr("Delete Preset"), self.tr("Choose preset to delete:"), names, 0, False)
|
|
1785
1794
|
if ok and name:
|
|
1786
1795
|
from setiastro.saspro.curves_preset import delete_custom_preset
|
|
1787
1796
|
if delete_custom_preset(name):
|
|
1788
1797
|
self._rebuild_presets_menu()
|
|
1789
1798
|
|
|
1790
1799
|
|
|
1800
|
+
# ----- active document change -----
|
|
1801
|
+
def _on_active_doc_changed(self, doc):
|
|
1802
|
+
"""Called when user clicks a different image window."""
|
|
1803
|
+
if doc is None or getattr(doc, "image", None) is None:
|
|
1804
|
+
return
|
|
1805
|
+
self.doc = doc
|
|
1806
|
+
self._load_from_doc()
|
|
1807
|
+
QTimer.singleShot(0, self._fit_after_load)
|
|
1808
|
+
|
|
1791
1809
|
# ----- data -----
|
|
1792
1810
|
def _load_from_doc(self):
|
|
1793
1811
|
img = self.doc.image
|
|
1794
1812
|
if img is None:
|
|
1795
|
-
QMessageBox.information(self, "No image", "Open an image first.")
|
|
1813
|
+
QMessageBox.information(self, self.tr("No image"), self.tr("Open an image first."))
|
|
1796
1814
|
return
|
|
1797
1815
|
arr = np.asarray(img)
|
|
1798
1816
|
# normalize to float01 gently
|
|
@@ -1837,7 +1855,7 @@ class CurvesDialogPro(QDialog):
|
|
|
1837
1855
|
# Pick which buffer to show (both are downsampled)
|
|
1838
1856
|
img = self._preview_proc if (self._show_proc and self._preview_proc is not None) else self._preview_orig
|
|
1839
1857
|
self._update_preview_pix(img)
|
|
1840
|
-
self._set_status("Preview ON" if self._show_proc else "Preview OFF")
|
|
1858
|
+
self._set_status(self.tr("Preview ON") if self._show_proc else self.tr("Preview OFF"))
|
|
1841
1859
|
|
|
1842
1860
|
|
|
1843
1861
|
# ----- quick (in-UI) preview on downsample -----
|
|
@@ -1858,15 +1876,15 @@ class CurvesDialogPro(QDialog):
|
|
|
1858
1876
|
rgb = self._clip_counts_rgb_from_thresholds(bt, wt)
|
|
1859
1877
|
def _fmt(pair):
|
|
1860
1878
|
cnt_b, cnt_w, fb, fw = pair
|
|
1861
|
-
return
|
|
1879
|
+
return self.tr("Bk {0:,} ({1:.2f}%) Wt {2:,} ({3:.2f}%)").format(cnt_b, fb*100, cnt_w, fw*100)
|
|
1862
1880
|
self._set_status(
|
|
1863
|
-
|
|
1881
|
+
self.tr("Clipping — R: {0} G: {1} B: {2}").format(_fmt(rgb['r']), _fmt(rgb['g']), _fmt(rgb['b']))
|
|
1864
1882
|
)
|
|
1865
1883
|
else:
|
|
1866
1884
|
# Grayscale/mono → K summary (unchanged behavior)
|
|
1867
1885
|
below, above, f_below, f_above = self._clip_counts_from_thresholds(bt, wt)
|
|
1868
1886
|
self._set_status(
|
|
1869
|
-
|
|
1887
|
+
self.tr("Clipping — Bk {0:,} ({1:.2f}%) Wt {2:,} ({3:.2f}%)").format(below, f_below*100, above, f_above*100)
|
|
1870
1888
|
)
|
|
1871
1889
|
except Exception:
|
|
1872
1890
|
pass
|
|
@@ -1887,7 +1905,7 @@ class CurvesDialogPro(QDialog):
|
|
|
1887
1905
|
# NOTE: do not push full-res into the label
|
|
1888
1906
|
out_masked = self._blend_with_mask(out01)
|
|
1889
1907
|
self._last_preview = out_masked # cache for Apply
|
|
1890
|
-
self._set_status("Full-res ready (not shown).")
|
|
1908
|
+
self._set_status(self.tr("Full-res ready (not shown)."))
|
|
1891
1909
|
|
|
1892
1910
|
def _clip_counts_from_thresholds(self, black_t: float | None, white_t: float | None):
|
|
1893
1911
|
"""
|
|
@@ -2066,12 +2084,12 @@ class CurvesDialogPro(QDialog):
|
|
|
2066
2084
|
|
|
2067
2085
|
self._refresh_overlays()
|
|
2068
2086
|
self._quick_preview()
|
|
2069
|
-
self._set_status("Applied. Image reloaded. All curves reset — keep tweaking.")
|
|
2087
|
+
self._set_status(self.tr("Applied. Image reloaded. All curves reset — keep tweaking."))
|
|
2070
2088
|
|
|
2071
2089
|
|
|
2072
2090
|
|
|
2073
2091
|
except Exception as e:
|
|
2074
|
-
QMessageBox.critical(self, "Apply failed", str(e))
|
|
2092
|
+
QMessageBox.critical(self, self.tr("Apply failed"), str(e))
|
|
2075
2093
|
|
|
2076
2094
|
|
|
2077
2095
|
# ----- helpers -----
|
|
@@ -2288,7 +2306,7 @@ class CurvesDialogPro(QDialog):
|
|
|
2288
2306
|
break
|
|
2289
2307
|
|
|
2290
2308
|
self.editor.addControlPoint(x, y)
|
|
2291
|
-
self._set_status(
|
|
2309
|
+
self._set_status(self.tr("Added point at x={0:.3f}").format(v))
|
|
2292
2310
|
ev.accept()
|
|
2293
2311
|
return True
|
|
2294
2312
|
|
|
@@ -2304,7 +2322,7 @@ class CurvesDialogPro(QDialog):
|
|
|
2304
2322
|
# 3) refresh overlays & preview
|
|
2305
2323
|
self._refresh_overlays()
|
|
2306
2324
|
self._quick_preview()
|
|
2307
|
-
self._set_status("All curves reset.")
|
|
2325
|
+
self._set_status(self.tr("All curves reset."))
|
|
2308
2326
|
|
|
2309
2327
|
def _find_main_window(self):
|
|
2310
2328
|
p = self.parent()
|
|
@@ -2351,7 +2369,7 @@ class CurvesDialogPro(QDialog):
|
|
|
2351
2369
|
|
|
2352
2370
|
# 4) status: don’t assume shape exists
|
|
2353
2371
|
shape_tag = f"[{shape}]" if shape else "[custom]"
|
|
2354
|
-
self._set_status(
|
|
2372
|
+
self._set_status(self.tr("Preset: {0} {1}").format(preset.get('name', self.tr('(built-in)')), shape_tag))
|
|
2355
2373
|
|
|
2356
2374
|
|
|
2357
2375
|
def apply_curves_ops(doc, op: dict):
|
setiastro/saspro/debayer.py
CHANGED
|
@@ -401,7 +401,10 @@ class DebayerDialog(QDialog):
|
|
|
401
401
|
"""
|
|
402
402
|
def __init__(self, parent, doc_manager, active_doc):
|
|
403
403
|
super().__init__(parent)
|
|
404
|
-
self.setWindowTitle("Debayer")
|
|
404
|
+
self.setWindowTitle(self.tr("Debayer"))
|
|
405
|
+
self.setWindowFlag(Qt.WindowType.Window, True)
|
|
406
|
+
self.setWindowModality(Qt.WindowModality.NonModal)
|
|
407
|
+
self.setModal(False)
|
|
405
408
|
self.dm = doc_manager
|
|
406
409
|
self.doc = active_doc
|
|
407
410
|
self.worker: Optional[_DebayerWorker] = None
|
|
@@ -435,7 +438,7 @@ class DebayerDialog(QDialog):
|
|
|
435
438
|
detected = _detect_bayer_from_header(active_doc)
|
|
436
439
|
self._detected_pattern = detected # store for later
|
|
437
440
|
|
|
438
|
-
gb = QGroupBox("Bayer pattern", self)
|
|
441
|
+
gb = QGroupBox(self.tr("Bayer pattern"), self)
|
|
439
442
|
h = QHBoxLayout(gb)
|
|
440
443
|
self.combo_pattern = QComboBox(self)
|
|
441
444
|
self.combo_pattern.addItems([
|
|
@@ -455,7 +458,7 @@ class DebayerDialog(QDialog):
|
|
|
455
458
|
norm = _normalize_bayer_token(self._detected_pattern or "")
|
|
456
459
|
self.lbl_detect.setText(f"Detected: {norm or '(unknown)'}")
|
|
457
460
|
|
|
458
|
-
self.method_group = QGroupBox("Method", self)
|
|
461
|
+
self.method_group = QGroupBox(self.tr("Method"), self)
|
|
459
462
|
hm = QHBoxLayout(self.method_group)
|
|
460
463
|
self.combo_method = QComboBox(self)
|
|
461
464
|
|
setiastro/saspro/doc_manager.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#
|
|
1
|
+
# saspro/doc_manager.py
|
|
2
2
|
from __future__ import annotations
|
|
3
3
|
from PyQt6.QtCore import QObject, pyqtSignal, Qt, QTimer
|
|
4
4
|
from PyQt6.QtWidgets import QApplication, QMessageBox
|
|
@@ -2472,23 +2472,29 @@ class DocManager(QObject):
|
|
|
2472
2472
|
If a Preview tab is selected on the active ImageSubWindow, return a cached
|
|
2473
2473
|
_RoiViewDocument so tools and the Preview tab share the same instance.
|
|
2474
2474
|
Otherwise return the real ImageDocument.
|
|
2475
|
+
|
|
2476
|
+
IMPORTANT: Always check the currently active MDI subwindow first,
|
|
2477
|
+
as that's what the user expects to be the "active" document.
|
|
2475
2478
|
"""
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
|
|
2479
|
-
|
|
2480
|
-
|
|
2481
|
-
|
|
2482
|
-
if
|
|
2483
|
-
|
|
2484
|
-
|
|
2485
|
-
|
|
2486
|
-
|
|
2487
|
-
|
|
2488
|
-
|
|
2489
|
-
|
|
2490
|
-
|
|
2491
|
-
|
|
2479
|
+
base_doc = None
|
|
2480
|
+
|
|
2481
|
+
# ALWAYS check the MDI active subwindow first - this is the source of truth
|
|
2482
|
+
try:
|
|
2483
|
+
if self._mdi is not None:
|
|
2484
|
+
sw = self._mdi.activeSubWindow()
|
|
2485
|
+
if sw is not None:
|
|
2486
|
+
w = sw.widget()
|
|
2487
|
+
base_doc = getattr(w, "document", None) or getattr(sw, "document", None)
|
|
2488
|
+
if base_doc is not None:
|
|
2489
|
+
self._active_doc = base_doc
|
|
2490
|
+
except Exception:
|
|
2491
|
+
pass
|
|
2492
|
+
|
|
2493
|
+
# Fallback to cached value only if MDI lookup failed
|
|
2494
|
+
if base_doc is None:
|
|
2495
|
+
if self._active_doc is not None and self._active_doc in self._docs:
|
|
2496
|
+
base_doc = self._active_doc
|
|
2497
|
+
else:
|
|
2492
2498
|
base_doc = self._docs[-1] if self._docs else None
|
|
2493
2499
|
|
|
2494
2500
|
# Non-image docs just pass through
|
|
@@ -2514,9 +2520,33 @@ class DocManager(QObject):
|
|
|
2514
2520
|
|
|
2515
2521
|
|
|
2516
2522
|
|
|
2517
|
-
def update_active_document(
|
|
2523
|
+
def update_active_document(
|
|
2524
|
+
self,
|
|
2525
|
+
updated_image,
|
|
2526
|
+
metadata=None,
|
|
2527
|
+
step_name: str = "Edit",
|
|
2528
|
+
doc=None, # 👈 NEW optional parameter
|
|
2529
|
+
):
|
|
2530
|
+
|
|
2531
|
+
# Prefer explicit doc if given; otherwise fall back to "active"
|
|
2532
|
+
view_doc = doc or self.get_active_document()
|
|
2533
|
+
|
|
2534
|
+
# DEBUG: Trace why LinearFit might fail
|
|
2535
|
+
# print(f"[DocManager] update_active_document target: {view_doc}, type: {type(view_doc).__name__}")
|
|
2536
|
+
|
|
2537
|
+
# NEW: Unwrap proxy objects (_DocProxy / LiveViewDocument)
|
|
2538
|
+
tname = type(view_doc).__name__
|
|
2539
|
+
if "LiveViewDocument" in tname:
|
|
2540
|
+
try:
|
|
2541
|
+
view_doc = view_doc._current()
|
|
2542
|
+
except Exception:
|
|
2543
|
+
pass
|
|
2544
|
+
elif "_DocProxy" in tname:
|
|
2545
|
+
try:
|
|
2546
|
+
view_doc = view_doc._target()
|
|
2547
|
+
except Exception:
|
|
2548
|
+
pass
|
|
2518
2549
|
|
|
2519
|
-
view_doc = self.get_active_document()
|
|
2520
2550
|
if view_doc is None:
|
|
2521
2551
|
raise RuntimeError("No active document")
|
|
2522
2552
|
|
|
@@ -253,7 +253,7 @@ class ClickableEllipseItem(QGraphicsEllipseItem):
|
|
|
253
253
|
class ReferenceOverlayDialog(QDialog):
|
|
254
254
|
def __init__(self, plane: np.ndarray, positions: List[Tuple], target_median: float, parent=None):
|
|
255
255
|
super().__init__(parent)
|
|
256
|
-
self.setWindowTitle("Reference Frame: Stars Overlay")
|
|
256
|
+
self.setWindowTitle(self.tr("Reference Frame: Stars Overlay"))
|
|
257
257
|
self.plane = plane.astype(np.float32)
|
|
258
258
|
self.positions = positions
|
|
259
259
|
self.target_median = target_median
|
|
@@ -388,7 +388,7 @@ class ReferenceOverlayDialog(QDialog):
|
|
|
388
388
|
class ExoPlanetWindow(QDialog):
|
|
389
389
|
def __init__(self, parent=None, wrench_path=None):
|
|
390
390
|
super().__init__(parent)
|
|
391
|
-
self.setWindowTitle("Exoplanet Transit Detector")
|
|
391
|
+
self.setWindowTitle(self.tr("Exoplanet Transit Detector"))
|
|
392
392
|
|
|
393
393
|
self.resize(900, 600)
|
|
394
394
|
self.wrench_path = wrench_path
|
|
@@ -430,9 +430,9 @@ class ExoPlanetWindow(QDialog):
|
|
|
430
430
|
|
|
431
431
|
# — Mode selector —
|
|
432
432
|
mode_layout = QHBoxLayout()
|
|
433
|
-
mode_layout.addWidget(QLabel("Mode:"))
|
|
434
|
-
self.aligned_mode_rb = QRadioButton("Aligned Subs")
|
|
435
|
-
self.raw_mode_rb = QRadioButton("Raw Subs")
|
|
433
|
+
mode_layout.addWidget(QLabel(self.tr("Mode:")))
|
|
434
|
+
self.aligned_mode_rb = QRadioButton(self.tr("Aligned Subs"))
|
|
435
|
+
self.raw_mode_rb = QRadioButton(self.tr("Raw Subs"))
|
|
436
436
|
self.aligned_mode_rb.setChecked(True)
|
|
437
437
|
mg = QButtonGroup(self)
|
|
438
438
|
mg.addButton(self.aligned_mode_rb); mg.addButton(self.raw_mode_rb)
|
|
@@ -459,8 +459,8 @@ class ExoPlanetWindow(QDialog):
|
|
|
459
459
|
|
|
460
460
|
# — Calibration controls (hidden in Aligned) —
|
|
461
461
|
cal_layout = QHBoxLayout()
|
|
462
|
-
self.load_darks_btn = QPushButton("Load Master Dark…")
|
|
463
|
-
self.load_flats_btn = QPushButton("Load Master Flat…")
|
|
462
|
+
self.load_darks_btn = QPushButton(self.tr("Load Master Dark…"))
|
|
463
|
+
self.load_flats_btn = QPushButton(self.tr("Load Master Flat…"))
|
|
464
464
|
for w in (self.load_darks_btn, self.load_flats_btn):
|
|
465
465
|
w.clicked.connect(self.load_masters)
|
|
466
466
|
w.hide()
|
|
@@ -478,10 +478,10 @@ class ExoPlanetWindow(QDialog):
|
|
|
478
478
|
|
|
479
479
|
# — Top controls —
|
|
480
480
|
top_layout = QHBoxLayout()
|
|
481
|
-
self.load_raw_btn = QPushButton("1: Load Raw Subs…")
|
|
482
|
-
self.load_aligned_btn = QPushButton("Load, Measure && Photometry…")
|
|
483
|
-
self.calibrate_btn = QPushButton("1a: Calibrate && Align Subs")
|
|
484
|
-
self.measure_btn = QPushButton("2: Measure && Photometry")
|
|
481
|
+
self.load_raw_btn = QPushButton(self.tr("1: Load Raw Subs…"))
|
|
482
|
+
self.load_aligned_btn = QPushButton(self.tr("Load, Measure && Photometry…"))
|
|
483
|
+
self.calibrate_btn = QPushButton(self.tr("1a: Calibrate && Align Subs"))
|
|
484
|
+
self.measure_btn = QPushButton(self.tr("2: Measure && Photometry"))
|
|
485
485
|
self.load_raw_btn. clicked.connect(self.load_raw_subs)
|
|
486
486
|
self.load_aligned_btn.clicked.connect(self.load_and_measure_subs)
|
|
487
487
|
self.calibrate_btn.clicked.connect(self.calibrate_and_align)
|