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
|
@@ -24,7 +24,7 @@ from setiastro.saspro.legacy.image_manager import load_image, save_image
|
|
|
24
24
|
from setiastro.saspro.legacy.numba_utils import bulk_cosmetic_correction_numba
|
|
25
25
|
from setiastro.saspro.imageops.stretch import stretch_mono_image, stretch_color_image
|
|
26
26
|
from setiastro.saspro.star_alignment import PolyGradientRemoval
|
|
27
|
-
from
|
|
27
|
+
from setiastro.saspro import minorbodycatalog as mbc
|
|
28
28
|
from setiastro.saspro.plate_solver import PlateSolverDialog as PlateSolver
|
|
29
29
|
from setiastro.saspro.widgets.themed_buttons import themed_toolbtn
|
|
30
30
|
|
|
@@ -159,7 +159,7 @@ class MinorBodyWorker(QObject):
|
|
|
159
159
|
def run(self):
|
|
160
160
|
try:
|
|
161
161
|
# Kick off with a low percentage
|
|
162
|
-
self.progress.emit(0, "Minor-body search: preparing catalog query...")
|
|
162
|
+
self.progress.emit(0, self.tr("Minor-body search: preparing catalog query..."))
|
|
163
163
|
bodies = self._owner._get_predicted_minor_bodies_for_field(
|
|
164
164
|
H_ast_max=self._owner.minor_H_ast_max,
|
|
165
165
|
H_com_max=self._owner.minor_H_com_max,
|
|
@@ -292,11 +292,11 @@ class ImagePreviewWindow(QDialog):
|
|
|
292
292
|
|
|
293
293
|
# toolbar
|
|
294
294
|
tb = QToolBar(self)
|
|
295
|
-
self.act_fit = QAction("Fit", self)
|
|
296
|
-
self.act_1to1 = QAction("1:1", self)
|
|
297
|
-
self.act_zoom_in = QAction("Zoom In", self)
|
|
298
|
-
self.act_zoom_out = QAction("Zoom Out", self)
|
|
299
|
-
self.act_push = QAction("Push to New View", self)
|
|
295
|
+
self.act_fit = QAction(self.tr("Fit"), self)
|
|
296
|
+
self.act_1to1 = QAction(self.tr("1:1"), self)
|
|
297
|
+
self.act_zoom_in = QAction(self.tr("Zoom In"), self)
|
|
298
|
+
self.act_zoom_out = QAction(self.tr("Zoom Out"), self)
|
|
299
|
+
self.act_push = QAction(self.tr("Push to New View"), self)
|
|
300
300
|
# self.act_minor = QAction("Check Catalogued Minor Bodies in Field", self)
|
|
301
301
|
|
|
302
302
|
self.act_zoom_in.setShortcut("Ctrl++")
|
|
@@ -343,7 +343,7 @@ class ImagePreviewWindow(QDialog):
|
|
|
343
343
|
def _on_push(self):
|
|
344
344
|
# Emit the anomaly-marked image
|
|
345
345
|
self.pushed.emit(self._original, self.windowTitle())
|
|
346
|
-
QMessageBox.information(self, "Pushed", "New View Created.")
|
|
346
|
+
QMessageBox.information(self, self.tr("Pushed"), self.tr("New View Created."))
|
|
347
347
|
|
|
348
348
|
|
|
349
349
|
def _on_minor_body_search(self):
|
|
@@ -361,7 +361,10 @@ class SupernovaAsteroidHunterDialog(QDialog):
|
|
|
361
361
|
image_manager=None, doc_manager=None,
|
|
362
362
|
supernova_path=None, wrench_path=None, spinner_path=None):
|
|
363
363
|
super().__init__(parent)
|
|
364
|
-
self.setWindowTitle("Supernova / Asteroid Hunter")
|
|
364
|
+
self.setWindowTitle(self.tr("Supernova / Asteroid Hunter"))
|
|
365
|
+
self.setWindowFlag(Qt.WindowType.Window, True)
|
|
366
|
+
self.setWindowModality(Qt.WindowModality.NonModal)
|
|
367
|
+
self.setModal(False)
|
|
365
368
|
if supernova_path:
|
|
366
369
|
self.setWindowIcon(QIcon(supernova_path))
|
|
367
370
|
# keep icon path for previews
|
|
@@ -404,17 +407,17 @@ class SupernovaAsteroidHunterDialog(QDialog):
|
|
|
404
407
|
layout = self.layout()
|
|
405
408
|
|
|
406
409
|
# Instruction Label
|
|
407
|
-
instructions = QLabel(
|
|
410
|
+
instructions = QLabel(self.tr(
|
|
408
411
|
"Select the reference image and search images. "
|
|
409
412
|
"Then click Process to hunt for anomalies."
|
|
410
|
-
)
|
|
413
|
+
))
|
|
411
414
|
layout.addWidget(instructions)
|
|
412
415
|
|
|
413
416
|
# --- Reference Image Selection ---
|
|
414
417
|
ref_layout = QHBoxLayout()
|
|
415
418
|
self.ref_line_edit = QLineEdit(self)
|
|
416
|
-
self.ref_line_edit.setPlaceholderText("No reference image selected")
|
|
417
|
-
self.ref_button = QPushButton("Select Reference Image", self)
|
|
419
|
+
self.ref_line_edit.setPlaceholderText(self.tr("No reference image selected"))
|
|
420
|
+
self.ref_button = QPushButton(self.tr("Select Reference Image"), self)
|
|
418
421
|
self.ref_button.clicked.connect(self.selectReferenceImage)
|
|
419
422
|
ref_layout.addWidget(self.ref_line_edit)
|
|
420
423
|
ref_layout.addWidget(self.ref_button)
|
|
@@ -423,7 +426,7 @@ class SupernovaAsteroidHunterDialog(QDialog):
|
|
|
423
426
|
# --- Search Images Selection ---
|
|
424
427
|
search_layout = QHBoxLayout()
|
|
425
428
|
self.search_list = QListWidget(self)
|
|
426
|
-
self.search_button = QPushButton("Select Search Images", self)
|
|
429
|
+
self.search_button = QPushButton(self.tr("Select Search Images"), self)
|
|
427
430
|
self.search_button.clicked.connect(self.selectSearchImages)
|
|
428
431
|
search_layout.addWidget(self.search_list)
|
|
429
432
|
search_layout.addWidget(self.search_button)
|
|
@@ -431,13 +434,13 @@ class SupernovaAsteroidHunterDialog(QDialog):
|
|
|
431
434
|
|
|
432
435
|
# --- Cosmetic Correction Checkbox ---
|
|
433
436
|
self.cosmetic_checkbox = QCheckBox(
|
|
434
|
-
"Apply Cosmetic Correction before Preprocessing", self
|
|
437
|
+
self.tr("Apply Cosmetic Correction before Preprocessing"), self
|
|
435
438
|
)
|
|
436
439
|
layout.addWidget(self.cosmetic_checkbox)
|
|
437
440
|
|
|
438
441
|
# --- Threshold Slider ---
|
|
439
442
|
thresh_layout = QHBoxLayout()
|
|
440
|
-
self.thresh_label = QLabel("Anomaly Detection Threshold: 0.10", self)
|
|
443
|
+
self.thresh_label = QLabel(self.tr("Anomaly Detection Threshold: 0.10"), self)
|
|
441
444
|
self.thresh_slider = QSlider(Qt.Orientation.Horizontal, self)
|
|
442
445
|
self.thresh_slider.setMinimum(1)
|
|
443
446
|
self.thresh_slider.setMaximum(50) # Represents 0.01 to 0.50
|
|
@@ -449,19 +452,19 @@ class SupernovaAsteroidHunterDialog(QDialog):
|
|
|
449
452
|
|
|
450
453
|
# --- Process Button ---
|
|
451
454
|
self.process_button = QPushButton(
|
|
452
|
-
"Process (Cosmetic Correction, Preprocess, and Search)", self
|
|
455
|
+
self.tr("Process (Cosmetic Correction, Preprocess, and Search)"), self
|
|
453
456
|
)
|
|
454
457
|
self.process_button.clicked.connect(self.process)
|
|
455
458
|
layout.addWidget(self.process_button)
|
|
456
459
|
|
|
457
460
|
# --- Progress Labels ---
|
|
458
|
-
self.preprocess_progress_label = QLabel("Preprocessing progress: 0 / 0", self)
|
|
459
|
-
self.search_progress_label = QLabel("Processing progress: 0 / 0", self)
|
|
461
|
+
self.preprocess_progress_label = QLabel(self.tr("Preprocessing progress: 0 / 0"), self)
|
|
462
|
+
self.search_progress_label = QLabel(self.tr("Processing progress: 0 / 0"), self)
|
|
460
463
|
layout.addWidget(self.preprocess_progress_label)
|
|
461
464
|
layout.addWidget(self.search_progress_label)
|
|
462
465
|
|
|
463
466
|
# -- Status label --
|
|
464
|
-
self.status_label = QLabel("Status: Idle", self)
|
|
467
|
+
self.status_label = QLabel(self.tr("Status: Idle"), self)
|
|
465
468
|
layout.addWidget(self.status_label)
|
|
466
469
|
|
|
467
470
|
# Minor-body progress bar (hidden by default)
|
|
@@ -472,7 +475,7 @@ class SupernovaAsteroidHunterDialog(QDialog):
|
|
|
472
475
|
layout.addWidget(self.minor_progress)
|
|
473
476
|
|
|
474
477
|
# --- New Instance Button ---
|
|
475
|
-
self.new_instance_button = QPushButton("New Instance", self)
|
|
478
|
+
self.new_instance_button = QPushButton(self.tr("New Instance"), self)
|
|
476
479
|
self.new_instance_button.clicked.connect(self.newInstance)
|
|
477
480
|
layout.addWidget(self.new_instance_button)
|
|
478
481
|
|
|
@@ -484,18 +487,18 @@ class SupernovaAsteroidHunterDialog(QDialog):
|
|
|
484
487
|
def updateThreshold(self, value):
|
|
485
488
|
threshold = value / 100.0 # e.g. slider value 10 becomes 0.10
|
|
486
489
|
self.parameters["threshold"] = threshold
|
|
487
|
-
self.thresh_label.setText(
|
|
490
|
+
self.thresh_label.setText(self.tr("Anomaly Detection Threshold: {0:.2f}").format(threshold))
|
|
488
491
|
|
|
489
492
|
def selectReferenceImage(self):
|
|
490
|
-
file_path, _ = QFileDialog.getOpenFileName(self, "Select Reference Image", "",
|
|
491
|
-
"Images (*.png *.tif *.tiff *.fits *.fit *.xisf)")
|
|
493
|
+
file_path, _ = QFileDialog.getOpenFileName(self, self.tr("Select Reference Image"), "",
|
|
494
|
+
self.tr("Images (*.png *.tif *.tiff *.fits *.fit *.xisf)"))
|
|
492
495
|
if file_path:
|
|
493
496
|
self.parameters["referenceImagePath"] = file_path
|
|
494
497
|
self.ref_line_edit.setText(os.path.basename(file_path))
|
|
495
498
|
|
|
496
499
|
def selectSearchImages(self):
|
|
497
|
-
file_paths, _ = QFileDialog.getOpenFileNames(self, "Select Search Images", "",
|
|
498
|
-
"Images (*.png *.tif *.tiff *.fits *.fit *.xisf)")
|
|
500
|
+
file_paths, _ = QFileDialog.getOpenFileNames(self, self.tr("Select Search Images"), "",
|
|
501
|
+
self.tr("Images (*.png *.tif *.tiff *.fits *.fit *.xisf)"))
|
|
499
502
|
if file_paths:
|
|
500
503
|
self.parameters["searchImagePaths"] = file_paths
|
|
501
504
|
self.search_list.clear()
|
|
@@ -503,24 +506,24 @@ class SupernovaAsteroidHunterDialog(QDialog):
|
|
|
503
506
|
self.search_list.addItem(os.path.basename(path))
|
|
504
507
|
|
|
505
508
|
def process(self):
|
|
506
|
-
self.status_label.setText("Process started...")
|
|
509
|
+
self.status_label.setText(self.tr("Process started..."))
|
|
507
510
|
QApplication.processEvents()
|
|
508
511
|
|
|
509
512
|
# If cosmetic correction is enabled, run it first
|
|
510
513
|
if self.cosmetic_checkbox.isChecked():
|
|
511
|
-
self.status_label.setText("Running Cosmetic Correction...")
|
|
514
|
+
self.status_label.setText(self.tr("Running Cosmetic Correction..."))
|
|
512
515
|
QApplication.processEvents()
|
|
513
516
|
self.runCosmeticCorrectionIfNeeded()
|
|
514
517
|
|
|
515
|
-
self.status_label.setText("Preprocessing images...")
|
|
518
|
+
self.status_label.setText(self.tr("Preprocessing images..."))
|
|
516
519
|
QApplication.processEvents()
|
|
517
520
|
self.preprocessImages()
|
|
518
521
|
|
|
519
|
-
self.status_label.setText("Analyzing anomalies...")
|
|
522
|
+
self.status_label.setText(self.tr("Analyzing anomalies..."))
|
|
520
523
|
QApplication.processEvents()
|
|
521
524
|
self.runSearch()
|
|
522
525
|
|
|
523
|
-
self.status_label.setText("Process complete.")
|
|
526
|
+
self.status_label.setText(self.tr("Process complete."))
|
|
524
527
|
QApplication.processEvents()
|
|
525
528
|
|
|
526
529
|
|
|
@@ -534,7 +537,9 @@ class SupernovaAsteroidHunterDialog(QDialog):
|
|
|
534
537
|
for idx, image_path in enumerate(self.parameters["searchImagePaths"]):
|
|
535
538
|
try:
|
|
536
539
|
# Update status label to show which image is being handled
|
|
537
|
-
self.status_label.setText(
|
|
540
|
+
self.status_label.setText(self.tr("Cosmetic Correction: {0}/{1} => {2}").format(
|
|
541
|
+
idx+1, len(self.parameters['searchImagePaths']), os.path.basename(image_path)
|
|
542
|
+
))
|
|
538
543
|
QApplication.processEvents()
|
|
539
544
|
|
|
540
545
|
img, header, bit_depth, is_mono = load_image(image_path)
|
|
@@ -558,13 +563,13 @@ class SupernovaAsteroidHunterDialog(QDialog):
|
|
|
558
563
|
|
|
559
564
|
def preprocessImages(self):
|
|
560
565
|
# Update status label for reference image
|
|
561
|
-
self.status_label.setText("Preprocessing reference image...")
|
|
566
|
+
self.status_label.setText(self.tr("Preprocessing reference image..."))
|
|
562
567
|
print("[Preprocessing] Preprocessing reference image...")
|
|
563
568
|
QApplication.processEvents()
|
|
564
569
|
|
|
565
570
|
ref_path = self.parameters["referenceImagePath"]
|
|
566
571
|
if not ref_path:
|
|
567
|
-
QMessageBox.warning(self, "Error", "No reference image selected.")
|
|
572
|
+
QMessageBox.warning(self, self.tr("Error"), self.tr("No reference image selected."))
|
|
568
573
|
return
|
|
569
574
|
|
|
570
575
|
try:
|
|
@@ -623,11 +628,11 @@ class SupernovaAsteroidHunterDialog(QDialog):
|
|
|
623
628
|
ref_processed = self.preprocessImage(ref_img, debug_prefix=debug_prefix_ref)
|
|
624
629
|
self.preprocessed_reference = ref_processed
|
|
625
630
|
self.preprocess_progress_label.setText(
|
|
626
|
-
"Preprocessing reference image... Done."
|
|
631
|
+
self.tr("Preprocessing reference image... Done.")
|
|
627
632
|
)
|
|
628
633
|
|
|
629
634
|
except Exception as e:
|
|
630
|
-
QMessageBox.critical(self, "Error",
|
|
635
|
+
QMessageBox.critical(self, self.tr("Error"), self.tr("Failed to preprocess reference image: {0}").format(e))
|
|
631
636
|
return
|
|
632
637
|
|
|
633
638
|
# --- Preprocess search images ---
|
|
@@ -638,7 +643,9 @@ class SupernovaAsteroidHunterDialog(QDialog):
|
|
|
638
643
|
for i, path in enumerate(search_paths):
|
|
639
644
|
try:
|
|
640
645
|
self.status_label.setText(
|
|
641
|
-
|
|
646
|
+
self.tr("Preprocessing search image {0}/{1} => {2}").format(
|
|
647
|
+
i+1, total, os.path.basename(path)
|
|
648
|
+
)
|
|
642
649
|
)
|
|
643
650
|
QApplication.processEvents()
|
|
644
651
|
|
|
@@ -653,14 +660,14 @@ class SupernovaAsteroidHunterDialog(QDialog):
|
|
|
653
660
|
self.preprocessed_search.append({"path": path, "image": processed})
|
|
654
661
|
|
|
655
662
|
self.preprocess_progress_label.setText(
|
|
656
|
-
|
|
663
|
+
self.tr("Preprocessing image {0} of {1}... Done.").format(i+1, total)
|
|
657
664
|
)
|
|
658
665
|
QApplication.processEvents()
|
|
659
666
|
|
|
660
667
|
except Exception as e:
|
|
661
668
|
print(f"Failed to preprocess {path}: {e}")
|
|
662
669
|
|
|
663
|
-
self.status_label.setText("All search images preprocessed.")
|
|
670
|
+
self.status_label.setText(self.tr("All search images preprocessed."))
|
|
664
671
|
QApplication.processEvents()
|
|
665
672
|
|
|
666
673
|
def _ensure_wcs(self, ref_path: str):
|
|
@@ -736,7 +743,7 @@ class SupernovaAsteroidHunterDialog(QDialog):
|
|
|
736
743
|
False if they cancelled.
|
|
737
744
|
"""
|
|
738
745
|
dlg = QDialog(self)
|
|
739
|
-
dlg.setWindowTitle("Minor-body Search Limits")
|
|
746
|
+
dlg.setWindowTitle(self.tr("Minor-body Search Limits"))
|
|
740
747
|
layout = QVBoxLayout(dlg)
|
|
741
748
|
|
|
742
749
|
row_layout = QGridLayout()
|
|
@@ -837,29 +844,29 @@ class SupernovaAsteroidHunterDialog(QDialog):
|
|
|
837
844
|
print("[MinorBodies] prediction failed:", error)
|
|
838
845
|
QMessageBox.critical(
|
|
839
846
|
self,
|
|
840
|
-
"Minor-body Search",
|
|
841
|
-
|
|
847
|
+
self.tr("Minor-body Search"),
|
|
848
|
+
self.tr("Minor-body prediction failed:\n{0}").format(error)
|
|
842
849
|
)
|
|
843
|
-
self.status_label.setText("Minor-body search failed.")
|
|
850
|
+
self.status_label.setText(self.tr("Minor-body search failed."))
|
|
844
851
|
return
|
|
845
852
|
|
|
846
853
|
self.predicted_minor_bodies = bodies or []
|
|
847
854
|
|
|
848
855
|
if not self.predicted_minor_bodies:
|
|
849
856
|
self.status_label.setText(
|
|
850
|
-
"Minor-body search complete: no catalogued objects in this field "
|
|
851
|
-
|
|
857
|
+
self.tr("Minor-body search complete: no catalogued objects in this field "
|
|
858
|
+
"for the current magnitude limits.")
|
|
852
859
|
)
|
|
853
860
|
QMessageBox.information(
|
|
854
861
|
self,
|
|
855
|
-
"Minor-body Search",
|
|
856
|
-
"No catalogued minor bodies (within the configured magnitude limits) "
|
|
857
|
-
|
|
862
|
+
self.tr("Minor-body Search"),
|
|
863
|
+
self.tr("No catalogued minor bodies (within the configured magnitude limits) "
|
|
864
|
+
"were found in this field.")
|
|
858
865
|
)
|
|
859
866
|
return
|
|
860
867
|
|
|
861
868
|
self.status_label.setText(
|
|
862
|
-
|
|
869
|
+
self.tr("Minor-body search complete: {0} objects in field.").format(len(self.predicted_minor_bodies))
|
|
863
870
|
)
|
|
864
871
|
QApplication.processEvents()
|
|
865
872
|
|
|
@@ -876,10 +883,10 @@ class SupernovaAsteroidHunterDialog(QDialog):
|
|
|
876
883
|
else:
|
|
877
884
|
QMessageBox.information(
|
|
878
885
|
self,
|
|
879
|
-
"Minor-body Search",
|
|
880
|
-
"Minor bodies in field have been computed.\n\n"
|
|
881
|
-
|
|
882
|
-
|
|
886
|
+
self.tr("Minor-body Search"),
|
|
887
|
+
self.tr("Minor bodies in field have been computed.\n\n"
|
|
888
|
+
"Run the anomaly search (Process) to cross-match detections "
|
|
889
|
+
"against the predicted objects.")
|
|
883
890
|
)
|
|
884
891
|
except Exception as e:
|
|
885
892
|
print("[MinorBodies] cross-match failed:", e)
|
|
@@ -897,26 +904,26 @@ class SupernovaAsteroidHunterDialog(QDialog):
|
|
|
897
904
|
if not ref_path:
|
|
898
905
|
QMessageBox.warning(
|
|
899
906
|
self,
|
|
900
|
-
"Minor-body Search",
|
|
901
|
-
"No reference image selected.\n\n"
|
|
902
|
-
|
|
907
|
+
self.tr("Minor-body Search"),
|
|
908
|
+
self.tr("No reference image selected.\n\n"
|
|
909
|
+
"Please select a reference image and run Process first.")
|
|
903
910
|
)
|
|
904
911
|
return
|
|
905
912
|
|
|
906
913
|
if self.preprocessed_reference is None:
|
|
907
914
|
QMessageBox.warning(
|
|
908
915
|
self,
|
|
909
|
-
"Minor-body Search",
|
|
910
|
-
"Reference image has not been preprocessed yet.\n\n"
|
|
911
|
-
|
|
916
|
+
self.tr("Minor-body Search"),
|
|
917
|
+
self.tr("Reference image has not been preprocessed yet.\n\n"
|
|
918
|
+
"Please click 'Process' before running the minor-body search.")
|
|
912
919
|
)
|
|
913
920
|
return
|
|
914
921
|
|
|
915
922
|
if self.settings is None:
|
|
916
923
|
QMessageBox.warning(
|
|
917
924
|
self,
|
|
918
|
-
"Minor-body Search",
|
|
919
|
-
"Settings object is not available; cannot locate the minor-body database path."
|
|
925
|
+
self.tr("Minor-body Search"),
|
|
926
|
+
self.tr("Settings object is not available; cannot locate the minor-body database path.")
|
|
920
927
|
)
|
|
921
928
|
return
|
|
922
929
|
|
setiastro/saspro/swap_manager.py
CHANGED
|
@@ -1,10 +1,5 @@
|
|
|
1
|
-
import os
|
|
2
|
-
import
|
|
3
|
-
import tempfile
|
|
4
|
-
import uuid
|
|
5
|
-
import pickle
|
|
6
|
-
import atexit
|
|
7
|
-
import threading
|
|
1
|
+
import os, shutil, tempfile, uuid, atexit, threading
|
|
2
|
+
from collections import OrderedDict
|
|
8
3
|
import numpy as np
|
|
9
4
|
|
|
10
5
|
class SwapManager:
|
|
@@ -14,66 +9,110 @@ class SwapManager:
|
|
|
14
9
|
def __new__(cls, *args, **kwargs):
|
|
15
10
|
with cls._lock:
|
|
16
11
|
if cls._instance is None:
|
|
17
|
-
cls._instance = super(
|
|
12
|
+
cls._instance = super().__new__(cls)
|
|
18
13
|
cls._instance._initialized = False
|
|
19
14
|
return cls._instance
|
|
20
15
|
|
|
21
|
-
def __init__(self):
|
|
16
|
+
def __init__(self, *, cache_bytes: int = 1_000_000_000):
|
|
22
17
|
if self._initialized:
|
|
23
18
|
return
|
|
24
19
|
self._initialized = True
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
20
|
+
|
|
21
|
+
self.temp_dir = os.path.join(
|
|
22
|
+
tempfile.gettempdir(), "SetiAstroSuitePro_Swap", str(uuid.uuid4())
|
|
23
|
+
)
|
|
28
24
|
os.makedirs(self.temp_dir, exist_ok=True)
|
|
29
|
-
|
|
30
|
-
# Register cleanup on exit
|
|
31
25
|
atexit.register(self.cleanup_all)
|
|
32
26
|
|
|
27
|
+
# LRU of in-RAM states: swap_id -> ndarray
|
|
28
|
+
self._cache = OrderedDict()
|
|
29
|
+
self._cache_bytes = int(cache_bytes)
|
|
30
|
+
self._cache_used = 0
|
|
31
|
+
self._cache_lock = threading.Lock()
|
|
32
|
+
|
|
33
33
|
def get_swap_path(self, swap_id: str) -> str:
|
|
34
|
-
|
|
34
|
+
# store as .npy (fast + supports mmap)
|
|
35
|
+
return os.path.join(self.temp_dir, f"{swap_id}.npy")
|
|
36
|
+
|
|
37
|
+
def _arr_nbytes(self, a: np.ndarray) -> int:
|
|
38
|
+
try:
|
|
39
|
+
return int(a.nbytes)
|
|
40
|
+
except Exception:
|
|
41
|
+
return 0
|
|
42
|
+
|
|
43
|
+
def _cache_put(self, swap_id: str, arr: np.ndarray):
|
|
44
|
+
if arr is None:
|
|
45
|
+
return
|
|
46
|
+
n = self._arr_nbytes(arr)
|
|
47
|
+
if n <= 0:
|
|
48
|
+
return
|
|
35
49
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
50
|
+
with self._cache_lock:
|
|
51
|
+
# If already present, refresh
|
|
52
|
+
old = self._cache.pop(swap_id, None)
|
|
53
|
+
if old is not None:
|
|
54
|
+
self._cache_used -= self._arr_nbytes(old)
|
|
55
|
+
|
|
56
|
+
self._cache[swap_id] = arr
|
|
57
|
+
self._cache_used += n
|
|
58
|
+
|
|
59
|
+
# Evict LRU until under budget
|
|
60
|
+
while self._cache_used > self._cache_bytes and self._cache:
|
|
61
|
+
k, v = self._cache.popitem(last=False)
|
|
62
|
+
self._cache_used -= self._arr_nbytes(v)
|
|
63
|
+
|
|
64
|
+
def _cache_get(self, swap_id: str):
|
|
65
|
+
with self._cache_lock:
|
|
66
|
+
arr = self._cache.pop(swap_id, None)
|
|
67
|
+
if arr is None:
|
|
68
|
+
return None
|
|
69
|
+
# move to MRU
|
|
70
|
+
self._cache[swap_id] = arr
|
|
71
|
+
return arr
|
|
72
|
+
|
|
73
|
+
def save_state(self, image: np.ndarray) -> str | None:
|
|
41
74
|
swap_id = uuid.uuid4().hex
|
|
42
75
|
path = self.get_swap_path(swap_id)
|
|
43
|
-
|
|
44
|
-
# We only save the image data to disk. Metadata is kept in RAM by the caller.
|
|
45
|
-
# Using pickle for simplicity and robustness with numpy arrays.
|
|
46
|
-
# For pure numpy arrays, np.save might be slightly faster, but pickle is more flexible if we change what we store.
|
|
47
|
-
# Let's stick to pickle for now as per plan.
|
|
48
76
|
try:
|
|
49
|
-
|
|
50
|
-
|
|
77
|
+
# Write fast .npy
|
|
78
|
+
np.save(path, image, allow_pickle=False)
|
|
79
|
+
# Optionally keep it hot in RAM too (depends how you use it)
|
|
80
|
+
self._cache_put(swap_id, image)
|
|
81
|
+
return swap_id
|
|
51
82
|
except Exception as e:
|
|
52
83
|
print(f"[SwapManager] Failed to save state {swap_id}: {e}")
|
|
53
84
|
return None
|
|
54
|
-
|
|
55
|
-
return swap_id
|
|
56
85
|
|
|
57
86
|
def load_state(self, swap_id: str) -> np.ndarray | None:
|
|
58
|
-
""
|
|
59
|
-
|
|
60
|
-
|
|
87
|
+
#print("[SwapManager] LOAD", swap_id)
|
|
88
|
+
# First: try RAM
|
|
89
|
+
hot = self._cache_get(swap_id)
|
|
90
|
+
if hot is not None:
|
|
91
|
+
return hot
|
|
92
|
+
|
|
61
93
|
path = self.get_swap_path(swap_id)
|
|
62
94
|
if not os.path.exists(path):
|
|
63
95
|
print(f"[SwapManager] Swap file not found: {path}")
|
|
64
96
|
return None
|
|
65
|
-
|
|
97
|
+
|
|
66
98
|
try:
|
|
67
|
-
|
|
68
|
-
|
|
99
|
+
# mmap_mode="r" is extremely fast; convert to real ndarray only if needed
|
|
100
|
+
arr = np.load(path, mmap_mode="r", allow_pickle=False)
|
|
101
|
+
# If your pipeline needs a writable array, materialize:
|
|
102
|
+
# arr = np.array(arr, copy=True)
|
|
103
|
+
# Cache the loaded array (mmap object still OK to cache; you can decide)
|
|
104
|
+
self._cache_put(swap_id, np.array(arr, copy=False))
|
|
105
|
+
return np.array(arr, copy=False)
|
|
69
106
|
except Exception as e:
|
|
70
107
|
print(f"[SwapManager] Failed to load state {swap_id}: {e}")
|
|
71
108
|
return None
|
|
72
109
|
|
|
73
110
|
def delete_state(self, swap_id: str):
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
111
|
+
with self._cache_lock:
|
|
112
|
+
old = self._cache.pop(swap_id, None)
|
|
113
|
+
if old is not None:
|
|
114
|
+
self._cache_used -= self._arr_nbytes(old)
|
|
115
|
+
|
|
77
116
|
path = self.get_swap_path(swap_id)
|
|
78
117
|
try:
|
|
79
118
|
if os.path.exists(path):
|
|
@@ -82,13 +121,9 @@ class SwapManager:
|
|
|
82
121
|
print(f"[SwapManager] Failed to delete state {swap_id}: {e}")
|
|
83
122
|
|
|
84
123
|
def cleanup_all(self):
|
|
85
|
-
"""
|
|
86
|
-
Delete the entire temporary directory for this session.
|
|
87
|
-
"""
|
|
88
124
|
try:
|
|
89
125
|
if os.path.exists(self.temp_dir):
|
|
90
126
|
shutil.rmtree(self.temp_dir, ignore_errors=True)
|
|
91
|
-
# print(f"[SwapManager] Cleaned up {self.temp_dir}")
|
|
92
127
|
except Exception as e:
|
|
93
128
|
print(f"[SwapManager] Cleanup failed: {e}")
|
|
94
129
|
|