setiastrosuitepro 1.6.5.post3__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.
Files changed (368) hide show
  1. setiastro/__init__.py +2 -0
  2. setiastro/data/SASP_data.fits +0 -0
  3. setiastro/data/catalogs/List_of_Galaxies_with_Distances_Gly.csv +488 -0
  4. setiastro/data/catalogs/astrobin_filters.csv +890 -0
  5. setiastro/data/catalogs/astrobin_filters_page1_local.csv +51 -0
  6. setiastro/data/catalogs/cali2.csv +63 -0
  7. setiastro/data/catalogs/cali2color.csv +65 -0
  8. setiastro/data/catalogs/celestial_catalog - original.csv +16471 -0
  9. setiastro/data/catalogs/celestial_catalog.csv +24031 -0
  10. setiastro/data/catalogs/detected_stars.csv +24784 -0
  11. setiastro/data/catalogs/fits_header_data.csv +46 -0
  12. setiastro/data/catalogs/test.csv +8 -0
  13. setiastro/data/catalogs/updated_celestial_catalog.csv +16471 -0
  14. setiastro/images/Astro_Spikes.png +0 -0
  15. setiastro/images/Background_startup.jpg +0 -0
  16. setiastro/images/HRDiagram.png +0 -0
  17. setiastro/images/LExtract.png +0 -0
  18. setiastro/images/LInsert.png +0 -0
  19. setiastro/images/Oxygenation-atm-2.svg.png +0 -0
  20. setiastro/images/RGB080604.png +0 -0
  21. setiastro/images/abeicon.png +0 -0
  22. setiastro/images/aberration.png +0 -0
  23. setiastro/images/andromedatry.png +0 -0
  24. setiastro/images/andromedatry_satellited.png +0 -0
  25. setiastro/images/annotated.png +0 -0
  26. setiastro/images/aperture.png +0 -0
  27. setiastro/images/astrosuite.ico +0 -0
  28. setiastro/images/astrosuite.png +0 -0
  29. setiastro/images/astrosuitepro.icns +0 -0
  30. setiastro/images/astrosuitepro.ico +0 -0
  31. setiastro/images/astrosuitepro.png +0 -0
  32. setiastro/images/background.png +0 -0
  33. setiastro/images/background2.png +0 -0
  34. setiastro/images/benchmark.png +0 -0
  35. setiastro/images/big_moon_stabilizer_timeline.png +0 -0
  36. setiastro/images/big_moon_stabilizer_timeline_clean.png +0 -0
  37. setiastro/images/blaster.png +0 -0
  38. setiastro/images/blink.png +0 -0
  39. setiastro/images/clahe.png +0 -0
  40. setiastro/images/collage.png +0 -0
  41. setiastro/images/colorwheel.png +0 -0
  42. setiastro/images/contsub.png +0 -0
  43. setiastro/images/convo.png +0 -0
  44. setiastro/images/copyslot.png +0 -0
  45. setiastro/images/cosmic.png +0 -0
  46. setiastro/images/cosmicsat.png +0 -0
  47. setiastro/images/crop1.png +0 -0
  48. setiastro/images/cropicon.png +0 -0
  49. setiastro/images/curves.png +0 -0
  50. setiastro/images/cvs.png +0 -0
  51. setiastro/images/debayer.png +0 -0
  52. setiastro/images/denoise_cnn_custom.png +0 -0
  53. setiastro/images/denoise_cnn_graph.png +0 -0
  54. setiastro/images/disk.png +0 -0
  55. setiastro/images/dse.png +0 -0
  56. setiastro/images/exoicon.png +0 -0
  57. setiastro/images/eye.png +0 -0
  58. setiastro/images/fliphorizontal.png +0 -0
  59. setiastro/images/flipvertical.png +0 -0
  60. setiastro/images/font.png +0 -0
  61. setiastro/images/freqsep.png +0 -0
  62. setiastro/images/functionbundle.png +0 -0
  63. setiastro/images/graxpert.png +0 -0
  64. setiastro/images/green.png +0 -0
  65. setiastro/images/gridicon.png +0 -0
  66. setiastro/images/halo.png +0 -0
  67. setiastro/images/hdr.png +0 -0
  68. setiastro/images/histogram.png +0 -0
  69. setiastro/images/hubble.png +0 -0
  70. setiastro/images/imagecombine.png +0 -0
  71. setiastro/images/invert.png +0 -0
  72. setiastro/images/isophote.png +0 -0
  73. setiastro/images/isophote_demo_figure.png +0 -0
  74. setiastro/images/isophote_demo_image.png +0 -0
  75. setiastro/images/isophote_demo_model.png +0 -0
  76. setiastro/images/isophote_demo_residual.png +0 -0
  77. setiastro/images/jwstpupil.png +0 -0
  78. setiastro/images/linearfit.png +0 -0
  79. setiastro/images/livestacking.png +0 -0
  80. setiastro/images/mask.png +0 -0
  81. setiastro/images/maskapply.png +0 -0
  82. setiastro/images/maskcreate.png +0 -0
  83. setiastro/images/maskremove.png +0 -0
  84. setiastro/images/morpho.png +0 -0
  85. setiastro/images/mosaic.png +0 -0
  86. setiastro/images/multiscale_decomp.png +0 -0
  87. setiastro/images/nbtorgb.png +0 -0
  88. setiastro/images/neutral.png +0 -0
  89. setiastro/images/nuke.png +0 -0
  90. setiastro/images/openfile.png +0 -0
  91. setiastro/images/pedestal.png +0 -0
  92. setiastro/images/pen.png +0 -0
  93. setiastro/images/pixelmath.png +0 -0
  94. setiastro/images/platesolve.png +0 -0
  95. setiastro/images/ppp.png +0 -0
  96. setiastro/images/pro.png +0 -0
  97. setiastro/images/project.png +0 -0
  98. setiastro/images/psf.png +0 -0
  99. setiastro/images/redo.png +0 -0
  100. setiastro/images/redoicon.png +0 -0
  101. setiastro/images/rescale.png +0 -0
  102. setiastro/images/rgbalign.png +0 -0
  103. setiastro/images/rgbcombo.png +0 -0
  104. setiastro/images/rgbextract.png +0 -0
  105. setiastro/images/rotate180.png +0 -0
  106. setiastro/images/rotatearbitrary.png +0 -0
  107. setiastro/images/rotateclockwise.png +0 -0
  108. setiastro/images/rotatecounterclockwise.png +0 -0
  109. setiastro/images/satellite.png +0 -0
  110. setiastro/images/script.png +0 -0
  111. setiastro/images/selectivecolor.png +0 -0
  112. setiastro/images/simbad.png +0 -0
  113. setiastro/images/slot0.png +0 -0
  114. setiastro/images/slot1.png +0 -0
  115. setiastro/images/slot2.png +0 -0
  116. setiastro/images/slot3.png +0 -0
  117. setiastro/images/slot4.png +0 -0
  118. setiastro/images/slot5.png +0 -0
  119. setiastro/images/slot6.png +0 -0
  120. setiastro/images/slot7.png +0 -0
  121. setiastro/images/slot8.png +0 -0
  122. setiastro/images/slot9.png +0 -0
  123. setiastro/images/spcc.png +0 -0
  124. setiastro/images/spin_precession_vs_lunar_distance.png +0 -0
  125. setiastro/images/spinner.gif +0 -0
  126. setiastro/images/stacking.png +0 -0
  127. setiastro/images/staradd.png +0 -0
  128. setiastro/images/staralign.png +0 -0
  129. setiastro/images/starnet.png +0 -0
  130. setiastro/images/starregistration.png +0 -0
  131. setiastro/images/starspike.png +0 -0
  132. setiastro/images/starstretch.png +0 -0
  133. setiastro/images/statstretch.png +0 -0
  134. setiastro/images/supernova.png +0 -0
  135. setiastro/images/uhs.png +0 -0
  136. setiastro/images/undoicon.png +0 -0
  137. setiastro/images/upscale.png +0 -0
  138. setiastro/images/viewbundle.png +0 -0
  139. setiastro/images/whitebalance.png +0 -0
  140. setiastro/images/wimi_icon_256x256.png +0 -0
  141. setiastro/images/wimilogo.png +0 -0
  142. setiastro/images/wims.png +0 -0
  143. setiastro/images/wrench_icon.png +0 -0
  144. setiastro/images/xisfliberator.png +0 -0
  145. setiastro/qml/ResourceMonitor.qml +126 -0
  146. setiastro/saspro/__init__.py +20 -0
  147. setiastro/saspro/__main__.py +958 -0
  148. setiastro/saspro/_generated/__init__.py +7 -0
  149. setiastro/saspro/_generated/build_info.py +3 -0
  150. setiastro/saspro/abe.py +1346 -0
  151. setiastro/saspro/abe_preset.py +196 -0
  152. setiastro/saspro/aberration_ai.py +698 -0
  153. setiastro/saspro/aberration_ai_preset.py +224 -0
  154. setiastro/saspro/accel_installer.py +218 -0
  155. setiastro/saspro/accel_workers.py +30 -0
  156. setiastro/saspro/add_stars.py +624 -0
  157. setiastro/saspro/astrobin_exporter.py +1010 -0
  158. setiastro/saspro/astrospike.py +153 -0
  159. setiastro/saspro/astrospike_python.py +1841 -0
  160. setiastro/saspro/autostretch.py +198 -0
  161. setiastro/saspro/backgroundneutral.py +611 -0
  162. setiastro/saspro/batch_convert.py +328 -0
  163. setiastro/saspro/batch_renamer.py +522 -0
  164. setiastro/saspro/blemish_blaster.py +491 -0
  165. setiastro/saspro/blink_comparator_pro.py +3149 -0
  166. setiastro/saspro/bundles.py +61 -0
  167. setiastro/saspro/bundles_dock.py +114 -0
  168. setiastro/saspro/cheat_sheet.py +213 -0
  169. setiastro/saspro/clahe.py +368 -0
  170. setiastro/saspro/comet_stacking.py +1442 -0
  171. setiastro/saspro/common_tr.py +107 -0
  172. setiastro/saspro/config.py +38 -0
  173. setiastro/saspro/config_bootstrap.py +40 -0
  174. setiastro/saspro/config_manager.py +316 -0
  175. setiastro/saspro/continuum_subtract.py +1617 -0
  176. setiastro/saspro/convo.py +1400 -0
  177. setiastro/saspro/convo_preset.py +414 -0
  178. setiastro/saspro/copyastro.py +190 -0
  179. setiastro/saspro/cosmicclarity.py +1589 -0
  180. setiastro/saspro/cosmicclarity_preset.py +407 -0
  181. setiastro/saspro/crop_dialog_pro.py +983 -0
  182. setiastro/saspro/crop_preset.py +189 -0
  183. setiastro/saspro/curve_editor_pro.py +2562 -0
  184. setiastro/saspro/curves_preset.py +375 -0
  185. setiastro/saspro/debayer.py +673 -0
  186. setiastro/saspro/debug_utils.py +29 -0
  187. setiastro/saspro/dnd_mime.py +35 -0
  188. setiastro/saspro/doc_manager.py +2664 -0
  189. setiastro/saspro/exoplanet_detector.py +2166 -0
  190. setiastro/saspro/file_utils.py +284 -0
  191. setiastro/saspro/fitsmodifier.py +748 -0
  192. setiastro/saspro/fix_bom.py +32 -0
  193. setiastro/saspro/free_torch_memory.py +48 -0
  194. setiastro/saspro/frequency_separation.py +1349 -0
  195. setiastro/saspro/function_bundle.py +1596 -0
  196. setiastro/saspro/generate_translations.py +3092 -0
  197. setiastro/saspro/ghs_dialog_pro.py +663 -0
  198. setiastro/saspro/ghs_preset.py +284 -0
  199. setiastro/saspro/graxpert.py +637 -0
  200. setiastro/saspro/graxpert_preset.py +287 -0
  201. setiastro/saspro/gui/__init__.py +0 -0
  202. setiastro/saspro/gui/main_window.py +8792 -0
  203. setiastro/saspro/gui/mixins/__init__.py +33 -0
  204. setiastro/saspro/gui/mixins/dock_mixin.py +375 -0
  205. setiastro/saspro/gui/mixins/file_mixin.py +450 -0
  206. setiastro/saspro/gui/mixins/geometry_mixin.py +503 -0
  207. setiastro/saspro/gui/mixins/header_mixin.py +441 -0
  208. setiastro/saspro/gui/mixins/mask_mixin.py +421 -0
  209. setiastro/saspro/gui/mixins/menu_mixin.py +390 -0
  210. setiastro/saspro/gui/mixins/theme_mixin.py +367 -0
  211. setiastro/saspro/gui/mixins/toolbar_mixin.py +1619 -0
  212. setiastro/saspro/gui/mixins/update_mixin.py +323 -0
  213. setiastro/saspro/gui/mixins/view_mixin.py +435 -0
  214. setiastro/saspro/gui/statistics_dialog.py +47 -0
  215. setiastro/saspro/halobgon.py +488 -0
  216. setiastro/saspro/header_viewer.py +448 -0
  217. setiastro/saspro/headless_utils.py +88 -0
  218. setiastro/saspro/histogram.py +756 -0
  219. setiastro/saspro/history_explorer.py +941 -0
  220. setiastro/saspro/i18n.py +168 -0
  221. setiastro/saspro/image_combine.py +417 -0
  222. setiastro/saspro/image_peeker_pro.py +1604 -0
  223. setiastro/saspro/imageops/__init__.py +37 -0
  224. setiastro/saspro/imageops/mdi_snap.py +292 -0
  225. setiastro/saspro/imageops/scnr.py +36 -0
  226. setiastro/saspro/imageops/starbasedwhitebalance.py +210 -0
  227. setiastro/saspro/imageops/stretch.py +236 -0
  228. setiastro/saspro/isophote.py +1182 -0
  229. setiastro/saspro/layers.py +208 -0
  230. setiastro/saspro/layers_dock.py +714 -0
  231. setiastro/saspro/lazy_imports.py +193 -0
  232. setiastro/saspro/legacy/__init__.py +2 -0
  233. setiastro/saspro/legacy/image_manager.py +2360 -0
  234. setiastro/saspro/legacy/numba_utils.py +3676 -0
  235. setiastro/saspro/legacy/xisf.py +1213 -0
  236. setiastro/saspro/linear_fit.py +537 -0
  237. setiastro/saspro/live_stacking.py +1854 -0
  238. setiastro/saspro/log_bus.py +5 -0
  239. setiastro/saspro/logging_config.py +460 -0
  240. setiastro/saspro/luminancerecombine.py +510 -0
  241. setiastro/saspro/main_helpers.py +201 -0
  242. setiastro/saspro/mask_creation.py +1086 -0
  243. setiastro/saspro/masks_core.py +56 -0
  244. setiastro/saspro/mdi_widgets.py +353 -0
  245. setiastro/saspro/memory_utils.py +666 -0
  246. setiastro/saspro/metadata_patcher.py +75 -0
  247. setiastro/saspro/mfdeconv.py +3909 -0
  248. setiastro/saspro/mfdeconv_earlystop.py +71 -0
  249. setiastro/saspro/mfdeconvcudnn.py +3312 -0
  250. setiastro/saspro/mfdeconvsport.py +2459 -0
  251. setiastro/saspro/minorbodycatalog.py +567 -0
  252. setiastro/saspro/morphology.py +407 -0
  253. setiastro/saspro/multiscale_decomp.py +1747 -0
  254. setiastro/saspro/nbtorgb_stars.py +541 -0
  255. setiastro/saspro/numba_utils.py +3145 -0
  256. setiastro/saspro/numba_warmup.py +141 -0
  257. setiastro/saspro/ops/__init__.py +9 -0
  258. setiastro/saspro/ops/command_help_dialog.py +623 -0
  259. setiastro/saspro/ops/command_runner.py +217 -0
  260. setiastro/saspro/ops/commands.py +1594 -0
  261. setiastro/saspro/ops/script_editor.py +1105 -0
  262. setiastro/saspro/ops/scripts.py +1476 -0
  263. setiastro/saspro/ops/settings.py +637 -0
  264. setiastro/saspro/parallel_utils.py +554 -0
  265. setiastro/saspro/pedestal.py +121 -0
  266. setiastro/saspro/perfect_palette_picker.py +1105 -0
  267. setiastro/saspro/pipeline.py +110 -0
  268. setiastro/saspro/pixelmath.py +1604 -0
  269. setiastro/saspro/plate_solver.py +2445 -0
  270. setiastro/saspro/project_io.py +797 -0
  271. setiastro/saspro/psf_utils.py +136 -0
  272. setiastro/saspro/psf_viewer.py +549 -0
  273. setiastro/saspro/pyi_rthook_astroquery.py +95 -0
  274. setiastro/saspro/remove_green.py +331 -0
  275. setiastro/saspro/remove_stars.py +1599 -0
  276. setiastro/saspro/remove_stars_preset.py +446 -0
  277. setiastro/saspro/resources.py +503 -0
  278. setiastro/saspro/rgb_combination.py +208 -0
  279. setiastro/saspro/rgb_extract.py +19 -0
  280. setiastro/saspro/rgbalign.py +723 -0
  281. setiastro/saspro/runtime_imports.py +7 -0
  282. setiastro/saspro/runtime_torch.py +754 -0
  283. setiastro/saspro/save_options.py +73 -0
  284. setiastro/saspro/selective_color.py +1611 -0
  285. setiastro/saspro/sfcc.py +1472 -0
  286. setiastro/saspro/shortcuts.py +3116 -0
  287. setiastro/saspro/signature_insert.py +1102 -0
  288. setiastro/saspro/stacking_suite.py +19066 -0
  289. setiastro/saspro/star_alignment.py +7380 -0
  290. setiastro/saspro/star_alignment_preset.py +329 -0
  291. setiastro/saspro/star_metrics.py +49 -0
  292. setiastro/saspro/star_spikes.py +765 -0
  293. setiastro/saspro/star_stretch.py +507 -0
  294. setiastro/saspro/stat_stretch.py +538 -0
  295. setiastro/saspro/status_log_dock.py +78 -0
  296. setiastro/saspro/subwindow.py +3407 -0
  297. setiastro/saspro/supernovaasteroidhunter.py +1719 -0
  298. setiastro/saspro/swap_manager.py +134 -0
  299. setiastro/saspro/torch_backend.py +89 -0
  300. setiastro/saspro/torch_rejection.py +434 -0
  301. setiastro/saspro/translations/all_source_strings.json +4726 -0
  302. setiastro/saspro/translations/ar_translations.py +4096 -0
  303. setiastro/saspro/translations/de_translations.py +3728 -0
  304. setiastro/saspro/translations/es_translations.py +4169 -0
  305. setiastro/saspro/translations/fr_translations.py +4090 -0
  306. setiastro/saspro/translations/hi_translations.py +3803 -0
  307. setiastro/saspro/translations/integrate_translations.py +271 -0
  308. setiastro/saspro/translations/it_translations.py +4728 -0
  309. setiastro/saspro/translations/ja_translations.py +3834 -0
  310. setiastro/saspro/translations/pt_translations.py +3847 -0
  311. setiastro/saspro/translations/ru_translations.py +3082 -0
  312. setiastro/saspro/translations/saspro_ar.qm +0 -0
  313. setiastro/saspro/translations/saspro_ar.ts +16019 -0
  314. setiastro/saspro/translations/saspro_de.qm +0 -0
  315. setiastro/saspro/translations/saspro_de.ts +14548 -0
  316. setiastro/saspro/translations/saspro_es.qm +0 -0
  317. setiastro/saspro/translations/saspro_es.ts +16202 -0
  318. setiastro/saspro/translations/saspro_fr.qm +0 -0
  319. setiastro/saspro/translations/saspro_fr.ts +15870 -0
  320. setiastro/saspro/translations/saspro_hi.qm +0 -0
  321. setiastro/saspro/translations/saspro_hi.ts +14855 -0
  322. setiastro/saspro/translations/saspro_it.qm +0 -0
  323. setiastro/saspro/translations/saspro_it.ts +19046 -0
  324. setiastro/saspro/translations/saspro_ja.qm +0 -0
  325. setiastro/saspro/translations/saspro_ja.ts +14980 -0
  326. setiastro/saspro/translations/saspro_pt.qm +0 -0
  327. setiastro/saspro/translations/saspro_pt.ts +15024 -0
  328. setiastro/saspro/translations/saspro_ru.qm +0 -0
  329. setiastro/saspro/translations/saspro_ru.ts +11835 -0
  330. setiastro/saspro/translations/saspro_sw.qm +0 -0
  331. setiastro/saspro/translations/saspro_sw.ts +15237 -0
  332. setiastro/saspro/translations/saspro_uk.qm +0 -0
  333. setiastro/saspro/translations/saspro_uk.ts +15248 -0
  334. setiastro/saspro/translations/saspro_zh.qm +0 -0
  335. setiastro/saspro/translations/saspro_zh.ts +15289 -0
  336. setiastro/saspro/translations/sw_translations.py +3897 -0
  337. setiastro/saspro/translations/uk_translations.py +3929 -0
  338. setiastro/saspro/translations/zh_translations.py +3910 -0
  339. setiastro/saspro/versioning.py +77 -0
  340. setiastro/saspro/view_bundle.py +1558 -0
  341. setiastro/saspro/wavescale_hdr.py +645 -0
  342. setiastro/saspro/wavescale_hdr_preset.py +101 -0
  343. setiastro/saspro/wavescalede.py +680 -0
  344. setiastro/saspro/wavescalede_preset.py +230 -0
  345. setiastro/saspro/wcs_update.py +374 -0
  346. setiastro/saspro/whitebalance.py +513 -0
  347. setiastro/saspro/widgets/__init__.py +48 -0
  348. setiastro/saspro/widgets/common_utilities.py +306 -0
  349. setiastro/saspro/widgets/graphics_views.py +122 -0
  350. setiastro/saspro/widgets/image_utils.py +518 -0
  351. setiastro/saspro/widgets/minigame/game.js +991 -0
  352. setiastro/saspro/widgets/minigame/index.html +53 -0
  353. setiastro/saspro/widgets/minigame/style.css +241 -0
  354. setiastro/saspro/widgets/preview_dialogs.py +280 -0
  355. setiastro/saspro/widgets/resource_monitor.py +263 -0
  356. setiastro/saspro/widgets/spinboxes.py +290 -0
  357. setiastro/saspro/widgets/themed_buttons.py +13 -0
  358. setiastro/saspro/widgets/wavelet_utils.py +331 -0
  359. setiastro/saspro/wimi.py +7996 -0
  360. setiastro/saspro/wims.py +578 -0
  361. setiastro/saspro/window_shelf.py +185 -0
  362. setiastro/saspro/xisf.py +1213 -0
  363. setiastrosuitepro-1.6.5.post3.dist-info/METADATA +278 -0
  364. setiastrosuitepro-1.6.5.post3.dist-info/RECORD +368 -0
  365. setiastrosuitepro-1.6.5.post3.dist-info/WHEEL +4 -0
  366. setiastrosuitepro-1.6.5.post3.dist-info/entry_points.txt +6 -0
  367. setiastrosuitepro-1.6.5.post3.dist-info/licenses/LICENSE +674 -0
  368. setiastrosuitepro-1.6.5.post3.dist-info/licenses/license.txt +2580 -0
@@ -0,0 +1,107 @@
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ Common UI strings translation module.
4
+
5
+ This module provides centralized translation for common button labels,
6
+ dialog titles, and messages used throughout the application.
7
+ """
8
+ from PyQt6.QtCore import QCoreApplication
9
+
10
+ def _tr(text: str, context: str = "Common") -> str:
11
+ """Translate common UI strings."""
12
+ return QCoreApplication.translate(context, text)
13
+
14
+ # ============================================================================
15
+ # Common Button Labels
16
+ # ============================================================================
17
+ class Buttons:
18
+ @staticmethod
19
+ def apply(): return _tr("Apply")
20
+ @staticmethod
21
+ def cancel(): return _tr("Cancel")
22
+ @staticmethod
23
+ def close(): return _tr("Close")
24
+ @staticmethod
25
+ def ok(): return _tr("OK")
26
+ @staticmethod
27
+ def yes(): return _tr("Yes")
28
+ @staticmethod
29
+ def no(): return _tr("No")
30
+ @staticmethod
31
+ def save(): return _tr("Save")
32
+ @staticmethod
33
+ def save_as(): return _tr("Save As...")
34
+ @staticmethod
35
+ def open(): return _tr("Open...")
36
+ @staticmethod
37
+ def browse(): return _tr("Browse...")
38
+ @staticmethod
39
+ def reset(): return _tr("Reset")
40
+ @staticmethod
41
+ def clear(): return _tr("Clear")
42
+ @staticmethod
43
+ def delete(): return _tr("Delete")
44
+ @staticmethod
45
+ def add(): return _tr("Add")
46
+ @staticmethod
47
+ def remove(): return _tr("Remove")
48
+ @staticmethod
49
+ def preview(): return _tr("Preview")
50
+ @staticmethod
51
+ def apply_to_document(): return _tr("Apply to Document")
52
+ @staticmethod
53
+ def zoom_in(): return _tr("Zoom In")
54
+ @staticmethod
55
+ def zoom_out(): return _tr("Zoom Out")
56
+ @staticmethod
57
+ def fit_to_preview(): return _tr("Fit to Preview")
58
+ @staticmethod
59
+ def show_original(): return _tr("Show Original")
60
+ @staticmethod
61
+ def run(): return _tr("Run")
62
+ @staticmethod
63
+ def stop(): return _tr("Stop")
64
+ @staticmethod
65
+ def export(): return _tr("Export")
66
+ @staticmethod
67
+ def import_(): return _tr("Import")
68
+
69
+ # ============================================================================
70
+ # Common Dialog Titles
71
+ # ============================================================================
72
+ class Titles:
73
+ @staticmethod
74
+ def error(): return _tr("Error")
75
+ @staticmethod
76
+ def warning(): return _tr("Warning")
77
+ @staticmethod
78
+ def info(): return _tr("Information")
79
+ @staticmethod
80
+ def confirm(): return _tr("Confirm")
81
+ @staticmethod
82
+ def success(): return _tr("Success")
83
+ @staticmethod
84
+ def processing(): return _tr("Processing...")
85
+ @staticmethod
86
+ def please_wait(): return _tr("Please wait")
87
+
88
+ # ============================================================================
89
+ # Common Messages
90
+ # ============================================================================
91
+ class Messages:
92
+ @staticmethod
93
+ def no_image(): return _tr("No image loaded.")
94
+ @staticmethod
95
+ def no_active_image(): return _tr("No active image.")
96
+ @staticmethod
97
+ def load_image_first(): return _tr("Load an image first.")
98
+ @staticmethod
99
+ def processing_failed(): return _tr("Processing failed.")
100
+ @staticmethod
101
+ def operation_complete(): return _tr("Operation complete.")
102
+ @staticmethod
103
+ def are_you_sure(): return _tr("Are you sure?")
104
+ @staticmethod
105
+ def unsaved_changes(): return _tr("You have unsaved changes.")
106
+ @staticmethod
107
+ def exit_confirm(): return _tr("Do you really want to exit?")
@@ -0,0 +1,38 @@
1
+ # pro/config.py
2
+ import os
3
+ import sys
4
+ from PyQt6.QtCore import QStandardPaths
5
+
6
+ class Config:
7
+ """Central configuration for Seti Astro Suite Pro."""
8
+
9
+ # GitHub Repos
10
+ GITHUB_ABERRATION_REPO = "riccardoalberghi/abberation_models"
11
+
12
+ # Paths
13
+ @staticmethod
14
+ def get_app_data_dir() -> str:
15
+ """Returns the application data directory."""
16
+ base = QStandardPaths.writableLocation(QStandardPaths.StandardLocation.AppDataLocation)
17
+ if not base:
18
+ base = os.path.expanduser("~/.local/share/SetiAstro")
19
+ return base
20
+
21
+ @staticmethod
22
+ def get_models_dir() -> str:
23
+ """Returns the directory for storing AI models."""
24
+ return os.path.join(Config.get_app_data_dir(), "Models")
25
+
26
+ @staticmethod
27
+ def get_aberration_models_dir() -> str:
28
+ """Returns the directory for Aberration AI models."""
29
+ return os.path.join(Config.get_models_dir(), "aberration_ai")
30
+
31
+ @staticmethod
32
+ def get_graxpert_default_path() -> str | None:
33
+ """Returns the default GraXpert executable path based on OS."""
34
+ if sys.platform == "darwin":
35
+ return "/Applications/GraXpert.app/Contents/MacOS/GraXpert"
36
+ elif sys.platform == "win32":
37
+ return "GraXpert.exe"
38
+ return None
@@ -0,0 +1,40 @@
1
+ """
2
+ Centralized matplotlib configuration bootstrap.
3
+
4
+ This module provides a single source of truth for setting up matplotlib's
5
+ configuration directory, used by both the main application entry point and
6
+ the GUI main window.
7
+ """
8
+ import os
9
+ import sys
10
+
11
+
12
+ def ensure_mpl_config_dir() -> str:
13
+ """
14
+ Make matplotlib use a known, writable folder.
15
+
16
+ Frozen (PyInstaller): <folder-with-exe>/mpl_config
17
+ Dev / IDE: <repo-folder>/mpl_config
18
+
19
+ This matches the pre-warm script that will build the font cache there.
20
+
21
+ Returns:
22
+ str: Path to the matplotlib configuration directory
23
+ """
24
+ if getattr(sys, "frozen", False):
25
+ base = os.path.dirname(sys.executable)
26
+ else:
27
+ base = os.path.dirname(os.path.abspath(__file__))
28
+ # We're in pro/ directory, go up one level to project root
29
+ base = os.path.dirname(base)
30
+
31
+ mpl_cfg = os.path.join(base, "mpl_config")
32
+ try:
33
+ os.makedirs(mpl_cfg, exist_ok=True)
34
+ except OSError:
35
+ # worst case: let matplotlib pick its default
36
+ return mpl_cfg
37
+
38
+ # only set if user / env didn't force something else
39
+ os.environ.setdefault("MPLCONFIGDIR", mpl_cfg)
40
+ return mpl_cfg
@@ -0,0 +1,316 @@
1
+ # pro/config_manager.py
2
+ """
3
+ Centralized configuration manager for Seti Astro Suite Pro.
4
+
5
+ Provides type-safe access to application settings with validation,
6
+ defaults, and change notifications.
7
+ """
8
+ from __future__ import annotations
9
+
10
+ from typing import Any, Dict, Optional, TypeVar, Generic, Callable, List
11
+ from PyQt6.QtCore import QSettings, QObject, pyqtSignal
12
+ import json
13
+ import os
14
+
15
+ T = TypeVar('T')
16
+
17
+
18
+ class ConfigValue(Generic[T]):
19
+ """
20
+ Descriptor for a typed configuration value.
21
+
22
+ Usage:
23
+ class MyConfig(ConfigManager):
24
+ my_setting = ConfigValue("my_setting", default=10, type_=int)
25
+ """
26
+ def __init__(
27
+ self,
28
+ key: str,
29
+ default: T,
30
+ type_: type = str,
31
+ validator: Callable[[T], bool] | None = None,
32
+ description: str = ""
33
+ ):
34
+ self.key = key
35
+ self.default = default
36
+ self.type_ = type_
37
+ self.validator = validator
38
+ self.description = description
39
+
40
+ def __set_name__(self, owner, name):
41
+ self.name = name
42
+
43
+ def __get__(self, obj, objtype=None) -> T:
44
+ if obj is None:
45
+ return self # type: ignore
46
+ return obj.get(self.key, self.default, self.type_)
47
+
48
+ def __set__(self, obj, value: T):
49
+ if self.validator and not self.validator(value):
50
+ raise ValueError(f"Invalid value for {self.key}: {value}")
51
+ obj.set(self.key, value)
52
+
53
+
54
+ class ConfigManager(QObject):
55
+ """
56
+ Centralized configuration manager with type safety.
57
+
58
+ Wraps QSettings with:
59
+ - Type-safe get/set
60
+ - Default values
61
+ - Change notifications
62
+ - Validation
63
+
64
+ Usage:
65
+ config = ConfigManager.instance()
66
+ config.set("my_key", 42)
67
+ value = config.get("my_key", default=0, type_=int)
68
+
69
+ Or with descriptors:
70
+ class AppConfig(ConfigManager):
71
+ chunk_height = ConfigValue("stacking/chunk_height", default=512, type_=int)
72
+
73
+ config = AppConfig.instance()
74
+ print(config.chunk_height)
75
+ config.chunk_height = 1024
76
+ """
77
+
78
+ # Singleton instance
79
+ _instance: Optional['ConfigManager'] = None
80
+
81
+ # Signal emitted when any setting changes
82
+ settingChanged = pyqtSignal(str, object) # key, new_value
83
+
84
+ def __init__(self, organization: str = "SetiAstro", application: str = "SetiAstroSuitePro"):
85
+ super().__init__()
86
+ self._settings = QSettings(organization, application)
87
+ self._cache: Dict[str, Any] = {}
88
+ self._listeners: Dict[str, List[Callable]] = {}
89
+
90
+ @classmethod
91
+ def instance(cls) -> 'ConfigManager':
92
+ """Get the singleton instance."""
93
+ if cls._instance is None:
94
+ cls._instance = cls()
95
+ return cls._instance
96
+
97
+ @classmethod
98
+ def reset_instance(cls):
99
+ """Reset the singleton (mainly for testing)."""
100
+ cls._instance = None
101
+
102
+ def get(self, key: str, default: T = None, type_: type = str) -> T:
103
+ """
104
+ Get a configuration value with type conversion.
105
+
106
+ Args:
107
+ key: The setting key (can use "/" for groups, e.g., "stacking/chunk_size")
108
+ default: Default value if key doesn't exist
109
+ type_: Expected type (int, float, bool, str, list, dict)
110
+
111
+ Returns:
112
+ The value converted to the specified type
113
+ """
114
+ # Check cache first
115
+ cache_key = f"{key}:{type_.__name__}"
116
+ if cache_key in self._cache:
117
+ return self._cache[cache_key]
118
+
119
+ value = self._settings.value(key, default)
120
+
121
+ # Convert to requested type
122
+ if value is None:
123
+ return default
124
+
125
+ try:
126
+ if type_ == bool:
127
+ # QSettings stores bools as strings sometimes
128
+ if isinstance(value, str):
129
+ value = value.lower() in ('true', '1', 'yes')
130
+ else:
131
+ value = bool(value)
132
+ elif type_ == int:
133
+ value = int(value)
134
+ elif type_ == float:
135
+ value = float(value)
136
+ elif type_ == list:
137
+ if isinstance(value, str):
138
+ value = json.loads(value) if value else []
139
+ elif not isinstance(value, list):
140
+ value = list(value) if value else []
141
+ elif type_ == dict:
142
+ if isinstance(value, str):
143
+ value = json.loads(value) if value else {}
144
+ elif not isinstance(value, dict):
145
+ value = {}
146
+ else:
147
+ value = type_(value)
148
+ except (ValueError, TypeError, json.JSONDecodeError):
149
+ value = default
150
+
151
+ # Cache the result
152
+ self._cache[cache_key] = value
153
+ return value
154
+
155
+ def set(self, key: str, value: Any) -> None:
156
+ """
157
+ Set a configuration value.
158
+
159
+ Args:
160
+ key: The setting key
161
+ value: The value to store
162
+ """
163
+ # Invalidate cache for this key
164
+ for cache_key in list(self._cache.keys()):
165
+ if cache_key.startswith(f"{key}:"):
166
+ del self._cache[cache_key]
167
+
168
+ # Convert complex types to JSON for storage
169
+ if isinstance(value, (list, dict)):
170
+ value = json.dumps(value)
171
+
172
+ self._settings.setValue(key, value)
173
+
174
+ # Emit signal
175
+ self.settingChanged.emit(key, value)
176
+
177
+ # Notify listeners
178
+ if key in self._listeners:
179
+ for callback in self._listeners[key]:
180
+ try:
181
+ callback(value)
182
+ except Exception:
183
+ pass
184
+
185
+ def remove(self, key: str) -> None:
186
+ """Remove a setting."""
187
+ # Invalidate cache
188
+ for cache_key in list(self._cache.keys()):
189
+ if cache_key.startswith(f"{key}:"):
190
+ del self._cache[cache_key]
191
+
192
+ self._settings.remove(key)
193
+
194
+ def contains(self, key: str) -> bool:
195
+ """Check if a setting exists."""
196
+ return self._settings.contains(key)
197
+
198
+ def all_keys(self) -> List[str]:
199
+ """Get all setting keys."""
200
+ return self._settings.allKeys()
201
+
202
+ def clear(self) -> None:
203
+ """Clear all settings."""
204
+ self._cache.clear()
205
+ self._settings.clear()
206
+
207
+ def sync(self) -> None:
208
+ """Force sync to disk."""
209
+ self._settings.sync()
210
+
211
+ def add_listener(self, key: str, callback: Callable[[Any], None]) -> None:
212
+ """
213
+ Add a listener for changes to a specific key.
214
+
215
+ Args:
216
+ key: The setting key to watch
217
+ callback: Function to call when value changes
218
+ """
219
+ if key not in self._listeners:
220
+ self._listeners[key] = []
221
+ self._listeners[key].append(callback)
222
+
223
+ def remove_listener(self, key: str, callback: Callable[[Any], None]) -> None:
224
+ """Remove a listener."""
225
+ if key in self._listeners and callback in self._listeners[key]:
226
+ self._listeners[key].remove(callback)
227
+
228
+ def begin_group(self, prefix: str) -> None:
229
+ """Begin a settings group (for hierarchical settings)."""
230
+ self._settings.beginGroup(prefix)
231
+
232
+ def end_group(self) -> None:
233
+ """End the current settings group."""
234
+ self._settings.endGroup()
235
+
236
+ def get_group(self, prefix: str) -> Dict[str, Any]:
237
+ """
238
+ Get all settings in a group as a dictionary.
239
+
240
+ Args:
241
+ prefix: The group prefix
242
+
243
+ Returns:
244
+ Dictionary of key -> value for all settings in the group
245
+ """
246
+ result = {}
247
+ self._settings.beginGroup(prefix)
248
+ for key in self._settings.childKeys():
249
+ result[key] = self._settings.value(key)
250
+ self._settings.endGroup()
251
+ return result
252
+
253
+ def set_group(self, prefix: str, values: Dict[str, Any]) -> None:
254
+ """
255
+ Set multiple settings in a group.
256
+
257
+ Args:
258
+ prefix: The group prefix
259
+ values: Dictionary of key -> value to set
260
+ """
261
+ self._settings.beginGroup(prefix)
262
+ for key, value in values.items():
263
+ if isinstance(value, (list, dict)):
264
+ value = json.dumps(value)
265
+ self._settings.setValue(key, value)
266
+ self._settings.endGroup()
267
+ self._cache.clear() # Invalidate all cache
268
+
269
+
270
+ # Convenience function
271
+ def get_config() -> ConfigManager:
272
+ """Get the global configuration manager."""
273
+ return ConfigManager.instance()
274
+
275
+
276
+ # ============================================================================
277
+ # Application-specific configuration class with typed properties
278
+ # ============================================================================
279
+
280
+ class AppConfig(ConfigManager):
281
+ """
282
+ Application configuration with typed properties.
283
+
284
+ Usage:
285
+ config = AppConfig.instance()
286
+ print(config.chunk_height)
287
+ config.chunk_height = 1024
288
+ """
289
+
290
+ # Stacking settings
291
+ chunk_height = ConfigValue("stacking/chunk_height", default=512, type_=int)
292
+ chunk_width = ConfigValue("stacking/chunk_width", default=512, type_=int)
293
+ use_gpu = ConfigValue("stacking/use_gpu", default=True, type_=bool)
294
+ rejection_algorithm = ConfigValue("stacking/rejection_algorithm", default="sigma_clip", type_=str)
295
+
296
+ # UI settings
297
+ theme = ConfigValue("ui/theme", default="dark", type_=str)
298
+ show_toolbar = ConfigValue("ui/show_toolbar", default=True, type_=bool)
299
+ recent_files_max = ConfigValue("ui/recent_files_max", default=10, type_=int)
300
+
301
+ # Performance settings
302
+ max_threads = ConfigValue("performance/max_threads", default=0, type_=int) # 0 = auto
303
+ memory_limit_mb = ConfigValue("performance/memory_limit_mb", default=0, type_=int) # 0 = no limit
304
+ use_memmap = ConfigValue("performance/use_memmap", default=True, type_=bool)
305
+
306
+ # Paths
307
+ last_open_dir = ConfigValue("paths/last_open_dir", default="", type_=str)
308
+ last_save_dir = ConfigValue("paths/last_save_dir", default="", type_=str)
309
+ output_dir = ConfigValue("paths/output_dir", default="", type_=str)
310
+
311
+
312
+ def get_app_config() -> AppConfig:
313
+ """Get the application configuration with typed properties."""
314
+ if AppConfig._instance is None:
315
+ AppConfig._instance = AppConfig()
316
+ return AppConfig._instance # type: ignore