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/fitsmodifier.py
CHANGED
|
@@ -30,7 +30,7 @@ class FITSModifier(QDialog):
|
|
|
30
30
|
doc_manager=None, active_document=None, # <— rename param
|
|
31
31
|
parent=None):
|
|
32
32
|
super().__init__(parent)
|
|
33
|
-
self.setWindowTitle("FITS Header Editor")
|
|
33
|
+
self.setWindowTitle(self.tr("FITS Header Editor"))
|
|
34
34
|
self.resize(800, 600)
|
|
35
35
|
|
|
36
36
|
self._doc_manager = doc_manager
|
|
@@ -48,17 +48,17 @@ class FITSModifier(QDialog):
|
|
|
48
48
|
|
|
49
49
|
# UI
|
|
50
50
|
top = QHBoxLayout()
|
|
51
|
-
self.path_label = QLabel(self.file_path or "(no file)")
|
|
52
|
-
self.open_btn = QPushButton("Open FITS…")
|
|
53
|
-
self.reload_btn = QPushButton("Reload")
|
|
51
|
+
self.path_label = QLabel(self.file_path or self.tr("(no file)"))
|
|
52
|
+
self.open_btn = QPushButton(self.tr("Open FITS…"))
|
|
53
|
+
self.reload_btn = QPushButton(self.tr("Reload"))
|
|
54
54
|
self.hdu_combo = QComboBox()
|
|
55
|
-
self.save_btn = QPushButton("Save")
|
|
56
|
-
self.saveas_btn = QPushButton("Save a Copy As…")
|
|
55
|
+
self.save_btn = QPushButton(self.tr("Save"))
|
|
56
|
+
self.saveas_btn = QPushButton(self.tr("Save a Copy As…"))
|
|
57
57
|
# self.apply_to_slot_btn = QPushButton("Apply to Slot Metadata") # optional
|
|
58
58
|
|
|
59
|
-
top.addWidget(QLabel("File:"))
|
|
59
|
+
top.addWidget(QLabel(self.tr("File:")))
|
|
60
60
|
top.addWidget(self.path_label, 1)
|
|
61
|
-
top.addWidget(QLabel("HDU:"))
|
|
61
|
+
top.addWidget(QLabel(self.tr("HDU:")))
|
|
62
62
|
top.addWidget(self.hdu_combo)
|
|
63
63
|
top.addWidget(self.open_btn)
|
|
64
64
|
top.addWidget(self.reload_btn)
|
|
@@ -67,14 +67,14 @@ class FITSModifier(QDialog):
|
|
|
67
67
|
# top.addWidget(self.apply_to_slot_btn)
|
|
68
68
|
|
|
69
69
|
batch = QHBoxLayout()
|
|
70
|
-
self.batch_btn = QPushButton("Batch Modify...")
|
|
70
|
+
self.batch_btn = QPushButton(self.tr("Batch Modify..."))
|
|
71
71
|
batch.addStretch()
|
|
72
72
|
batch.addWidget(self.batch_btn)
|
|
73
73
|
batch.addStretch()
|
|
74
74
|
|
|
75
75
|
self.tree = QTreeWidget()
|
|
76
76
|
self.tree.setColumnCount(3)
|
|
77
|
-
self.tree.setHeaderLabels(["Keyword", "Value", "Comment"])
|
|
77
|
+
self.tree.setHeaderLabels([self.tr("Keyword"), self.tr("Value"), self.tr("Comment")])
|
|
78
78
|
self.tree.setAlternatingRowColors(True)
|
|
79
79
|
self.tree.setRootIsDecorated(False)
|
|
80
80
|
self.tree.setEditTriggers(QTreeWidget.EditTrigger.DoubleClicked | QTreeWidget.EditTrigger.SelectedClicked)
|
|
@@ -89,12 +89,12 @@ class FITSModifier(QDialog):
|
|
|
89
89
|
""")
|
|
90
90
|
|
|
91
91
|
bottom = QHBoxLayout()
|
|
92
|
-
self.add_key_edit = QLineEdit(); self.add_key_edit.setPlaceholderText("KEYWORD")
|
|
93
|
-
self.add_val_edit = QLineEdit(); self.add_val_edit.setPlaceholderText("Value")
|
|
94
|
-
self.add_com_edit = QLineEdit(); self.add_com_edit.setPlaceholderText("Comment (optional)")
|
|
95
|
-
self.add_btn = QPushButton("Add/Update")
|
|
96
|
-
self.del_btn = QPushButton("Delete Selected")
|
|
97
|
-
self.all_hdus_chk = QCheckBox("Apply add/update/delete to all HDUs")
|
|
92
|
+
self.add_key_edit = QLineEdit(); self.add_key_edit.setPlaceholderText(self.tr("KEYWORD"))
|
|
93
|
+
self.add_val_edit = QLineEdit(); self.add_val_edit.setPlaceholderText(self.tr("Value"))
|
|
94
|
+
self.add_com_edit = QLineEdit(); self.add_com_edit.setPlaceholderText(self.tr("Comment (optional)"))
|
|
95
|
+
self.add_btn = QPushButton(self.tr("Add/Update"))
|
|
96
|
+
self.del_btn = QPushButton(self.tr("Delete Selected"))
|
|
97
|
+
self.all_hdus_chk = QCheckBox(self.tr("Apply add/update/delete to all HDUs"))
|
|
98
98
|
bottom.addWidget(self.add_key_edit)
|
|
99
99
|
bottom.addWidget(self.add_val_edit)
|
|
100
100
|
bottom.addWidget(self.add_com_edit)
|
|
@@ -210,7 +210,7 @@ class FITSModifier(QDialog):
|
|
|
210
210
|
|
|
211
211
|
def _set_dirty(self, dirty=True):
|
|
212
212
|
self._dirty = dirty
|
|
213
|
-
self.setWindowTitle("FITS Header Editor" + (" *" if dirty else ""))
|
|
213
|
+
self.setWindowTitle(self.tr("FITS Header Editor") + (" *" if dirty else ""))
|
|
214
214
|
|
|
215
215
|
def _sync_tree_to_header(self):
|
|
216
216
|
if not self.hdul:
|
|
@@ -219,7 +219,7 @@ class FITSModifier(QDialog):
|
|
|
219
219
|
self._collect_tree_into_header(hdr)
|
|
220
220
|
|
|
221
221
|
def _choose_file(self):
|
|
222
|
-
fn, _ = QFileDialog.getOpenFileName(self, "Open FITS", self._last_dir(), "FITS files (*.fits *.fit *.fts *.fz)")
|
|
222
|
+
fn, _ = QFileDialog.getOpenFileName(self, self.tr("Open FITS"), self._last_dir(), self.tr("FITS files (*.fits *.fit *.fts *.fz)"))
|
|
223
223
|
if not fn:
|
|
224
224
|
return
|
|
225
225
|
self._load_file(fn)
|
|
@@ -233,12 +233,12 @@ class FITSModifier(QDialog):
|
|
|
233
233
|
try:
|
|
234
234
|
self.hdul = fits.open(path, mode='update', memmap=False)
|
|
235
235
|
except Exception as e:
|
|
236
|
-
QMessageBox.warning(self, "Invalid FITS",
|
|
237
|
-
|
|
238
|
-
"Tip: Choose a FITS file via 'Open FITS…' or edit an in-memory header.")
|
|
236
|
+
QMessageBox.warning(self, self.tr("Invalid FITS"),
|
|
237
|
+
self.tr("This file does not appear to be a valid FITS:\n\n{0}\n\n{1}\n\n"
|
|
238
|
+
"Tip: Choose a FITS file via 'Open FITS…' or edit an in-memory header.").format(path, e))
|
|
239
239
|
self.hdul = None
|
|
240
240
|
self.file_path = None
|
|
241
|
-
self.path_label.setText("(no file)")
|
|
241
|
+
self.path_label.setText(self.tr("(no file)"))
|
|
242
242
|
self.hdu_combo.clear()
|
|
243
243
|
self._update_multi_hdu_ui()
|
|
244
244
|
return False
|
|
@@ -373,7 +373,7 @@ class FITSModifier(QDialog):
|
|
|
373
373
|
"""
|
|
374
374
|
doc = self._active_doc()
|
|
375
375
|
if doc is None or doc.image is None:
|
|
376
|
-
QMessageBox.warning(self, "No Image", "No active image/document to save.")
|
|
376
|
+
QMessageBox.warning(self, self.tr("No Image"), self.tr("No active image/document to save."))
|
|
377
377
|
return False
|
|
378
378
|
|
|
379
379
|
edited_hdr = self._edited_primary_header()
|
|
@@ -401,7 +401,7 @@ class FITSModifier(QDialog):
|
|
|
401
401
|
file_meta=file_meta,
|
|
402
402
|
)
|
|
403
403
|
except Exception as e:
|
|
404
|
-
QMessageBox.critical(self, "Save Error",
|
|
404
|
+
QMessageBox.critical(self, self.tr("Save Error"), self.tr("Could not save:\n{0}").format(e))
|
|
405
405
|
return False
|
|
406
406
|
|
|
407
407
|
if update_doc_metadata:
|
|
@@ -436,9 +436,9 @@ class FITSModifier(QDialog):
|
|
|
436
436
|
self._sync_tree_to_header()
|
|
437
437
|
last = self._settings().value("fits_modifier/last_dir", "", type=str) or ""
|
|
438
438
|
path, _ = QFileDialog.getSaveFileName(
|
|
439
|
-
self, "Save Image As",
|
|
439
|
+
self, self.tr("Save Image As"),
|
|
440
440
|
last,
|
|
441
|
-
"FITS (*.fits *.fit);;TIFF (*.tif *.tiff);;PNG (*.png);;JPEG (*.jpg *.jpeg);;XISF (*.xisf)"
|
|
441
|
+
self.tr("FITS (*.fits *.fit);;TIFF (*.tif *.tiff);;PNG (*.png);;JPEG (*.jpg *.jpeg);;XISF (*.xisf)")
|
|
442
442
|
)
|
|
443
443
|
if not path:
|
|
444
444
|
return
|
|
@@ -446,7 +446,7 @@ class FITSModifier(QDialog):
|
|
|
446
446
|
if ok:
|
|
447
447
|
self._save_last_dir(os.path.dirname(path))
|
|
448
448
|
# Optional: toast confirmation only
|
|
449
|
-
QMessageBox.information(self, "Saved Copy",
|
|
449
|
+
QMessageBox.information(self, self.tr("Saved Copy"), self.tr("Saved a copy to:\n{0}").format(path))
|
|
450
450
|
|
|
451
451
|
|
|
452
452
|
def _save_to_path(self, path: str) -> bool:
|
|
@@ -605,27 +605,31 @@ class FITSModifier(QDialog):
|
|
|
605
605
|
class BatchFITSHeaderDialog(QDialog):
|
|
606
606
|
def __init__(self, parent=None, preset_keyword: str = "", preset_value: str = "", preset_comment: str = ""):
|
|
607
607
|
super().__init__(parent)
|
|
608
|
-
self.setWindowTitle("Batch Modify FITS Headers")
|
|
608
|
+
self.setWindowTitle(self.tr("Batch Modify FITS Headers"))
|
|
609
|
+
self.setWindowFlag(Qt.WindowType.Window, True)
|
|
610
|
+
self.setWindowModality(Qt.WindowModality.NonModal)
|
|
611
|
+
self.setModal(False)
|
|
609
612
|
self.resize(520, 220)
|
|
610
613
|
|
|
611
614
|
v = QVBoxLayout(self)
|
|
612
615
|
|
|
613
616
|
row1 = QHBoxLayout()
|
|
614
|
-
self.files_edit = QLineEdit(); self.files_edit.setPlaceholderText("No files selected")
|
|
615
|
-
self.pick_btn = QPushButton("Choose FITS Files…")
|
|
617
|
+
self.files_edit = QLineEdit(); self.files_edit.setPlaceholderText(self.tr("No files selected"))
|
|
618
|
+
self.pick_btn = QPushButton(self.tr("Choose FITS Files…"))
|
|
616
619
|
row1.addWidget(self.files_edit, 1); row1.addWidget(self.pick_btn)
|
|
617
620
|
|
|
618
621
|
row2 = QHBoxLayout()
|
|
619
|
-
self.key_edit = QLineEdit(); self.key_edit.setPlaceholderText("KEYWORD")
|
|
620
|
-
self.val_edit = QLineEdit(); self.val_edit.setPlaceholderText("Value (leave blank for delete)")
|
|
621
|
-
self.com_edit = QLineEdit(); self.com_edit.setPlaceholderText("Comment (optional)")
|
|
622
|
+
self.key_edit = QLineEdit(); self.key_edit.setPlaceholderText(self.tr("KEYWORD"))
|
|
623
|
+
self.val_edit = QLineEdit(); self.val_edit.setPlaceholderText(self.tr("Value (leave blank for delete)"))
|
|
624
|
+
self.com_edit = QLineEdit(); self.com_edit.setPlaceholderText(self.tr("Comment (optional)"))
|
|
622
625
|
row2.addWidget(self.key_edit); row2.addWidget(self.val_edit); row2.addWidget(self.com_edit)
|
|
623
626
|
|
|
624
627
|
row3 = QHBoxLayout()
|
|
625
628
|
self.mode_combo = QComboBox()
|
|
626
|
-
self.mode_combo.
|
|
627
|
-
self.
|
|
628
|
-
self.
|
|
629
|
+
self.mode_combo.addItem(self.tr("Add/Update"), "Add/Update")
|
|
630
|
+
self.mode_combo.addItem(self.tr("Delete"), "Delete")
|
|
631
|
+
self.all_hdus_chk = QCheckBox(self.tr("Apply to all HDUs"))
|
|
632
|
+
self.add_if_missing_chk = QCheckBox(self.tr("Add if missing (for Add/Update)"))
|
|
629
633
|
self.add_if_missing_chk.setChecked(True)
|
|
630
634
|
row3.addWidget(self.mode_combo)
|
|
631
635
|
row3.addWidget(self.all_hdus_chk)
|
|
@@ -633,8 +637,8 @@ class BatchFITSHeaderDialog(QDialog):
|
|
|
633
637
|
row3.addStretch()
|
|
634
638
|
|
|
635
639
|
row4 = QHBoxLayout()
|
|
636
|
-
self.run_btn = QPushButton("Run")
|
|
637
|
-
self.close_btn = QPushButton("Close")
|
|
640
|
+
self.run_btn = QPushButton(self.tr("Run"))
|
|
641
|
+
self.close_btn = QPushButton(self.tr("Close"))
|
|
638
642
|
row4.addStretch(); row4.addWidget(self.run_btn); row4.addWidget(self.close_btn)
|
|
639
643
|
|
|
640
644
|
v.addLayout(row1)
|
|
@@ -660,11 +664,11 @@ class BatchFITSHeaderDialog(QDialog):
|
|
|
660
664
|
|
|
661
665
|
def _pick_files(self):
|
|
662
666
|
last = self._settings().value("fits_modifier/batch_dir", "", type=str) or ""
|
|
663
|
-
files, _ = QFileDialog.getOpenFileNames(self, "Select FITS files", last, "FITS files (*.fits *.fit *.fts *.fz)")
|
|
667
|
+
files, _ = QFileDialog.getOpenFileNames(self, self.tr("Select FITS files"), last, self.tr("FITS files (*.fits *.fit *.fts *.fz)"))
|
|
664
668
|
if not files:
|
|
665
669
|
return
|
|
666
670
|
self.files = files
|
|
667
|
-
self.files_edit.setText(
|
|
671
|
+
self.files_edit.setText(self.tr("{0} files selected").format(len(files)))
|
|
668
672
|
self._settings().setValue("fits_modifier/batch_dir", os.path.dirname(files[0]))
|
|
669
673
|
|
|
670
674
|
def _parse_val(self, s: str):
|
|
@@ -689,14 +693,14 @@ class BatchFITSHeaderDialog(QDialog):
|
|
|
689
693
|
|
|
690
694
|
def _run(self):
|
|
691
695
|
if not self.files:
|
|
692
|
-
QMessageBox.warning(self, "No files", "Please choose one or more FITS files.")
|
|
696
|
+
QMessageBox.warning(self, self.tr("No files"), self.tr("Please choose one or more FITS files."))
|
|
693
697
|
return
|
|
694
698
|
key = self.key_edit.text().strip()
|
|
695
699
|
if not key:
|
|
696
|
-
QMessageBox.warning(self, "Missing keyword", "Please enter a FITS keyword.")
|
|
700
|
+
QMessageBox.warning(self, self.tr("Missing keyword"), self.tr("Please enter a FITS keyword."))
|
|
697
701
|
return
|
|
698
702
|
|
|
699
|
-
mode = self.mode_combo.
|
|
703
|
+
mode = self.mode_combo.currentData()
|
|
700
704
|
apply_all_hdus = self.all_hdus_chk.isChecked()
|
|
701
705
|
add_if_missing = self.add_if_missing_chk.isChecked()
|
|
702
706
|
com = self.com_edit.text().strip()
|
|
@@ -741,4 +745,4 @@ class BatchFITSHeaderDialog(QDialog):
|
|
|
741
745
|
print(f"[Batch FITS] Error on {fp}: {e}")
|
|
742
746
|
n_err += 1
|
|
743
747
|
|
|
744
|
-
QMessageBox.information(self, "Batch Complete",
|
|
748
|
+
QMessageBox.information(self, self.tr("Batch Complete"), self.tr("Updated {0} file(s); {1} error(s).").format(n_ok, n_err))
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
|
|
2
|
+
import os
|
|
3
|
+
import codecs
|
|
4
|
+
|
|
5
|
+
def remove_bom(base_dir):
|
|
6
|
+
count = 0
|
|
7
|
+
for root, dirs, files in os.walk(base_dir):
|
|
8
|
+
for name in files:
|
|
9
|
+
if name.endswith(".py"):
|
|
10
|
+
path = os.path.join(root, name)
|
|
11
|
+
try:
|
|
12
|
+
with open(path, 'rb') as f:
|
|
13
|
+
raw = f.read(3)
|
|
14
|
+
|
|
15
|
+
if raw.startswith(codecs.BOM_UTF8):
|
|
16
|
+
print(f"Removing BOM from {path}")
|
|
17
|
+
with open(path, 'rb') as f:
|
|
18
|
+
content = f.read()
|
|
19
|
+
|
|
20
|
+
# strip BOM
|
|
21
|
+
content = content[3:]
|
|
22
|
+
|
|
23
|
+
with open(path, 'wb') as f:
|
|
24
|
+
f.write(content)
|
|
25
|
+
count += 1
|
|
26
|
+
except Exception as e:
|
|
27
|
+
print(f"Error processing {path}: {e}")
|
|
28
|
+
print(f"Removed BOM from {count} files.")
|
|
29
|
+
|
|
30
|
+
if __name__ == "__main__":
|
|
31
|
+
base_dir = os.path.dirname(os.path.abspath(__file__))
|
|
32
|
+
remove_bom(base_dir)
|
|
@@ -237,7 +237,7 @@ class FrequencySeperationTab(QWidget):
|
|
|
237
237
|
left.addWidget(self.fileLabel)
|
|
238
238
|
|
|
239
239
|
# Method
|
|
240
|
-
left.addWidget(QLabel("Method:", self))
|
|
240
|
+
left.addWidget(QLabel(self.tr("Method:"), self))
|
|
241
241
|
self.method_combo = QComboBox(self)
|
|
242
242
|
self.method_combo.addItems(['Gaussian', 'Median', 'Bilateral'])
|
|
243
243
|
self.method_combo.currentTextChanged.connect(self._on_method_changed)
|
|
@@ -259,14 +259,14 @@ class FrequencySeperationTab(QWidget):
|
|
|
259
259
|
self._toggle_tol_enabled(False)
|
|
260
260
|
|
|
261
261
|
# Apply separation
|
|
262
|
-
btn_apply = QPushButton("Apply
|
|
262
|
+
btn_apply = QPushButton(self.tr("Apply - Split HF & LF"), self)
|
|
263
263
|
btn_apply.clicked.connect(self._apply_separation)
|
|
264
264
|
left.addWidget(btn_apply)
|
|
265
265
|
|
|
266
|
-
left.addWidget(QLabel("<b>HF Enhancements</b>", self))
|
|
266
|
+
left.addWidget(QLabel(self.tr("<b>HF Enhancements</b>"), self))
|
|
267
267
|
|
|
268
268
|
# Sharpen scale
|
|
269
|
-
self.cb_scale = QCheckBox("Enable Sharpen Scale", self)
|
|
269
|
+
self.cb_scale = QCheckBox(self.tr("Enable Sharpen Scale"), self)
|
|
270
270
|
self.cb_scale.setChecked(True); left.addWidget(self.cb_scale)
|
|
271
271
|
self.scale_label = QLabel("Sharpen Scale: 1.00", self); left.addWidget(self.scale_label)
|
|
272
272
|
self.scale_slider = QSlider(Qt.Orientation.Horizontal, self)
|
|
@@ -275,7 +275,7 @@ class FrequencySeperationTab(QWidget):
|
|
|
275
275
|
left.addWidget(self.scale_slider)
|
|
276
276
|
|
|
277
277
|
# Wavelet
|
|
278
|
-
self.cb_wavelet = QCheckBox("Enable Wavelet Sharpening", self)
|
|
278
|
+
self.cb_wavelet = QCheckBox(self.tr("Enable Wavelet Sharpening"), self)
|
|
279
279
|
self.cb_wavelet.setChecked(True); left.addWidget(self.cb_wavelet)
|
|
280
280
|
self.wavelet_level_label = QLabel("Wavelet Level: 2", self); left.addWidget(self.wavelet_level_label)
|
|
281
281
|
self.wavelet_level_slider = QSlider(Qt.Orientation.Horizontal, self)
|
|
@@ -290,7 +290,7 @@ class FrequencySeperationTab(QWidget):
|
|
|
290
290
|
left.addWidget(self.wavelet_boost_slider)
|
|
291
291
|
|
|
292
292
|
# Denoise
|
|
293
|
-
self.cb_denoise = QCheckBox("Enable HF Denoise", self)
|
|
293
|
+
self.cb_denoise = QCheckBox(self.tr("Enable HF Denoise"), self)
|
|
294
294
|
self.cb_denoise.setChecked(False); left.addWidget(self.cb_denoise)
|
|
295
295
|
self.denoise_label = QLabel("Denoise Strength: 3.00", self); left.addWidget(self.denoise_label)
|
|
296
296
|
self.denoise_slider = QSlider(Qt.Orientation.Horizontal, self)
|
|
@@ -300,7 +300,7 @@ class FrequencySeperationTab(QWidget):
|
|
|
300
300
|
|
|
301
301
|
# HF actions row
|
|
302
302
|
row = QHBoxLayout()
|
|
303
|
-
self.btn_apply_hf = QPushButton("Apply HF Enhancements", self)
|
|
303
|
+
self.btn_apply_hf = QPushButton(self.tr("Apply HF Enhancements"), self)
|
|
304
304
|
self.btn_apply_hf.setIcon(self.style().standardIcon(QStyle.StandardPixmap.SP_DialogApplyButton))
|
|
305
305
|
self.btn_apply_hf.clicked.connect(self._apply_hf_enhancements)
|
|
306
306
|
row.addWidget(self.btn_apply_hf)
|
|
@@ -315,8 +315,8 @@ class FrequencySeperationTab(QWidget):
|
|
|
315
315
|
|
|
316
316
|
# Push buttons
|
|
317
317
|
push_row = QHBoxLayout()
|
|
318
|
-
self.btn_push_lf = QPushButton("Push LF", self); self.btn_push_lf.clicked.connect(lambda: self._push_array(self.low_freq_image, "LF"))
|
|
319
|
-
self.btn_push_hf = QPushButton("Push HF", self); self.btn_push_hf.clicked.connect(lambda: self._push_array(self._hf_display_for_push(), "HF"))
|
|
318
|
+
self.btn_push_lf = QPushButton(self.tr("Push LF"), self); self.btn_push_lf.clicked.connect(lambda: self._push_array(self.low_freq_image, "LF"))
|
|
319
|
+
self.btn_push_hf = QPushButton(self.tr("Push HF"), self); self.btn_push_hf.clicked.connect(lambda: self._push_array(self._hf_display_for_push(), "HF"))
|
|
320
320
|
push_row.addWidget(self.btn_push_lf); push_row.addWidget(self.btn_push_hf)
|
|
321
321
|
left.addLayout(push_row)
|
|
322
322
|
|
|
@@ -342,7 +342,7 @@ class FrequencySeperationTab(QWidget):
|
|
|
342
342
|
|
|
343
343
|
left.addLayout(load_row)
|
|
344
344
|
|
|
345
|
-
btn_combine_push = QPushButton("Combine HF+LF
|
|
345
|
+
btn_combine_push = QPushButton(self.tr("Combine HF+LF -> Push"), self)
|
|
346
346
|
btn_combine_push.clicked.connect(self._combine_and_push)
|
|
347
347
|
left.addWidget(btn_combine_push)
|
|
348
348
|
|
|
@@ -708,10 +708,16 @@ class FrequencySeperationTab(QWidget):
|
|
|
708
708
|
|
|
709
709
|
# channel reconcile
|
|
710
710
|
if rch == 1 and ch == 3:
|
|
711
|
-
# convert RGB→mono (luma or
|
|
711
|
+
# convert RGB→mono (use weighted luma for consistency, or mean if desired. Original was mean)
|
|
712
712
|
a = a.mean(axis=2).astype(np.float32)
|
|
713
713
|
elif rch == 3 and ch == 1:
|
|
714
|
-
|
|
714
|
+
# Broadcast mono to 3 channels without copying
|
|
715
|
+
# (H,W,1) -> (H,W,3) via broadcasted view if consumer allows,
|
|
716
|
+
# but usually downstream (like subtraction) handles broadcasting fine.
|
|
717
|
+
# If explicit physical layout is needed, we must check usage.
|
|
718
|
+
# Here: used for subtraction (OK) and preview (OK).
|
|
719
|
+
# We return a view using broadcast_to or striding tricks.
|
|
720
|
+
a = np.broadcast_to(a, (ah, aw, 3))
|
|
715
721
|
|
|
716
722
|
return a
|
|
717
723
|
|
|
@@ -202,7 +202,7 @@ class FunctionBundleChip(QWidget):
|
|
|
202
202
|
from PyQt6.QtWidgets import QMenu # already imported at top, but safe
|
|
203
203
|
|
|
204
204
|
m = QMenu(self)
|
|
205
|
-
act_del = m.addAction("Delete Chip")
|
|
205
|
+
act_del = m.addAction(self._panel.tr("Delete Chip"))
|
|
206
206
|
act = m.exec(ev.globalPos())
|
|
207
207
|
if act is act_del:
|
|
208
208
|
try:
|
|
@@ -333,7 +333,9 @@ class FunctionBundleDialog(QDialog):
|
|
|
333
333
|
def __init__(self, parent: QWidget | None = None):
|
|
334
334
|
super().__init__(parent)
|
|
335
335
|
_pin_on_top_mac(self)
|
|
336
|
-
self.setWindowTitle("Function Bundles")
|
|
336
|
+
self.setWindowTitle(self.tr("Function Bundles"))
|
|
337
|
+
self.setWindowFlag(Qt.WindowType.Window, True)
|
|
338
|
+
self.setWindowModality(Qt.WindowModality.NonModal)
|
|
337
339
|
self.setModal(False)
|
|
338
340
|
self.resize(920, 560)
|
|
339
341
|
self.setAcceptDrops(True)
|
|
@@ -348,9 +350,9 @@ class FunctionBundleDialog(QDialog):
|
|
|
348
350
|
self.list.setSelectionMode(QAbstractItemView.SelectionMode.SingleSelection)
|
|
349
351
|
self.list.setContextMenuPolicy(Qt.ContextMenuPolicy.CustomContextMenu)
|
|
350
352
|
|
|
351
|
-
self.btn_new = QPushButton("New")
|
|
352
|
-
self.btn_dup = QPushButton("Duplicate")
|
|
353
|
-
self.btn_del = QPushButton("Delete")
|
|
353
|
+
self.btn_new = QPushButton(self.tr("New"))
|
|
354
|
+
self.btn_dup = QPushButton(self.tr("Duplicate"))
|
|
355
|
+
self.btn_del = QPushButton(self.tr("Delete"))
|
|
354
356
|
|
|
355
357
|
# right: steps
|
|
356
358
|
self.steps = QListWidget()
|
|
@@ -366,26 +368,26 @@ class FunctionBundleDialog(QDialog):
|
|
|
366
368
|
self.steps.setResizeMode(QListView.ResizeMode.Adjust) # recompute item layout on width change
|
|
367
369
|
self.steps.setUniformItemSizes(False)
|
|
368
370
|
|
|
369
|
-
self.add_hint = QLabel("Drop shortcuts here to add steps")
|
|
371
|
+
self.add_hint = QLabel(self.tr("Drop shortcuts here to add steps"))
|
|
370
372
|
self.add_hint.setAlignment(Qt.AlignmentFlag.AlignCenter)
|
|
371
373
|
self.add_hint.setStyleSheet("color:#aaa; padding:6px; border:1px dashed #666; border-radius:6px;")
|
|
372
374
|
|
|
373
|
-
self.btn_edit_preset = QPushButton("Edit Preset…")
|
|
375
|
+
self.btn_edit_preset = QPushButton(self.tr("Edit Preset…"))
|
|
374
376
|
self.btn_edit_preset.setEnabled(False) # enabled when exactly one step is selected
|
|
375
377
|
|
|
376
|
-
self.btn_remove = QPushButton("Remove Selected")
|
|
377
|
-
self.btn_clear = QPushButton("Clear Steps")
|
|
378
|
-
self.btn_up = QPushButton("▲ Move Up")
|
|
379
|
-
self.btn_down = QPushButton("▼ Move Down")
|
|
378
|
+
self.btn_remove = QPushButton(self.tr("Remove Selected"))
|
|
379
|
+
self.btn_clear = QPushButton(self.tr("Clear Steps"))
|
|
380
|
+
self.btn_up = QPushButton(self.tr("▲ Move Up"))
|
|
381
|
+
self.btn_down = QPushButton(self.tr("▼ Move Down"))
|
|
380
382
|
|
|
381
|
-
self.btn_drag_bundle = QPushButton("Drag Bundle")
|
|
382
|
-
self.btn_run_active = QPushButton("Apply to Active View")
|
|
383
|
-
self.btn_apply_to_vbundle = QPushButton("Apply to View Bundle…")
|
|
384
|
-
self.btn_chip = QPushButton("Compress to Chip")
|
|
383
|
+
self.btn_drag_bundle = QPushButton(self.tr("Drag Bundle"))
|
|
384
|
+
self.btn_run_active = QPushButton(self.tr("Apply to Active View"))
|
|
385
|
+
self.btn_apply_to_vbundle = QPushButton(self.tr("Apply to View Bundle…"))
|
|
386
|
+
self.btn_chip = QPushButton(self.tr("Compress to Chip"))
|
|
385
387
|
|
|
386
388
|
# layout
|
|
387
389
|
left = QVBoxLayout()
|
|
388
|
-
left.addWidget(QLabel("Function Bundles"))
|
|
390
|
+
left.addWidget(QLabel(self.tr("Function Bundles")))
|
|
389
391
|
left.addWidget(self.list, 1)
|
|
390
392
|
row = QHBoxLayout()
|
|
391
393
|
row.addWidget(self.btn_new); row.addWidget(self.btn_dup); row.addWidget(self.btn_del)
|