setiastrosuitepro 1.6.7__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of setiastrosuitepro might be problematic. Click here for more details.
- setiastro/__init__.py +2 -0
- setiastro/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/acv_icon.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/first_quarter.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/full_moon.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/last_quarter.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/new_moon.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/waning_crescent_1.png +0 -0
- setiastro/images/waning_crescent_2.png +0 -0
- setiastro/images/waning_crescent_3.png +0 -0
- setiastro/images/waning_crescent_4.png +0 -0
- setiastro/images/waning_crescent_5.png +0 -0
- setiastro/images/waning_gibbous_1.png +0 -0
- setiastro/images/waning_gibbous_2.png +0 -0
- setiastro/images/waning_gibbous_3.png +0 -0
- setiastro/images/waning_gibbous_4.png +0 -0
- setiastro/images/waning_gibbous_5.png +0 -0
- setiastro/images/waxing_crescent_1.png +0 -0
- setiastro/images/waxing_crescent_2.png +0 -0
- setiastro/images/waxing_crescent_3.png +0 -0
- setiastro/images/waxing_crescent_4.png +0 -0
- setiastro/images/waxing_crescent_5.png +0 -0
- setiastro/images/waxing_gibbous_1.png +0 -0
- setiastro/images/waxing_gibbous_2.png +0 -0
- setiastro/images/waxing_gibbous_3.png +0 -0
- setiastro/images/waxing_gibbous_4.png +0 -0
- setiastro/images/waxing_gibbous_5.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 +128 -0
- setiastro/saspro/__init__.py +20 -0
- setiastro/saspro/__main__.py +964 -0
- setiastro/saspro/_generated/__init__.py +7 -0
- setiastro/saspro/_generated/build_info.py +3 -0
- setiastro/saspro/abe.py +1379 -0
- setiastro/saspro/abe_preset.py +196 -0
- setiastro/saspro/aberration_ai.py +910 -0
- setiastro/saspro/aberration_ai_preset.py +224 -0
- setiastro/saspro/accel_installer.py +218 -0
- setiastro/saspro/accel_workers.py +30 -0
- setiastro/saspro/acv_exporter.py +379 -0
- setiastro/saspro/add_stars.py +627 -0
- setiastro/saspro/astrobin_exporter.py +1010 -0
- setiastro/saspro/astrospike.py +153 -0
- setiastro/saspro/astrospike_python.py +1841 -0
- setiastro/saspro/autostretch.py +198 -0
- setiastro/saspro/backgroundneutral.py +639 -0
- setiastro/saspro/batch_convert.py +328 -0
- setiastro/saspro/batch_renamer.py +522 -0
- setiastro/saspro/blemish_blaster.py +494 -0
- setiastro/saspro/blink_comparator_pro.py +3149 -0
- setiastro/saspro/bundles.py +61 -0
- setiastro/saspro/bundles_dock.py +114 -0
- setiastro/saspro/cheat_sheet.py +213 -0
- setiastro/saspro/clahe.py +371 -0
- setiastro/saspro/comet_stacking.py +1442 -0
- setiastro/saspro/common_tr.py +107 -0
- setiastro/saspro/config.py +38 -0
- setiastro/saspro/config_bootstrap.py +40 -0
- setiastro/saspro/config_manager.py +316 -0
- setiastro/saspro/continuum_subtract.py +1620 -0
- setiastro/saspro/convo.py +1403 -0
- setiastro/saspro/convo_preset.py +414 -0
- setiastro/saspro/copyastro.py +190 -0
- setiastro/saspro/cosmicclarity.py +1593 -0
- setiastro/saspro/cosmicclarity_preset.py +407 -0
- setiastro/saspro/crop_dialog_pro.py +1005 -0
- setiastro/saspro/crop_preset.py +189 -0
- setiastro/saspro/curve_editor_pro.py +2608 -0
- setiastro/saspro/curves_preset.py +375 -0
- setiastro/saspro/debayer.py +673 -0
- setiastro/saspro/debug_utils.py +29 -0
- setiastro/saspro/dnd_mime.py +35 -0
- setiastro/saspro/doc_manager.py +2727 -0
- setiastro/saspro/exoplanet_detector.py +2258 -0
- setiastro/saspro/file_utils.py +284 -0
- setiastro/saspro/fitsmodifier.py +748 -0
- setiastro/saspro/fix_bom.py +32 -0
- setiastro/saspro/free_torch_memory.py +48 -0
- setiastro/saspro/frequency_separation.py +1352 -0
- setiastro/saspro/function_bundle.py +1596 -0
- setiastro/saspro/generate_translations.py +3092 -0
- setiastro/saspro/ghs_dialog_pro.py +728 -0
- setiastro/saspro/ghs_preset.py +284 -0
- setiastro/saspro/graxpert.py +638 -0
- setiastro/saspro/graxpert_preset.py +287 -0
- setiastro/saspro/gui/__init__.py +0 -0
- setiastro/saspro/gui/main_window.py +8928 -0
- setiastro/saspro/gui/mixins/__init__.py +33 -0
- setiastro/saspro/gui/mixins/dock_mixin.py +375 -0
- setiastro/saspro/gui/mixins/file_mixin.py +450 -0
- setiastro/saspro/gui/mixins/geometry_mixin.py +503 -0
- setiastro/saspro/gui/mixins/header_mixin.py +441 -0
- setiastro/saspro/gui/mixins/mask_mixin.py +421 -0
- setiastro/saspro/gui/mixins/menu_mixin.py +391 -0
- setiastro/saspro/gui/mixins/theme_mixin.py +367 -0
- setiastro/saspro/gui/mixins/toolbar_mixin.py +1824 -0
- setiastro/saspro/gui/mixins/update_mixin.py +323 -0
- setiastro/saspro/gui/mixins/view_mixin.py +477 -0
- setiastro/saspro/gui/statistics_dialog.py +47 -0
- setiastro/saspro/halobgon.py +492 -0
- setiastro/saspro/header_viewer.py +448 -0
- setiastro/saspro/headless_utils.py +88 -0
- setiastro/saspro/histogram.py +760 -0
- setiastro/saspro/history_explorer.py +941 -0
- setiastro/saspro/i18n.py +168 -0
- setiastro/saspro/image_combine.py +421 -0
- setiastro/saspro/image_peeker_pro.py +1608 -0
- setiastro/saspro/imageops/__init__.py +37 -0
- setiastro/saspro/imageops/mdi_snap.py +292 -0
- setiastro/saspro/imageops/scnr.py +36 -0
- setiastro/saspro/imageops/starbasedwhitebalance.py +210 -0
- setiastro/saspro/imageops/stretch.py +236 -0
- setiastro/saspro/isophote.py +1186 -0
- setiastro/saspro/layers.py +208 -0
- setiastro/saspro/layers_dock.py +714 -0
- setiastro/saspro/lazy_imports.py +193 -0
- setiastro/saspro/legacy/__init__.py +2 -0
- setiastro/saspro/legacy/image_manager.py +2360 -0
- setiastro/saspro/legacy/numba_utils.py +3676 -0
- setiastro/saspro/legacy/xisf.py +1213 -0
- setiastro/saspro/linear_fit.py +537 -0
- setiastro/saspro/live_stacking.py +1854 -0
- setiastro/saspro/log_bus.py +5 -0
- setiastro/saspro/logging_config.py +460 -0
- setiastro/saspro/luminancerecombine.py +510 -0
- setiastro/saspro/main_helpers.py +201 -0
- setiastro/saspro/mask_creation.py +1090 -0
- setiastro/saspro/masks_core.py +56 -0
- setiastro/saspro/mdi_widgets.py +353 -0
- setiastro/saspro/memory_utils.py +666 -0
- setiastro/saspro/metadata_patcher.py +75 -0
- setiastro/saspro/mfdeconv.py +3909 -0
- setiastro/saspro/mfdeconv_earlystop.py +71 -0
- setiastro/saspro/mfdeconvcudnn.py +3312 -0
- setiastro/saspro/mfdeconvsport.py +2459 -0
- setiastro/saspro/minorbodycatalog.py +567 -0
- setiastro/saspro/morphology.py +411 -0
- setiastro/saspro/multiscale_decomp.py +1751 -0
- setiastro/saspro/nbtorgb_stars.py +541 -0
- setiastro/saspro/numba_utils.py +3145 -0
- setiastro/saspro/numba_warmup.py +141 -0
- setiastro/saspro/ops/__init__.py +9 -0
- setiastro/saspro/ops/command_help_dialog.py +623 -0
- setiastro/saspro/ops/command_runner.py +217 -0
- setiastro/saspro/ops/commands.py +1594 -0
- setiastro/saspro/ops/script_editor.py +1105 -0
- setiastro/saspro/ops/scripts.py +1476 -0
- setiastro/saspro/ops/settings.py +637 -0
- setiastro/saspro/parallel_utils.py +554 -0
- setiastro/saspro/pedestal.py +121 -0
- setiastro/saspro/perfect_palette_picker.py +1105 -0
- setiastro/saspro/pipeline.py +110 -0
- setiastro/saspro/pixelmath.py +1604 -0
- setiastro/saspro/plate_solver.py +2480 -0
- setiastro/saspro/project_io.py +797 -0
- setiastro/saspro/psf_utils.py +136 -0
- setiastro/saspro/psf_viewer.py +631 -0
- setiastro/saspro/pyi_rthook_astroquery.py +95 -0
- setiastro/saspro/remove_green.py +331 -0
- setiastro/saspro/remove_stars.py +1599 -0
- setiastro/saspro/remove_stars_preset.py +446 -0
- setiastro/saspro/resources.py +570 -0
- setiastro/saspro/rgb_combination.py +208 -0
- setiastro/saspro/rgb_extract.py +19 -0
- setiastro/saspro/rgbalign.py +727 -0
- setiastro/saspro/runtime_imports.py +7 -0
- setiastro/saspro/runtime_torch.py +754 -0
- setiastro/saspro/save_options.py +73 -0
- setiastro/saspro/selective_color.py +1614 -0
- setiastro/saspro/sfcc.py +1530 -0
- setiastro/saspro/shortcuts.py +3125 -0
- setiastro/saspro/signature_insert.py +1106 -0
- setiastro/saspro/stacking_suite.py +19069 -0
- setiastro/saspro/star_alignment.py +7383 -0
- setiastro/saspro/star_alignment_preset.py +329 -0
- setiastro/saspro/star_metrics.py +49 -0
- setiastro/saspro/star_spikes.py +769 -0
- setiastro/saspro/star_stretch.py +542 -0
- setiastro/saspro/stat_stretch.py +554 -0
- setiastro/saspro/status_log_dock.py +78 -0
- setiastro/saspro/subwindow.py +3523 -0
- setiastro/saspro/supernovaasteroidhunter.py +1719 -0
- setiastro/saspro/swap_manager.py +134 -0
- setiastro/saspro/torch_backend.py +89 -0
- setiastro/saspro/torch_rejection.py +434 -0
- 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 +1558 -0
- setiastro/saspro/wavescale_hdr.py +648 -0
- setiastro/saspro/wavescale_hdr_preset.py +101 -0
- setiastro/saspro/wavescalede.py +683 -0
- setiastro/saspro/wavescalede_preset.py +230 -0
- setiastro/saspro/wcs_update.py +374 -0
- setiastro/saspro/whitebalance.py +540 -0
- setiastro/saspro/widgets/__init__.py +48 -0
- setiastro/saspro/widgets/common_utilities.py +306 -0
- setiastro/saspro/widgets/graphics_views.py +122 -0
- setiastro/saspro/widgets/image_utils.py +518 -0
- 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 +280 -0
- setiastro/saspro/widgets/resource_monitor.py +313 -0
- setiastro/saspro/widgets/spinboxes.py +290 -0
- setiastro/saspro/widgets/themed_buttons.py +13 -0
- setiastro/saspro/widgets/wavelet_utils.py +331 -0
- setiastro/saspro/wimi.py +7367 -0
- setiastro/saspro/wims.py +588 -0
- setiastro/saspro/window_shelf.py +185 -0
- setiastro/saspro/xisf.py +1213 -0
- setiastrosuitepro-1.6.7.dist-info/METADATA +279 -0
- setiastrosuitepro-1.6.7.dist-info/RECORD +394 -0
- setiastrosuitepro-1.6.7.dist-info/WHEEL +4 -0
- setiastrosuitepro-1.6.7.dist-info/entry_points.txt +6 -0
- setiastrosuitepro-1.6.7.dist-info/licenses/LICENSE +674 -0
- setiastrosuitepro-1.6.7.dist-info/licenses/license.txt +2580 -0
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
# pro/aberration_ai_preset.py
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
import os
|
|
4
|
+
import time
|
|
5
|
+
import numpy as np
|
|
6
|
+
from PyQt6.QtCore import QTimer
|
|
7
|
+
from PyQt6.QtWidgets import QDialog, QVBoxLayout, QProgressBar, QPushButton, QMessageBox, QFormLayout, QDialogButtonBox, QSpinBox, QCheckBox, QComboBox, QLabel
|
|
8
|
+
|
|
9
|
+
from PyQt6.QtCore import QSettings
|
|
10
|
+
# reuse everything from the UI module
|
|
11
|
+
from .aberration_ai import (
|
|
12
|
+
ort, IS_APPLE_ARM,
|
|
13
|
+
_ONNXWorker, pick_providers, _preserve_border
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
# ---------------------- Headless entry ----------------------
|
|
17
|
+
|
|
18
|
+
def run_aberration_ai_via_preset(main, preset: dict | None = None, doc=None):
|
|
19
|
+
"""
|
|
20
|
+
Headless Aberration AI
|
|
21
|
+
|
|
22
|
+
preset keys (all optional except model):
|
|
23
|
+
- model: str (path to .onnx). If omitted, uses QSettings "AberrationAI/model_path".
|
|
24
|
+
- patch: int (default 512)
|
|
25
|
+
- overlap: int (default 64)
|
|
26
|
+
- border_px: int (default 10)
|
|
27
|
+
- auto_gpu: bool (default True; forced False on Apple Silicon)
|
|
28
|
+
- provider: str (used when auto_gpu=False), e.g. "CPUExecutionProvider",
|
|
29
|
+
"CUDAExecutionProvider", "DmlExecutionProvider"
|
|
30
|
+
"""
|
|
31
|
+
if ort is None:
|
|
32
|
+
QMessageBox.critical(main, "Aberration AI", "onnxruntime not installed.")
|
|
33
|
+
return
|
|
34
|
+
|
|
35
|
+
# active doc
|
|
36
|
+
if doc is None:
|
|
37
|
+
d = getattr(main, "_active_doc", None)
|
|
38
|
+
doc = d() if callable(d) else d
|
|
39
|
+
|
|
40
|
+
if doc is None or getattr(doc, "image", None) is None:
|
|
41
|
+
QMessageBox.warning(main, "Aberration AI", "Load an image first.")
|
|
42
|
+
return
|
|
43
|
+
|
|
44
|
+
p = dict(preset or {})
|
|
45
|
+
|
|
46
|
+
# model path (preset beats QSettings)
|
|
47
|
+
model = p.get("model") or QSettings().value("AberrationAI/model_path", type=str)
|
|
48
|
+
if not model or not os.path.isfile(model):
|
|
49
|
+
QMessageBox.warning(main, "Aberration AI", "Model not set. Open the Aberration AI tool once and choose a model, or put 'model' into the preset.")
|
|
50
|
+
return
|
|
51
|
+
|
|
52
|
+
patch = int(p.get("patch", 512))
|
|
53
|
+
overlap = int(p.get("overlap", 64))
|
|
54
|
+
border_px= int(p.get("border_px", 10))
|
|
55
|
+
|
|
56
|
+
# providers
|
|
57
|
+
if IS_APPLE_ARM:
|
|
58
|
+
providers = ["CPUExecutionProvider"]
|
|
59
|
+
auto_gpu = False
|
|
60
|
+
provider_label = "CPUExecutionProvider"
|
|
61
|
+
else:
|
|
62
|
+
auto_gpu = bool(p.get("auto_gpu", True))
|
|
63
|
+
if auto_gpu:
|
|
64
|
+
providers = pick_providers(auto_gpu=True)
|
|
65
|
+
provider_label = "auto"
|
|
66
|
+
else:
|
|
67
|
+
sel = str(p.get("provider", "CPUExecutionProvider"))
|
|
68
|
+
providers = [sel]
|
|
69
|
+
provider_label = sel or "CPUExecutionProvider"
|
|
70
|
+
|
|
71
|
+
# Safety for CoreML if someone forces it
|
|
72
|
+
if "CoreMLExecutionProvider" in providers and patch > 128:
|
|
73
|
+
patch = 128
|
|
74
|
+
|
|
75
|
+
# Guard so interactive dialog won't pop during/after apply
|
|
76
|
+
setattr(main, "_aberration_ai_headless_running", True)
|
|
77
|
+
setattr(main, "_aberration_ai_guard", True)
|
|
78
|
+
|
|
79
|
+
# ---- minimal progress dialog ----
|
|
80
|
+
dlg = QDialog(main)
|
|
81
|
+
dlg.setWindowTitle("Aberration AI (Headless)")
|
|
82
|
+
lay = QVBoxLayout(dlg)
|
|
83
|
+
bar = QProgressBar(); bar.setRange(0, 100); lay.addWidget(bar)
|
|
84
|
+
btn = QPushButton("Cancel"); lay.addWidget(btn)
|
|
85
|
+
|
|
86
|
+
img = np.asarray(doc.image)
|
|
87
|
+
orig_for_border = img.copy()
|
|
88
|
+
|
|
89
|
+
t0 = time.perf_counter()
|
|
90
|
+
|
|
91
|
+
worker = _ONNXWorker(model, img, patch, overlap, providers)
|
|
92
|
+
worker.progressed.connect(bar.setValue)
|
|
93
|
+
|
|
94
|
+
def _fail(msg: str):
|
|
95
|
+
try:
|
|
96
|
+
if hasattr(main, "_log"):
|
|
97
|
+
main._log(f"❌ Aberration AI failed: {msg}")
|
|
98
|
+
except Exception:
|
|
99
|
+
pass
|
|
100
|
+
QMessageBox.critical(main, "Aberration AI", msg)
|
|
101
|
+
dlg.close()
|
|
102
|
+
|
|
103
|
+
def _ok(out: np.ndarray):
|
|
104
|
+
# preserve border and commit
|
|
105
|
+
try:
|
|
106
|
+
out2 = _preserve_border(out, orig_for_border, border_px)
|
|
107
|
+
except Exception:
|
|
108
|
+
out2 = out
|
|
109
|
+
|
|
110
|
+
meta = {
|
|
111
|
+
"is_mono": (out2.ndim == 2),
|
|
112
|
+
"processing_parameters": {
|
|
113
|
+
"AberrationAI": {
|
|
114
|
+
"model_path": model,
|
|
115
|
+
"patch_size": int(patch),
|
|
116
|
+
"overlap": int(overlap),
|
|
117
|
+
"provider": provider_label,
|
|
118
|
+
"border_px": int(border_px),
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
try:
|
|
123
|
+
doc.apply_edit(out2, meta, step_name="Aberration AI")
|
|
124
|
+
used = getattr(worker, "used_provider", provider_label)
|
|
125
|
+
dt = time.perf_counter() - t0
|
|
126
|
+
if hasattr(main, "_log"):
|
|
127
|
+
main._log(
|
|
128
|
+
f"✅ Aberration AI (headless) model={os.path.basename(model)}, "
|
|
129
|
+
f"provider={used}, patch={patch}, overlap={overlap}, "
|
|
130
|
+
f"border={border_px}px, time={dt:.2f}s"
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
# ---- Register as last_headless_command for Replay ----
|
|
134
|
+
try:
|
|
135
|
+
auto_flag = bool(auto_gpu)
|
|
136
|
+
replay_preset = {
|
|
137
|
+
"model": model,
|
|
138
|
+
"patch": int(patch),
|
|
139
|
+
"overlap": int(overlap),
|
|
140
|
+
"border_px": int(border_px),
|
|
141
|
+
"auto_gpu": auto_flag,
|
|
142
|
+
}
|
|
143
|
+
if not auto_flag:
|
|
144
|
+
replay_preset["provider"] = provider_label
|
|
145
|
+
|
|
146
|
+
payload = {
|
|
147
|
+
"command_id": "aberrationai",
|
|
148
|
+
"preset": replay_preset,
|
|
149
|
+
}
|
|
150
|
+
setattr(main, "_last_headless_command", payload)
|
|
151
|
+
except Exception:
|
|
152
|
+
pass
|
|
153
|
+
# -------------------------------------------------------
|
|
154
|
+
except Exception as e:
|
|
155
|
+
QMessageBox.critical(main, "Aberration AI", f"Failed to apply result:\n{e}")
|
|
156
|
+
finally:
|
|
157
|
+
dlg.close()
|
|
158
|
+
|
|
159
|
+
worker.failed.connect(_fail)
|
|
160
|
+
worker.finished_ok.connect(_ok)
|
|
161
|
+
worker.finished.connect(lambda: btn.setEnabled(False))
|
|
162
|
+
btn.clicked.connect(worker.terminate)
|
|
163
|
+
|
|
164
|
+
worker.start()
|
|
165
|
+
dlg.exec()
|
|
166
|
+
|
|
167
|
+
# clear the guard after a brief tick so downstream signals don’t re-open UI
|
|
168
|
+
def _clear():
|
|
169
|
+
for k in ("_aberration_ai_headless_running", "_aberration_ai_guard"):
|
|
170
|
+
try: delattr(main, k)
|
|
171
|
+
except Exception: setattr(main, k, False)
|
|
172
|
+
QTimer.singleShot(1000, _clear)
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
# ---------------------- Preset editor (for shortcut) ----------------------
|
|
176
|
+
|
|
177
|
+
class AberrationAIPresetDialog(QDialog):
|
|
178
|
+
def __init__(self, parent=None, initial: dict | None = None):
|
|
179
|
+
super().__init__(parent)
|
|
180
|
+
self.setWindowTitle("Aberration AI — Preset")
|
|
181
|
+
p = dict(initial or {})
|
|
182
|
+
|
|
183
|
+
self.spin_patch = QSpinBox(); self.spin_patch.setRange(128, 2048); self.spin_patch.setValue(int(p.get("patch", 512)))
|
|
184
|
+
self.spin_overlap = QSpinBox(); self.spin_overlap.setRange(16, 512); self.spin_overlap.setValue(int(p.get("overlap", 64)))
|
|
185
|
+
self.spin_border = QSpinBox(); self.spin_border.setRange(0, 64); self.spin_border.setValue(int(p.get("border_px", 10)))
|
|
186
|
+
|
|
187
|
+
self.chk_auto = QCheckBox("Auto GPU (prefer DML/CUDA)"); self.chk_auto.setChecked(bool(p.get("auto_gpu", True)))
|
|
188
|
+
self.cmb_provider = QComboBox(); self.cmb_provider.addItems([
|
|
189
|
+
"CPUExecutionProvider", "DmlExecutionProvider", "CUDAExecutionProvider", "CoreMLExecutionProvider"
|
|
190
|
+
])
|
|
191
|
+
self.cmb_provider.setCurrentText(str(p.get("provider", "CPUExecutionProvider")))
|
|
192
|
+
|
|
193
|
+
# info: model is taken from QSettings unless preset provides an absolute path from code
|
|
194
|
+
info = QLabel("Model path is taken from the Aberration AI tool (QSettings) unless you pass 'model' in the preset programmatically.")
|
|
195
|
+
info.setWordWrap(True); info.setStyleSheet("color:#888; font-size:11px;")
|
|
196
|
+
|
|
197
|
+
form = QFormLayout(self)
|
|
198
|
+
form.addRow("Patch:", self.spin_patch)
|
|
199
|
+
form.addRow("Overlap:", self.spin_overlap)
|
|
200
|
+
form.addRow("Preserve border (px):", self.spin_border)
|
|
201
|
+
form.addRow(self.chk_auto)
|
|
202
|
+
form.addRow("Provider (if Auto off):", self.cmb_provider)
|
|
203
|
+
form.addRow(info)
|
|
204
|
+
|
|
205
|
+
btns = QDialogButtonBox(QDialogButtonBox.StandardButton.Ok | QDialogButtonBox.StandardButton.Cancel, parent=self)
|
|
206
|
+
btns.accepted.connect(self.accept); btns.rejected.connect(self.reject)
|
|
207
|
+
form.addRow(btns)
|
|
208
|
+
|
|
209
|
+
# toggle enable
|
|
210
|
+
def _toggle():
|
|
211
|
+
en = not self.chk_auto.isChecked()
|
|
212
|
+
self.cmb_provider.setEnabled(en)
|
|
213
|
+
self.chk_auto.stateChanged.connect(lambda _: _toggle()); _toggle()
|
|
214
|
+
|
|
215
|
+
def result_dict(self) -> dict:
|
|
216
|
+
d = {
|
|
217
|
+
"patch": int(self.spin_patch.value()),
|
|
218
|
+
"overlap": int(self.spin_overlap.value()),
|
|
219
|
+
"border_px": int(self.spin_border.value()),
|
|
220
|
+
"auto_gpu": bool(self.chk_auto.isChecked()),
|
|
221
|
+
}
|
|
222
|
+
if not d["auto_gpu"]:
|
|
223
|
+
d["provider"] = self.cmb_provider.currentText()
|
|
224
|
+
return d
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
# pro/accel_installer.py
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
import platform
|
|
4
|
+
import subprocess
|
|
5
|
+
import sys
|
|
6
|
+
import os
|
|
7
|
+
from typing import Callable, Optional
|
|
8
|
+
from PyQt6.QtWidgets import QMessageBox
|
|
9
|
+
from setiastro.saspro.runtime_torch import import_torch, add_runtime_to_sys_path, _user_runtime_dir, _venv_paths
|
|
10
|
+
|
|
11
|
+
LogCB = Callable[[str], None]
|
|
12
|
+
|
|
13
|
+
def _run(cmd):
|
|
14
|
+
return subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def _has_intel_arc() -> bool:
|
|
18
|
+
"""
|
|
19
|
+
Return True if the machine appears to have an Intel Arc / Xe (XPU-capable) adapter.
|
|
20
|
+
Windows: CIM/WMIC name sniff.
|
|
21
|
+
Linux: lspci grep.
|
|
22
|
+
macOS: False.
|
|
23
|
+
"""
|
|
24
|
+
try:
|
|
25
|
+
sysname = platform.system()
|
|
26
|
+
if sysname == "Windows":
|
|
27
|
+
ps = _run(["powershell","-NoProfile","-Command",
|
|
28
|
+
"(Get-CimInstance Win32_VideoController | Select-Object -ExpandProperty Name) -join ';'"])
|
|
29
|
+
out = (ps.stdout or "").lower()
|
|
30
|
+
# Accept 'arc' or 'iris xe' (dg/xe discrete & some laptops with XPU)
|
|
31
|
+
return ("intel" in out) and ("arc" in out or "iris xe" in out or "a770" in out or "a750" in out or "a580" in out or "a380" in out)
|
|
32
|
+
if sysname == "Linux":
|
|
33
|
+
r = _run(["bash","-lc","lspci -nn | grep -i 'vga\\|3d'"])
|
|
34
|
+
s = (r.stdout or "").lower()
|
|
35
|
+
return ("intel" in s) and ("arc" in s or "iris xe" in s or "xe" in s)
|
|
36
|
+
return False
|
|
37
|
+
except Exception:
|
|
38
|
+
return False
|
|
39
|
+
|
|
40
|
+
def _has_nvidia() -> bool:
|
|
41
|
+
"""
|
|
42
|
+
Return True if the machine *appears* to have an NVIDIA adapter.
|
|
43
|
+
Windows: try PowerShell CIM first (wmic is deprecated), then wmic.
|
|
44
|
+
Linux: use nvidia-smi.
|
|
45
|
+
macOS: always False.
|
|
46
|
+
"""
|
|
47
|
+
try:
|
|
48
|
+
sysname = platform.system()
|
|
49
|
+
if sysname == "Windows":
|
|
50
|
+
# Try CIM (preferred)
|
|
51
|
+
ps = _run(["powershell","-NoProfile","-Command",
|
|
52
|
+
"(Get-CimInstance Win32_VideoController | Select-Object -ExpandProperty Name) -join ';'"])
|
|
53
|
+
out = (ps.stdout or "").lower()
|
|
54
|
+
if "nvidia" in out:
|
|
55
|
+
return True
|
|
56
|
+
# Fallback to wmic (older systems)
|
|
57
|
+
w = _run(["wmic","path","win32_VideoController","get","name"])
|
|
58
|
+
return "nvidia" in (w.stdout or "").lower()
|
|
59
|
+
if sysname == "Linux":
|
|
60
|
+
r = _run(["nvidia-smi","-L"])
|
|
61
|
+
return "GPU" in (r.stdout or "")
|
|
62
|
+
return False
|
|
63
|
+
except Exception:
|
|
64
|
+
return False
|
|
65
|
+
|
|
66
|
+
def _nvidia_driver_ok(log_cb: LogCB) -> bool:
|
|
67
|
+
try:
|
|
68
|
+
r = _run(["nvidia-smi", "--query-gpu=driver_version", "--format=csv,noheader"])
|
|
69
|
+
drv = (r.stdout or "").strip()
|
|
70
|
+
if not drv:
|
|
71
|
+
log_cb("nvidia-smi not found or driver not detected.")
|
|
72
|
+
return False
|
|
73
|
+
log_cb(f"NVIDIA driver detected: {drv}")
|
|
74
|
+
return True
|
|
75
|
+
except Exception:
|
|
76
|
+
log_cb("Unable to query NVIDIA driver via nvidia-smi.")
|
|
77
|
+
return False
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def ensure_torch_installed(prefer_gpu: bool, log_cb: LogCB) -> tuple[bool, Optional[str]]:
|
|
81
|
+
try:
|
|
82
|
+
is_windows = platform.system() == "Windows"
|
|
83
|
+
has_nv = _has_nvidia() and platform.system() in ("Windows", "Linux")
|
|
84
|
+
has_intel = (not has_nv) and _has_intel_arc() and platform.system() in ("Windows", "Linux")
|
|
85
|
+
|
|
86
|
+
prefer_cuda = prefer_gpu and has_nv
|
|
87
|
+
prefer_xpu = prefer_gpu and (not has_nv) and has_intel
|
|
88
|
+
|
|
89
|
+
if prefer_cuda and not _nvidia_driver_ok(log_cb):
|
|
90
|
+
log_cb("CUDA requested but NVIDIA driver not detected/working; CUDA wheels may not initialize.")
|
|
91
|
+
log_cb(f"PyTorch install preference: prefer_cuda={prefer_cuda}, prefer_xpu={prefer_xpu} (OS={platform.system()})")
|
|
92
|
+
|
|
93
|
+
# Install torch (tries CUDA → XPU → CPU)
|
|
94
|
+
torch = import_torch(prefer_cuda=prefer_cuda, prefer_xpu=prefer_xpu, status_cb=log_cb)
|
|
95
|
+
|
|
96
|
+
cuda_ok = bool(getattr(torch, "cuda", None) and torch.cuda.is_available())
|
|
97
|
+
xpu_ok = bool(hasattr(torch, "xpu") and torch.xpu.is_available())
|
|
98
|
+
|
|
99
|
+
# HARD RULES about DirectML:
|
|
100
|
+
# • If NVIDIA exists: never use DML.
|
|
101
|
+
# • If XPU is active: also avoid DML to prevent confusion.
|
|
102
|
+
if has_nv:
|
|
103
|
+
_maybe_uninstall_dml = True
|
|
104
|
+
else:
|
|
105
|
+
_maybe_uninstall_dml = xpu_ok
|
|
106
|
+
|
|
107
|
+
if _maybe_uninstall_dml:
|
|
108
|
+
try:
|
|
109
|
+
from setiastro.saspro.runtime_torch import _user_runtime_dir, _venv_paths
|
|
110
|
+
rt = _user_runtime_dir(); vpy = _venv_paths(rt)["python"]
|
|
111
|
+
r = subprocess.run([str(vpy), "-m", "pip", "show", "torch-directml"],
|
|
112
|
+
stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True)
|
|
113
|
+
if r.returncode == 0 and r.stdout:
|
|
114
|
+
log_cb("Non-DML path selected → uninstalling torch-directml.")
|
|
115
|
+
subprocess.run([str(vpy), "-m", "pip", "uninstall", "-y", "torch-directml"],
|
|
116
|
+
stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True)
|
|
117
|
+
except Exception:
|
|
118
|
+
pass
|
|
119
|
+
|
|
120
|
+
if cuda_ok:
|
|
121
|
+
log_cb("CUDA available; using NVIDIA backend.")
|
|
122
|
+
return True, None
|
|
123
|
+
|
|
124
|
+
if xpu_ok:
|
|
125
|
+
# optional: surface device name if available
|
|
126
|
+
try:
|
|
127
|
+
name = None
|
|
128
|
+
if hasattr(torch.xpu, "get_device_name"):
|
|
129
|
+
name = torch.xpu.get_device_name(0)
|
|
130
|
+
log_cb(f"Intel XPU available{f' ({name})' if name else ''}.")
|
|
131
|
+
except Exception:
|
|
132
|
+
log_cb("Intel XPU available.")
|
|
133
|
+
return True, None
|
|
134
|
+
|
|
135
|
+
# No CUDA/XPU ⇒ evaluate DML on Windows non-NVIDIA as before
|
|
136
|
+
dml_enabled = False
|
|
137
|
+
if is_windows and (not has_nv):
|
|
138
|
+
try:
|
|
139
|
+
import importlib; importlib.invalidate_caches()
|
|
140
|
+
import torch_directml # noqa
|
|
141
|
+
dml_enabled = True
|
|
142
|
+
log_cb("DirectML detected (already installed).")
|
|
143
|
+
except Exception:
|
|
144
|
+
from setiastro.saspro.runtime_torch import _user_runtime_dir, _venv_paths
|
|
145
|
+
rt = _user_runtime_dir(); vpy = _venv_paths(rt)["python"]
|
|
146
|
+
log_cb("Installing torch-directml (Windows fallback)…")
|
|
147
|
+
r = subprocess.run([str(vpy), "-m", "pip", "install", "--prefer-binary", "torch-directml"],
|
|
148
|
+
stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True)
|
|
149
|
+
if r.returncode == 0:
|
|
150
|
+
try:
|
|
151
|
+
import importlib; importlib.invalidate_caches()
|
|
152
|
+
import torch_directml # noqa
|
|
153
|
+
dml_enabled = True
|
|
154
|
+
log_cb("DirectML backend available.")
|
|
155
|
+
except Exception:
|
|
156
|
+
dml_enabled = False
|
|
157
|
+
log_cb("DirectML import failed after install; staying on CPU.")
|
|
158
|
+
else:
|
|
159
|
+
log_cb("DirectML install failed; staying on CPU.")
|
|
160
|
+
|
|
161
|
+
return True, None
|
|
162
|
+
except Exception as e:
|
|
163
|
+
msg = str(e)
|
|
164
|
+
if "PyTorch C-extension check failed" in msg or "Failed to load PyTorch C extensions" in msg:
|
|
165
|
+
msg += (
|
|
166
|
+
"\n\nHints:\n"
|
|
167
|
+
" • Make sure you are not launching SAS Pro from a folder that contains a 'torch' directory.\n"
|
|
168
|
+
" • If you previously ran a local PyTorch checkout, remove it from PYTHONPATH.\n"
|
|
169
|
+
f" • To force a clean reinstall, delete: {os.path.join(str(_user_runtime_dir()), 'venv')} and click Install/Update again."
|
|
170
|
+
)
|
|
171
|
+
if "macOS arm64 on Python 3.13" in msg:
|
|
172
|
+
msg += (
|
|
173
|
+
"\n\nmacOS tip:\n"
|
|
174
|
+
" • Install Python 3.12: `brew install python@3.12`\n"
|
|
175
|
+
" • Ensure `/opt/homebrew/bin/python3.12` exists, then relaunch SAS Pro.\n"
|
|
176
|
+
)
|
|
177
|
+
return False, msg
|
|
178
|
+
|
|
179
|
+
def current_backend() -> str:
|
|
180
|
+
try:
|
|
181
|
+
add_runtime_to_sys_path(status_cb=lambda *_: None)
|
|
182
|
+
import importlib
|
|
183
|
+
import platform as _plat
|
|
184
|
+
torch = importlib.import_module("torch")
|
|
185
|
+
|
|
186
|
+
if getattr(torch, "cuda", None) and torch.cuda.is_available():
|
|
187
|
+
try: name = torch.cuda.get_device_name(0)
|
|
188
|
+
except Exception: name = "CUDA"
|
|
189
|
+
return f"CUDA ({name})"
|
|
190
|
+
|
|
191
|
+
# Intel XPU (Arc / Xe)
|
|
192
|
+
if hasattr(torch, "xpu") and torch.xpu.is_available():
|
|
193
|
+
try:
|
|
194
|
+
name = None
|
|
195
|
+
if hasattr(torch.xpu, "get_device_name"):
|
|
196
|
+
name = torch.xpu.get_device_name(0)
|
|
197
|
+
except Exception:
|
|
198
|
+
name = None
|
|
199
|
+
return f"Intel XPU{f' ({name})' if name else ''}"
|
|
200
|
+
|
|
201
|
+
cuda_tag = getattr(getattr(torch, "version", None), "cuda", None)
|
|
202
|
+
has_nv = _has_nvidia() and _plat.system() in ("Windows","Linux")
|
|
203
|
+
if cuda_tag and has_nv:
|
|
204
|
+
return f"CPU (CUDA {cuda_tag} not available — check NVIDIA driver/CUDA runtime)"
|
|
205
|
+
|
|
206
|
+
if hasattr(torch.backends, "mps") and torch.backends.mps.is_available():
|
|
207
|
+
return "Apple MPS"
|
|
208
|
+
|
|
209
|
+
if _plat.system() == "Windows" and not has_nv:
|
|
210
|
+
try:
|
|
211
|
+
import torch_directml # noqa
|
|
212
|
+
return "DirectML"
|
|
213
|
+
except Exception:
|
|
214
|
+
pass
|
|
215
|
+
|
|
216
|
+
return "CPU"
|
|
217
|
+
except Exception:
|
|
218
|
+
return "Not installed"
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# pro/accel_workers.py
|
|
2
|
+
from __future__ import annotations
|
|
3
|
+
from PyQt6.QtCore import QObject, pyqtSignal, QThread
|
|
4
|
+
from setiastro.saspro.accel_installer import ensure_torch_installed
|
|
5
|
+
|
|
6
|
+
class AccelInstallWorker(QObject):
|
|
7
|
+
progress = pyqtSignal(str) # emitted from worker thread; GUI updates must connect with QueuedConnection
|
|
8
|
+
finished = pyqtSignal(bool, str) # (ok, message)
|
|
9
|
+
|
|
10
|
+
def __init__(self, prefer_gpu: bool = True):
|
|
11
|
+
super().__init__()
|
|
12
|
+
self.prefer_gpu = prefer_gpu
|
|
13
|
+
|
|
14
|
+
def _log(self, s: str):
|
|
15
|
+
# Never touch widgets here; just emit text
|
|
16
|
+
self.progress.emit(s)
|
|
17
|
+
|
|
18
|
+
def run(self):
|
|
19
|
+
# pure backend work; no QWidget/QMessageBox etc. in this method
|
|
20
|
+
ok, msg = ensure_torch_installed(self.prefer_gpu, self._log)
|
|
21
|
+
|
|
22
|
+
# honor cancellation if requested
|
|
23
|
+
if QThread.currentThread().isInterruptionRequested():
|
|
24
|
+
self.finished.emit(False, "Canceled.")
|
|
25
|
+
return
|
|
26
|
+
|
|
27
|
+
if ok:
|
|
28
|
+
self.finished.emit(True, "PyTorch installed and ready.")
|
|
29
|
+
else:
|
|
30
|
+
self.finished.emit(False, msg or "Installation failed.")
|