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.

Files changed (394) 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/acv_icon.png +0 -0
  24. setiastro/images/andromedatry.png +0 -0
  25. setiastro/images/andromedatry_satellited.png +0 -0
  26. setiastro/images/annotated.png +0 -0
  27. setiastro/images/aperture.png +0 -0
  28. setiastro/images/astrosuite.ico +0 -0
  29. setiastro/images/astrosuite.png +0 -0
  30. setiastro/images/astrosuitepro.icns +0 -0
  31. setiastro/images/astrosuitepro.ico +0 -0
  32. setiastro/images/astrosuitepro.png +0 -0
  33. setiastro/images/background.png +0 -0
  34. setiastro/images/background2.png +0 -0
  35. setiastro/images/benchmark.png +0 -0
  36. setiastro/images/big_moon_stabilizer_timeline.png +0 -0
  37. setiastro/images/big_moon_stabilizer_timeline_clean.png +0 -0
  38. setiastro/images/blaster.png +0 -0
  39. setiastro/images/blink.png +0 -0
  40. setiastro/images/clahe.png +0 -0
  41. setiastro/images/collage.png +0 -0
  42. setiastro/images/colorwheel.png +0 -0
  43. setiastro/images/contsub.png +0 -0
  44. setiastro/images/convo.png +0 -0
  45. setiastro/images/copyslot.png +0 -0
  46. setiastro/images/cosmic.png +0 -0
  47. setiastro/images/cosmicsat.png +0 -0
  48. setiastro/images/crop1.png +0 -0
  49. setiastro/images/cropicon.png +0 -0
  50. setiastro/images/curves.png +0 -0
  51. setiastro/images/cvs.png +0 -0
  52. setiastro/images/debayer.png +0 -0
  53. setiastro/images/denoise_cnn_custom.png +0 -0
  54. setiastro/images/denoise_cnn_graph.png +0 -0
  55. setiastro/images/disk.png +0 -0
  56. setiastro/images/dse.png +0 -0
  57. setiastro/images/exoicon.png +0 -0
  58. setiastro/images/eye.png +0 -0
  59. setiastro/images/first_quarter.png +0 -0
  60. setiastro/images/fliphorizontal.png +0 -0
  61. setiastro/images/flipvertical.png +0 -0
  62. setiastro/images/font.png +0 -0
  63. setiastro/images/freqsep.png +0 -0
  64. setiastro/images/full_moon.png +0 -0
  65. setiastro/images/functionbundle.png +0 -0
  66. setiastro/images/graxpert.png +0 -0
  67. setiastro/images/green.png +0 -0
  68. setiastro/images/gridicon.png +0 -0
  69. setiastro/images/halo.png +0 -0
  70. setiastro/images/hdr.png +0 -0
  71. setiastro/images/histogram.png +0 -0
  72. setiastro/images/hubble.png +0 -0
  73. setiastro/images/imagecombine.png +0 -0
  74. setiastro/images/invert.png +0 -0
  75. setiastro/images/isophote.png +0 -0
  76. setiastro/images/isophote_demo_figure.png +0 -0
  77. setiastro/images/isophote_demo_image.png +0 -0
  78. setiastro/images/isophote_demo_model.png +0 -0
  79. setiastro/images/isophote_demo_residual.png +0 -0
  80. setiastro/images/jwstpupil.png +0 -0
  81. setiastro/images/last_quarter.png +0 -0
  82. setiastro/images/linearfit.png +0 -0
  83. setiastro/images/livestacking.png +0 -0
  84. setiastro/images/mask.png +0 -0
  85. setiastro/images/maskapply.png +0 -0
  86. setiastro/images/maskcreate.png +0 -0
  87. setiastro/images/maskremove.png +0 -0
  88. setiastro/images/morpho.png +0 -0
  89. setiastro/images/mosaic.png +0 -0
  90. setiastro/images/multiscale_decomp.png +0 -0
  91. setiastro/images/nbtorgb.png +0 -0
  92. setiastro/images/neutral.png +0 -0
  93. setiastro/images/new_moon.png +0 -0
  94. setiastro/images/nuke.png +0 -0
  95. setiastro/images/openfile.png +0 -0
  96. setiastro/images/pedestal.png +0 -0
  97. setiastro/images/pen.png +0 -0
  98. setiastro/images/pixelmath.png +0 -0
  99. setiastro/images/platesolve.png +0 -0
  100. setiastro/images/ppp.png +0 -0
  101. setiastro/images/pro.png +0 -0
  102. setiastro/images/project.png +0 -0
  103. setiastro/images/psf.png +0 -0
  104. setiastro/images/redo.png +0 -0
  105. setiastro/images/redoicon.png +0 -0
  106. setiastro/images/rescale.png +0 -0
  107. setiastro/images/rgbalign.png +0 -0
  108. setiastro/images/rgbcombo.png +0 -0
  109. setiastro/images/rgbextract.png +0 -0
  110. setiastro/images/rotate180.png +0 -0
  111. setiastro/images/rotatearbitrary.png +0 -0
  112. setiastro/images/rotateclockwise.png +0 -0
  113. setiastro/images/rotatecounterclockwise.png +0 -0
  114. setiastro/images/satellite.png +0 -0
  115. setiastro/images/script.png +0 -0
  116. setiastro/images/selectivecolor.png +0 -0
  117. setiastro/images/simbad.png +0 -0
  118. setiastro/images/slot0.png +0 -0
  119. setiastro/images/slot1.png +0 -0
  120. setiastro/images/slot2.png +0 -0
  121. setiastro/images/slot3.png +0 -0
  122. setiastro/images/slot4.png +0 -0
  123. setiastro/images/slot5.png +0 -0
  124. setiastro/images/slot6.png +0 -0
  125. setiastro/images/slot7.png +0 -0
  126. setiastro/images/slot8.png +0 -0
  127. setiastro/images/slot9.png +0 -0
  128. setiastro/images/spcc.png +0 -0
  129. setiastro/images/spin_precession_vs_lunar_distance.png +0 -0
  130. setiastro/images/spinner.gif +0 -0
  131. setiastro/images/stacking.png +0 -0
  132. setiastro/images/staradd.png +0 -0
  133. setiastro/images/staralign.png +0 -0
  134. setiastro/images/starnet.png +0 -0
  135. setiastro/images/starregistration.png +0 -0
  136. setiastro/images/starspike.png +0 -0
  137. setiastro/images/starstretch.png +0 -0
  138. setiastro/images/statstretch.png +0 -0
  139. setiastro/images/supernova.png +0 -0
  140. setiastro/images/uhs.png +0 -0
  141. setiastro/images/undoicon.png +0 -0
  142. setiastro/images/upscale.png +0 -0
  143. setiastro/images/viewbundle.png +0 -0
  144. setiastro/images/waning_crescent_1.png +0 -0
  145. setiastro/images/waning_crescent_2.png +0 -0
  146. setiastro/images/waning_crescent_3.png +0 -0
  147. setiastro/images/waning_crescent_4.png +0 -0
  148. setiastro/images/waning_crescent_5.png +0 -0
  149. setiastro/images/waning_gibbous_1.png +0 -0
  150. setiastro/images/waning_gibbous_2.png +0 -0
  151. setiastro/images/waning_gibbous_3.png +0 -0
  152. setiastro/images/waning_gibbous_4.png +0 -0
  153. setiastro/images/waning_gibbous_5.png +0 -0
  154. setiastro/images/waxing_crescent_1.png +0 -0
  155. setiastro/images/waxing_crescent_2.png +0 -0
  156. setiastro/images/waxing_crescent_3.png +0 -0
  157. setiastro/images/waxing_crescent_4.png +0 -0
  158. setiastro/images/waxing_crescent_5.png +0 -0
  159. setiastro/images/waxing_gibbous_1.png +0 -0
  160. setiastro/images/waxing_gibbous_2.png +0 -0
  161. setiastro/images/waxing_gibbous_3.png +0 -0
  162. setiastro/images/waxing_gibbous_4.png +0 -0
  163. setiastro/images/waxing_gibbous_5.png +0 -0
  164. setiastro/images/whitebalance.png +0 -0
  165. setiastro/images/wimi_icon_256x256.png +0 -0
  166. setiastro/images/wimilogo.png +0 -0
  167. setiastro/images/wims.png +0 -0
  168. setiastro/images/wrench_icon.png +0 -0
  169. setiastro/images/xisfliberator.png +0 -0
  170. setiastro/qml/ResourceMonitor.qml +128 -0
  171. setiastro/saspro/__init__.py +20 -0
  172. setiastro/saspro/__main__.py +964 -0
  173. setiastro/saspro/_generated/__init__.py +7 -0
  174. setiastro/saspro/_generated/build_info.py +3 -0
  175. setiastro/saspro/abe.py +1379 -0
  176. setiastro/saspro/abe_preset.py +196 -0
  177. setiastro/saspro/aberration_ai.py +910 -0
  178. setiastro/saspro/aberration_ai_preset.py +224 -0
  179. setiastro/saspro/accel_installer.py +218 -0
  180. setiastro/saspro/accel_workers.py +30 -0
  181. setiastro/saspro/acv_exporter.py +379 -0
  182. setiastro/saspro/add_stars.py +627 -0
  183. setiastro/saspro/astrobin_exporter.py +1010 -0
  184. setiastro/saspro/astrospike.py +153 -0
  185. setiastro/saspro/astrospike_python.py +1841 -0
  186. setiastro/saspro/autostretch.py +198 -0
  187. setiastro/saspro/backgroundneutral.py +639 -0
  188. setiastro/saspro/batch_convert.py +328 -0
  189. setiastro/saspro/batch_renamer.py +522 -0
  190. setiastro/saspro/blemish_blaster.py +494 -0
  191. setiastro/saspro/blink_comparator_pro.py +3149 -0
  192. setiastro/saspro/bundles.py +61 -0
  193. setiastro/saspro/bundles_dock.py +114 -0
  194. setiastro/saspro/cheat_sheet.py +213 -0
  195. setiastro/saspro/clahe.py +371 -0
  196. setiastro/saspro/comet_stacking.py +1442 -0
  197. setiastro/saspro/common_tr.py +107 -0
  198. setiastro/saspro/config.py +38 -0
  199. setiastro/saspro/config_bootstrap.py +40 -0
  200. setiastro/saspro/config_manager.py +316 -0
  201. setiastro/saspro/continuum_subtract.py +1620 -0
  202. setiastro/saspro/convo.py +1403 -0
  203. setiastro/saspro/convo_preset.py +414 -0
  204. setiastro/saspro/copyastro.py +190 -0
  205. setiastro/saspro/cosmicclarity.py +1593 -0
  206. setiastro/saspro/cosmicclarity_preset.py +407 -0
  207. setiastro/saspro/crop_dialog_pro.py +1005 -0
  208. setiastro/saspro/crop_preset.py +189 -0
  209. setiastro/saspro/curve_editor_pro.py +2608 -0
  210. setiastro/saspro/curves_preset.py +375 -0
  211. setiastro/saspro/debayer.py +673 -0
  212. setiastro/saspro/debug_utils.py +29 -0
  213. setiastro/saspro/dnd_mime.py +35 -0
  214. setiastro/saspro/doc_manager.py +2727 -0
  215. setiastro/saspro/exoplanet_detector.py +2258 -0
  216. setiastro/saspro/file_utils.py +284 -0
  217. setiastro/saspro/fitsmodifier.py +748 -0
  218. setiastro/saspro/fix_bom.py +32 -0
  219. setiastro/saspro/free_torch_memory.py +48 -0
  220. setiastro/saspro/frequency_separation.py +1352 -0
  221. setiastro/saspro/function_bundle.py +1596 -0
  222. setiastro/saspro/generate_translations.py +3092 -0
  223. setiastro/saspro/ghs_dialog_pro.py +728 -0
  224. setiastro/saspro/ghs_preset.py +284 -0
  225. setiastro/saspro/graxpert.py +638 -0
  226. setiastro/saspro/graxpert_preset.py +287 -0
  227. setiastro/saspro/gui/__init__.py +0 -0
  228. setiastro/saspro/gui/main_window.py +8928 -0
  229. setiastro/saspro/gui/mixins/__init__.py +33 -0
  230. setiastro/saspro/gui/mixins/dock_mixin.py +375 -0
  231. setiastro/saspro/gui/mixins/file_mixin.py +450 -0
  232. setiastro/saspro/gui/mixins/geometry_mixin.py +503 -0
  233. setiastro/saspro/gui/mixins/header_mixin.py +441 -0
  234. setiastro/saspro/gui/mixins/mask_mixin.py +421 -0
  235. setiastro/saspro/gui/mixins/menu_mixin.py +391 -0
  236. setiastro/saspro/gui/mixins/theme_mixin.py +367 -0
  237. setiastro/saspro/gui/mixins/toolbar_mixin.py +1824 -0
  238. setiastro/saspro/gui/mixins/update_mixin.py +323 -0
  239. setiastro/saspro/gui/mixins/view_mixin.py +477 -0
  240. setiastro/saspro/gui/statistics_dialog.py +47 -0
  241. setiastro/saspro/halobgon.py +492 -0
  242. setiastro/saspro/header_viewer.py +448 -0
  243. setiastro/saspro/headless_utils.py +88 -0
  244. setiastro/saspro/histogram.py +760 -0
  245. setiastro/saspro/history_explorer.py +941 -0
  246. setiastro/saspro/i18n.py +168 -0
  247. setiastro/saspro/image_combine.py +421 -0
  248. setiastro/saspro/image_peeker_pro.py +1608 -0
  249. setiastro/saspro/imageops/__init__.py +37 -0
  250. setiastro/saspro/imageops/mdi_snap.py +292 -0
  251. setiastro/saspro/imageops/scnr.py +36 -0
  252. setiastro/saspro/imageops/starbasedwhitebalance.py +210 -0
  253. setiastro/saspro/imageops/stretch.py +236 -0
  254. setiastro/saspro/isophote.py +1186 -0
  255. setiastro/saspro/layers.py +208 -0
  256. setiastro/saspro/layers_dock.py +714 -0
  257. setiastro/saspro/lazy_imports.py +193 -0
  258. setiastro/saspro/legacy/__init__.py +2 -0
  259. setiastro/saspro/legacy/image_manager.py +2360 -0
  260. setiastro/saspro/legacy/numba_utils.py +3676 -0
  261. setiastro/saspro/legacy/xisf.py +1213 -0
  262. setiastro/saspro/linear_fit.py +537 -0
  263. setiastro/saspro/live_stacking.py +1854 -0
  264. setiastro/saspro/log_bus.py +5 -0
  265. setiastro/saspro/logging_config.py +460 -0
  266. setiastro/saspro/luminancerecombine.py +510 -0
  267. setiastro/saspro/main_helpers.py +201 -0
  268. setiastro/saspro/mask_creation.py +1090 -0
  269. setiastro/saspro/masks_core.py +56 -0
  270. setiastro/saspro/mdi_widgets.py +353 -0
  271. setiastro/saspro/memory_utils.py +666 -0
  272. setiastro/saspro/metadata_patcher.py +75 -0
  273. setiastro/saspro/mfdeconv.py +3909 -0
  274. setiastro/saspro/mfdeconv_earlystop.py +71 -0
  275. setiastro/saspro/mfdeconvcudnn.py +3312 -0
  276. setiastro/saspro/mfdeconvsport.py +2459 -0
  277. setiastro/saspro/minorbodycatalog.py +567 -0
  278. setiastro/saspro/morphology.py +411 -0
  279. setiastro/saspro/multiscale_decomp.py +1751 -0
  280. setiastro/saspro/nbtorgb_stars.py +541 -0
  281. setiastro/saspro/numba_utils.py +3145 -0
  282. setiastro/saspro/numba_warmup.py +141 -0
  283. setiastro/saspro/ops/__init__.py +9 -0
  284. setiastro/saspro/ops/command_help_dialog.py +623 -0
  285. setiastro/saspro/ops/command_runner.py +217 -0
  286. setiastro/saspro/ops/commands.py +1594 -0
  287. setiastro/saspro/ops/script_editor.py +1105 -0
  288. setiastro/saspro/ops/scripts.py +1476 -0
  289. setiastro/saspro/ops/settings.py +637 -0
  290. setiastro/saspro/parallel_utils.py +554 -0
  291. setiastro/saspro/pedestal.py +121 -0
  292. setiastro/saspro/perfect_palette_picker.py +1105 -0
  293. setiastro/saspro/pipeline.py +110 -0
  294. setiastro/saspro/pixelmath.py +1604 -0
  295. setiastro/saspro/plate_solver.py +2480 -0
  296. setiastro/saspro/project_io.py +797 -0
  297. setiastro/saspro/psf_utils.py +136 -0
  298. setiastro/saspro/psf_viewer.py +631 -0
  299. setiastro/saspro/pyi_rthook_astroquery.py +95 -0
  300. setiastro/saspro/remove_green.py +331 -0
  301. setiastro/saspro/remove_stars.py +1599 -0
  302. setiastro/saspro/remove_stars_preset.py +446 -0
  303. setiastro/saspro/resources.py +570 -0
  304. setiastro/saspro/rgb_combination.py +208 -0
  305. setiastro/saspro/rgb_extract.py +19 -0
  306. setiastro/saspro/rgbalign.py +727 -0
  307. setiastro/saspro/runtime_imports.py +7 -0
  308. setiastro/saspro/runtime_torch.py +754 -0
  309. setiastro/saspro/save_options.py +73 -0
  310. setiastro/saspro/selective_color.py +1614 -0
  311. setiastro/saspro/sfcc.py +1530 -0
  312. setiastro/saspro/shortcuts.py +3125 -0
  313. setiastro/saspro/signature_insert.py +1106 -0
  314. setiastro/saspro/stacking_suite.py +19069 -0
  315. setiastro/saspro/star_alignment.py +7383 -0
  316. setiastro/saspro/star_alignment_preset.py +329 -0
  317. setiastro/saspro/star_metrics.py +49 -0
  318. setiastro/saspro/star_spikes.py +769 -0
  319. setiastro/saspro/star_stretch.py +542 -0
  320. setiastro/saspro/stat_stretch.py +554 -0
  321. setiastro/saspro/status_log_dock.py +78 -0
  322. setiastro/saspro/subwindow.py +3523 -0
  323. setiastro/saspro/supernovaasteroidhunter.py +1719 -0
  324. setiastro/saspro/swap_manager.py +134 -0
  325. setiastro/saspro/torch_backend.py +89 -0
  326. setiastro/saspro/torch_rejection.py +434 -0
  327. setiastro/saspro/translations/all_source_strings.json +4726 -0
  328. setiastro/saspro/translations/ar_translations.py +4096 -0
  329. setiastro/saspro/translations/de_translations.py +3728 -0
  330. setiastro/saspro/translations/es_translations.py +4169 -0
  331. setiastro/saspro/translations/fr_translations.py +4090 -0
  332. setiastro/saspro/translations/hi_translations.py +3803 -0
  333. setiastro/saspro/translations/integrate_translations.py +271 -0
  334. setiastro/saspro/translations/it_translations.py +4728 -0
  335. setiastro/saspro/translations/ja_translations.py +3834 -0
  336. setiastro/saspro/translations/pt_translations.py +3847 -0
  337. setiastro/saspro/translations/ru_translations.py +3082 -0
  338. setiastro/saspro/translations/saspro_ar.qm +0 -0
  339. setiastro/saspro/translations/saspro_ar.ts +16019 -0
  340. setiastro/saspro/translations/saspro_de.qm +0 -0
  341. setiastro/saspro/translations/saspro_de.ts +14548 -0
  342. setiastro/saspro/translations/saspro_es.qm +0 -0
  343. setiastro/saspro/translations/saspro_es.ts +16202 -0
  344. setiastro/saspro/translations/saspro_fr.qm +0 -0
  345. setiastro/saspro/translations/saspro_fr.ts +15870 -0
  346. setiastro/saspro/translations/saspro_hi.qm +0 -0
  347. setiastro/saspro/translations/saspro_hi.ts +14855 -0
  348. setiastro/saspro/translations/saspro_it.qm +0 -0
  349. setiastro/saspro/translations/saspro_it.ts +19046 -0
  350. setiastro/saspro/translations/saspro_ja.qm +0 -0
  351. setiastro/saspro/translations/saspro_ja.ts +14980 -0
  352. setiastro/saspro/translations/saspro_pt.qm +0 -0
  353. setiastro/saspro/translations/saspro_pt.ts +15024 -0
  354. setiastro/saspro/translations/saspro_ru.qm +0 -0
  355. setiastro/saspro/translations/saspro_ru.ts +11835 -0
  356. setiastro/saspro/translations/saspro_sw.qm +0 -0
  357. setiastro/saspro/translations/saspro_sw.ts +15237 -0
  358. setiastro/saspro/translations/saspro_uk.qm +0 -0
  359. setiastro/saspro/translations/saspro_uk.ts +15248 -0
  360. setiastro/saspro/translations/saspro_zh.qm +0 -0
  361. setiastro/saspro/translations/saspro_zh.ts +15289 -0
  362. setiastro/saspro/translations/sw_translations.py +3897 -0
  363. setiastro/saspro/translations/uk_translations.py +3929 -0
  364. setiastro/saspro/translations/zh_translations.py +3910 -0
  365. setiastro/saspro/versioning.py +77 -0
  366. setiastro/saspro/view_bundle.py +1558 -0
  367. setiastro/saspro/wavescale_hdr.py +648 -0
  368. setiastro/saspro/wavescale_hdr_preset.py +101 -0
  369. setiastro/saspro/wavescalede.py +683 -0
  370. setiastro/saspro/wavescalede_preset.py +230 -0
  371. setiastro/saspro/wcs_update.py +374 -0
  372. setiastro/saspro/whitebalance.py +540 -0
  373. setiastro/saspro/widgets/__init__.py +48 -0
  374. setiastro/saspro/widgets/common_utilities.py +306 -0
  375. setiastro/saspro/widgets/graphics_views.py +122 -0
  376. setiastro/saspro/widgets/image_utils.py +518 -0
  377. setiastro/saspro/widgets/minigame/game.js +991 -0
  378. setiastro/saspro/widgets/minigame/index.html +53 -0
  379. setiastro/saspro/widgets/minigame/style.css +241 -0
  380. setiastro/saspro/widgets/preview_dialogs.py +280 -0
  381. setiastro/saspro/widgets/resource_monitor.py +313 -0
  382. setiastro/saspro/widgets/spinboxes.py +290 -0
  383. setiastro/saspro/widgets/themed_buttons.py +13 -0
  384. setiastro/saspro/widgets/wavelet_utils.py +331 -0
  385. setiastro/saspro/wimi.py +7367 -0
  386. setiastro/saspro/wims.py +588 -0
  387. setiastro/saspro/window_shelf.py +185 -0
  388. setiastro/saspro/xisf.py +1213 -0
  389. setiastrosuitepro-1.6.7.dist-info/METADATA +279 -0
  390. setiastrosuitepro-1.6.7.dist-info/RECORD +394 -0
  391. setiastrosuitepro-1.6.7.dist-info/WHEEL +4 -0
  392. setiastrosuitepro-1.6.7.dist-info/entry_points.txt +6 -0
  393. setiastrosuitepro-1.6.7.dist-info/licenses/LICENSE +674 -0
  394. setiastrosuitepro-1.6.7.dist-info/licenses/license.txt +2580 -0
@@ -0,0 +1,492 @@
1
+ # pro/halobgon.py
2
+ from __future__ import annotations
3
+ import numpy as np
4
+ import cv2
5
+ from typing import Optional
6
+
7
+ from PyQt6.QtCore import Qt, QTimer, QRectF
8
+ from PyQt6.QtGui import QImage, QPixmap, QIcon, QTransform, QPainter
9
+ from PyQt6.QtWidgets import (
10
+ QDialog, QVBoxLayout, QHBoxLayout, QGroupBox, QGridLayout, QLabel, QPushButton,
11
+ QSlider, QCheckBox, QComboBox, QGraphicsView, QGraphicsScene, QGraphicsPixmapItem,
12
+ QMessageBox, QWidget, QRadioButton
13
+ )
14
+
15
+ # -------- Optional numba utils (LUT in-place speedups) --------------------
16
+ try:
17
+ from setiastro.saspro.legacy.numba_utils import apply_lut_mono_inplace as _lut_mono_inplace
18
+ from setiastro.saspro.legacy.numba_utils import apply_lut_color_inplace as _lut_color_inplace
19
+ except Exception:
20
+ _lut_mono_inplace = None
21
+ _lut_color_inplace = None
22
+
23
+ from setiastro.saspro.widgets.themed_buttons import themed_toolbtn
24
+
25
+
26
+ # =============================================================================
27
+ # Helpers
28
+ # =============================================================================
29
+ def _as_rgb(a: np.ndarray) -> np.ndarray:
30
+ a = np.asarray(a, dtype=np.float32)
31
+ a = np.clip(a, 0.0, 1.0)
32
+ if a.ndim == 2:
33
+ a = np.repeat(a[..., None], 3, axis=2)
34
+ elif a.ndim == 3 and a.shape[2] == 1:
35
+ a = np.repeat(a, 3, axis=2)
36
+ else:
37
+ a = a[:, :, :3]
38
+ return a
39
+
40
+ def _qimage_from_rgb01(a: np.ndarray) -> QImage:
41
+ a = np.clip(a, 0, 1).astype(np.float32)
42
+ a8 = (a * 255.0).astype(np.uint8)
43
+ h, w = a8.shape[:2]
44
+ return QImage(a8.data, w, h, w*3, QImage.Format.Format_RGB888).copy()
45
+
46
+ def _maybe_get_mask(parent, ref_img: np.ndarray) -> Optional[np.ndarray]:
47
+ """Fetch an applied mask as float [0..1], broadcastable to ref_img."""
48
+ try:
49
+ mm = None
50
+ if hasattr(parent, "mask_manager"):
51
+ mm = parent.mask_manager
52
+ elif hasattr(parent, "image_manager") and getattr(parent.image_manager, "mask_manager", None):
53
+ mm = parent.image_manager.mask_manager
54
+ if mm is None:
55
+ return None
56
+ m = mm.get_applied_mask()
57
+ if m is None:
58
+ return None
59
+ m = np.asarray(m)
60
+ if m.dtype.kind in "ui":
61
+ m = m.astype(np.float32) / 255.0
62
+ m = np.clip(m, 0.0, 1.0)
63
+ if ref_img.ndim == 3 and m.ndim == 2:
64
+ m = m[..., None]
65
+ if m.shape[:2] != ref_img.shape[:2]:
66
+ return None
67
+ if ref_img.ndim == 3 and m.shape[-1] == 1:
68
+ m = np.repeat(m, ref_img.shape[2], axis=2)
69
+ return m
70
+ except Exception:
71
+ return None
72
+
73
+ # -------- LUTs (curves) ---------------------------------------------------
74
+ def _curve_lut(reduction_level: int) -> np.ndarray:
75
+ """
76
+ SASv2 used stronger darkening as level increases:
77
+ 0→γ=1.2, 1→1.5, 2→1.8, 3→2.2
78
+ """
79
+ gammas = [1.2, 1.5, 1.8, 2.2]
80
+ g = gammas[max(0, min(3, int(reduction_level)))]
81
+ x = np.linspace(0, 1, 256, dtype=np.float32)
82
+ y = np.power(x, g)
83
+ lut = np.clip((y * 255.0).round(), 0, 255).astype(np.uint8)
84
+ return lut
85
+
86
+ def _apply_curve_inplace(img01: np.ndarray, lut: np.ndarray) -> np.ndarray:
87
+ """
88
+ Apply 8-bit LUT to an [0..1] float image. We *always* go through cv2.LUT to
89
+ avoid any view/aliasing surprises. Returns img01 (modified in place).
90
+ """
91
+ u8 = (np.clip(img01, 0.0, 1.0) * 255.0).astype(np.uint8, copy=False)
92
+ mapped = cv2.LUT(u8, lut).astype(np.float32) / 255.0
93
+ np.copyto(img01, mapped)
94
+ return img01
95
+
96
+ # =============================================================================
97
+ # Core algorithm
98
+ # =============================================================================
99
+ def compute_halo_b_gon(image: np.ndarray, reduction_level: int = 0, is_linear: bool = False) -> np.ndarray:
100
+ """
101
+ Exact port of SASv2 (HaloProcessingThread.applyHaloReduction):
102
+ - operate in [0..1]
103
+ - optional gamma-domain pre-pass for linear data (x ** 1/5)
104
+ - lightness mask is built in 8-bit scale (divide by 255.0), then unsharp
105
+ - enhanced_mask = (1 - unsharp) - blur(unsharp) * (level * 0.33)
106
+ - cv2.multiply(image, enhanced_mask)
107
+ - per-level curves (gamma) via LUT: [1.2, 1.5, 1.8, 2.2]
108
+ Returns the SAME shape as input (2D stays 2D; RGB stays RGB; 1-chan stays 1-chan).
109
+ """
110
+ img = np.clip(np.asarray(image, dtype=np.float32), 0.0, 1.0)
111
+
112
+ # Work buffer (apply gamma-domain if linear)
113
+ work = img
114
+ if is_linear:
115
+ with np.errstate(invalid='ignore'):
116
+ work = np.power(np.clip(work, 0.0, 1.0), 1.0 / 5.0)
117
+
118
+ # --- Lightness mask (SASv2 did /255.0 even though image is [0..1]) ---
119
+ if work.ndim == 2 or (work.ndim == 3 and work.shape[2] == 1):
120
+ # treat as grayscale
121
+ light = work if work.ndim == 2 else work[..., 0]
122
+ light = (light.astype(np.float32)) / 255.0
123
+ else:
124
+ # RGB → gray, then scale to 8-bit range
125
+ light = cv2.cvtColor(work, cv2.COLOR_RGB2GRAY) / 255.0
126
+
127
+ blurred = cv2.GaussianBlur(light, (0, 0), sigmaX=2)
128
+ unsharp = cv2.addWeighted(light, 1.66, blurred, -0.66, 0.0)
129
+
130
+ # --- Enhanced mask (exact SASv2 order) ---
131
+ inv = 1.0 - unsharp
132
+ dup = cv2.GaussianBlur(unsharp, (0, 0), sigmaX=2)
133
+ scale = float(max(0, min(3, int(reduction_level)))) * 0.33
134
+ enhanced_mask = inv - dup * scale
135
+
136
+ # Match mask shape to image shape
137
+ if work.ndim == 3 and work.shape[2] == 3:
138
+ mask = np.repeat(enhanced_mask[:, :, None], 3, axis=2).astype(work.dtype, copy=False)
139
+ else:
140
+ mask = enhanced_mask.astype(work.dtype, copy=False)
141
+
142
+ if work.shape != mask.shape:
143
+ raise ValueError(f"Shape mismatch between image {work.shape} and enhanced_mask {mask.shape}")
144
+
145
+ # Multiply
146
+ masked = cv2.multiply(work, mask)
147
+
148
+ # Curves via LUT (gamma > 1 darkens), exactly SASv2 levels
149
+ gammas = [1.2, 1.5, 1.8, 2.2]
150
+ g = gammas[int(max(0, min(3, reduction_level)))]
151
+ lut = (np.clip((np.linspace(0, 1, 256, dtype=np.float32) ** g) * 255.0, 0, 255)).astype(np.uint8)
152
+
153
+ u8 = (np.clip(masked, 0.0, 1.0) * 255.0).astype(np.uint8, copy=False)
154
+ mapped = cv2.LUT(u8, lut).astype(np.float32) / 255.0
155
+
156
+ out = np.clip(mapped, 0.0, 1.0).astype(np.float32, copy=False)
157
+
158
+ # restore 1-channel shape if input was (H,W,1)
159
+ if img.ndim == 3 and img.shape[2] == 1 and out.ndim == 2:
160
+ out = out[:, :, None]
161
+
162
+ return out
163
+
164
+ # =============================================================================
165
+ # Headless apply
166
+ # =============================================================================
167
+ def apply_halo_b_gon_to_doc(parent, doc, preset: dict | None):
168
+ """
169
+ preset keys:
170
+ - reduction: int 0..3 (0=Extra Low, 1=Low, 2=Medium, 3=High) [default 0]
171
+ - linear: bool (operate in gamma domain) [default False]
172
+ """
173
+ if doc is None or getattr(doc, "image", None) is None:
174
+ raise RuntimeError("Document has no image.")
175
+
176
+ img = np.asarray(doc.image, dtype=np.float32)
177
+ lvl = int((preset or {}).get("reduction", 0))
178
+ lin = bool((preset or {}).get("linear", False))
179
+
180
+ base = _as_rgb(img) if img.ndim != 2 else img
181
+ out = compute_halo_b_gon(img, reduction_level=lvl, is_linear=lin)
182
+
183
+ # Blend with active mask if present
184
+ ref = _as_rgb(img)
185
+ m = _maybe_get_mask(parent, ref)
186
+ if m is not None:
187
+ out_rgb = _as_rgb(out)
188
+ blended = np.clip(out_rgb * m + ref * (1.0 - m), 0.0, 1.0)
189
+ # restore mono if needed
190
+ if out.ndim == 2 or (out.ndim == 3 and out.shape[2] == 1):
191
+ blended = np.mean(blended, axis=2, dtype=np.float32)
192
+ if out.ndim == 3 and out.shape[2] == 1:
193
+ blended = blended[:, :, None]
194
+ out = blended
195
+
196
+ out = np.clip(out, 0.0, 1.0).astype(np.float32, copy=False)
197
+
198
+ if hasattr(doc, "set_image"):
199
+ doc.set_image(out, step_name="Halo-B-Gon")
200
+ elif hasattr(doc, "apply_numpy"):
201
+ doc.apply_numpy(out, step_name="Halo-B-Gon")
202
+ else:
203
+ doc.image = out
204
+
205
+ # =============================================================================
206
+ # UI: dialog with preview, zoom/pan, fit, overwrite/new view
207
+ # =============================================================================
208
+ class _PreviewView(QGraphicsView):
209
+ def __init__(self, scene):
210
+ super().__init__(scene)
211
+ self.setAlignment(Qt.AlignmentFlag.AlignCenter)
212
+ # ✅ Use QPainter.RenderHint.* here
213
+ self.setRenderHints(
214
+ self.renderHints()
215
+ | QPainter.RenderHint.Antialiasing
216
+ | QPainter.RenderHint.SmoothPixmapTransform
217
+ )
218
+ self.setDragMode(QGraphicsView.DragMode.ScrollHandDrag)
219
+ self.setTransformationAnchor(QGraphicsView.ViewportAnchor.AnchorUnderMouse)
220
+ self._zoom = 1.0
221
+
222
+ def wheelEvent(self, e):
223
+ if e.modifiers() & Qt.KeyboardModifier.ControlModifier:
224
+ step = 1.15 if e.angleDelta().y() > 0 else 1/1.15
225
+ self.set_zoom(self._zoom * step)
226
+ e.accept(); return
227
+ super().wheelEvent(e)
228
+
229
+ def set_zoom(self, z):
230
+ z = max(0.1, min(10.0, float(z)))
231
+ self._zoom = z
232
+ self.setTransform(QTransform().scale(z, z))
233
+
234
+ def zoom_in(self): self.set_zoom(self._zoom * 1.15)
235
+ def zoom_out(self): self.set_zoom(self._zoom / 1.15)
236
+ def fit_to(self, rect: QRectF):
237
+ if rect.isEmpty(): return
238
+ self.fitInView(rect, Qt.AspectRatioMode.KeepAspectRatio)
239
+ self._zoom = 1.0
240
+
241
+ class HaloBGonDialogPro(QDialog):
242
+ """
243
+ Minimal, fast UI:
244
+ • Reduction level (0..3)
245
+ • Linear-data checkbox
246
+ • Live preview (debounced)
247
+ • Apply to: Overwrite active / Create new view
248
+ """
249
+ def __init__(self, parent, doc, icon: Optional[QIcon] = None):
250
+ super().__init__(parent)
251
+ self.setWindowTitle("Halo-B-Gon")
252
+ self.setWindowFlag(Qt.WindowType.Window, True)
253
+ self.setWindowModality(Qt.WindowModality.NonModal)
254
+ self.setModal(False)
255
+ try:
256
+ self.setAttribute(Qt.WidgetAttribute.WA_DeleteOnClose, True)
257
+ except Exception:
258
+ pass # older PyQt6 versions
259
+ if icon:
260
+ try: self.setWindowIcon(icon)
261
+ except Exception as e:
262
+ import logging
263
+ logging.debug(f"Exception suppressed: {type(e).__name__}: {e}")
264
+
265
+ self.parent_ref = parent
266
+ self.doc = doc
267
+ self.orig = np.clip(np.asarray(doc.image, dtype=np.float32), 0.0, 1.0)
268
+
269
+ # Display base is RGB
270
+ disp = _as_rgb(self.orig)
271
+ self._disp_base = disp
272
+
273
+ # ---- UI ----
274
+ v = QVBoxLayout(self)
275
+
276
+ # Controls
277
+ grp = QGroupBox("Halo-B-Gon Parameters")
278
+ grid = QGridLayout(grp)
279
+
280
+ grid.addWidget(QLabel("Reduction:"), 0, 0)
281
+ self.sl = QSlider(Qt.Orientation.Horizontal); self.sl.setRange(0, 3); self.sl.setValue(0)
282
+ self.lbl = QLabel("Extra Low")
283
+ def _lab(v):
284
+ self.lbl.setText(["Extra Low","Low","Medium","High"][int(v)])
285
+ self.sl.valueChanged.connect(_lab); _lab(0)
286
+ self.sl.valueChanged.connect(self._debounce)
287
+ grid.addWidget(self.sl, 0, 1); grid.addWidget(self.lbl, 0, 2)
288
+
289
+ self.cb_linear = QCheckBox("Linear data"); self.cb_linear.setChecked(False)
290
+ self.cb_linear.toggled.connect(self._debounce)
291
+ grid.addWidget(self.cb_linear, 1, 1)
292
+
293
+ # Apply target
294
+ grid.addWidget(QLabel("Apply to:"), 2, 0)
295
+ self.cmb_target = QComboBox(); self.cmb_target.addItems(["Overwrite active view", "Create new view"])
296
+ grid.addWidget(self.cmb_target, 2, 1, 1, 2)
297
+
298
+ v.addWidget(grp)
299
+
300
+ # Preview
301
+ self.scene = QGraphicsScene(self)
302
+ self.view = _PreviewView(self.scene)
303
+ self.pix = QGraphicsPixmapItem()
304
+ self.scene.addItem(self.pix)
305
+ v.addWidget(self.view, 1)
306
+
307
+ # Buttons (themed)
308
+ row = QHBoxLayout()
309
+ row.addWidget(QLabel("Zoom: Ctrl+Wheel"))
310
+
311
+ b_minus = themed_toolbtn("zoom-out", "Zoom Out")
312
+ b_plus = themed_toolbtn("zoom-in", "Zoom In")
313
+ b_fit = themed_toolbtn("zoom-fit-best", "Fit to View")
314
+
315
+ b_minus.clicked.connect(self.view.zoom_out)
316
+ b_plus .clicked.connect(self.view.zoom_in)
317
+ b_fit .clicked.connect(lambda: self.view.fit_to(self.scene.itemsBoundingRect()))
318
+
319
+ row.addWidget(b_minus)
320
+ row.addWidget(b_plus)
321
+ row.addWidget(b_fit)
322
+ row.addStretch(1)
323
+ v.addLayout(row)
324
+
325
+
326
+ row2 = QHBoxLayout()
327
+ b_apply = QPushButton("Apply"); b_apply.clicked.connect(self._apply)
328
+ b_reset = QPushButton("Reset"); b_reset.clicked.connect(self._reset)
329
+ b_cancel= QPushButton("Cancel"); b_cancel.clicked.connect(self.reject)
330
+ row2.addStretch(1); row2.addWidget(b_apply); row2.addWidget(b_reset); row2.addWidget(b_cancel)
331
+ v.addLayout(row2)
332
+
333
+ self._timer = QTimer(self); self._timer.setSingleShot(True); self._timer.timeout.connect(self._update_preview)
334
+
335
+ self._set_pix(self._disp_base)
336
+ self._update_preview()
337
+ self.resize(900, 620)
338
+
339
+ def _debounce(self): self._timer.start(180)
340
+
341
+ def _set_pix(self, rgb):
342
+ q = _qimage_from_rgb01(rgb)
343
+ self.pix.setPixmap(QPixmap.fromImage(q))
344
+ self.view.setSceneRect(self.pix.boundingRect())
345
+
346
+ def _params(self):
347
+ return int(self.sl.value()), bool(self.cb_linear.isChecked())
348
+
349
+ def _update_preview(self):
350
+ lvl, lin = self._params()
351
+ try:
352
+ out = compute_halo_b_gon(self.orig, reduction_level=lvl, is_linear=lin)
353
+ # Display only: convert mono → RGB for the pixmap
354
+ self._set_pix(_as_rgb(out))
355
+ except Exception as e:
356
+ QMessageBox.warning(self, "Halo-B-Gon", f"Preview failed:\n{e}")
357
+
358
+ def _apply_overwrite(self, out: np.ndarray):
359
+ if hasattr(self.doc, "set_image"):
360
+ self.doc.set_image(out, step_name="Halo-B-Gon")
361
+ elif hasattr(self.doc, "apply_numpy"):
362
+ self.doc.apply_numpy(out, step_name="Halo-B-Gon")
363
+ else:
364
+ self.doc.image = out
365
+
366
+ def _apply(self):
367
+ lvl, lin = self._params()
368
+ try:
369
+ out = compute_halo_b_gon(self.orig, reduction_level=lvl, is_linear=lin)
370
+
371
+ # Mask blend (same as your preview path)
372
+ m = _maybe_get_mask(self.parent_ref, np.asarray(self.orig, dtype=np.float32))
373
+ if m is not None:
374
+ if self.orig.ndim == 2 and m.ndim == 3:
375
+ m = m[..., 0]
376
+ if self.orig.ndim == 3 and self.orig.shape[2] == 1 and m.ndim == 2:
377
+ m = m[:, :, None]
378
+ out = np.clip(out * m + self.orig * (1.0 - m), 0.0, 1.0)
379
+
380
+ out = np.clip(out, 0.0, 1.0).astype(np.float32, copy=False)
381
+
382
+ # ── Register as last_headless_command for replay ──────────
383
+ try:
384
+ main = self.parent()
385
+ if main is not None:
386
+ preset = {
387
+ "reduction": int(lvl),
388
+ "linear": bool(lin),
389
+ }
390
+ payload = {
391
+ "command_id": "halo_b_gon",
392
+ "preset": dict(preset),
393
+ }
394
+ setattr(main, "_last_headless_command", payload)
395
+
396
+ # optional log
397
+ try:
398
+ if hasattr(main, "_log"):
399
+ main._log(
400
+ f"[Replay] Registered Halo-B-Gon as last action "
401
+ f"(level={int(lvl)}, linear={bool(lin)})"
402
+ )
403
+ except Exception:
404
+ pass
405
+ except Exception:
406
+ # don't break apply if replay wiring fails
407
+ pass
408
+ # ───────────────────────────────────────────────────────────
409
+
410
+ # If user chose "Create new view", go through DocManager so the UI spawns the window.
411
+ create_new = (self.cmb_target.currentIndex() == 1)
412
+
413
+ if create_new:
414
+ # Try to find a DocManager on the dialog's parent (preferred) or parent_ref.
415
+ dm = getattr(self.parent(), "doc_manager", None)
416
+ if dm is None:
417
+ dm = getattr(self.parent_ref, "doc_manager", None)
418
+
419
+ if dm is not None:
420
+ # Carry forward useful metadata; let DocManager’s signal create the view.
421
+ title = self.doc.display_name() if hasattr(self.doc, "display_name") else "Image"
422
+ meta = dict(getattr(self.doc, "metadata", {}) or {})
423
+ # Ensure expected fields exist
424
+ try:
425
+ meta.setdefault("bit_depth", "32-bit floating point")
426
+ if "is_mono" not in meta:
427
+ meta["is_mono"] = (out.ndim == 2 or (out.ndim == 3 and out.shape[2] == 1))
428
+ except Exception:
429
+ pass
430
+
431
+ new_doc = dm.create_document(out.copy(), metadata=meta, name=f"{title} [Halo-B-Gon]")
432
+ try:
433
+ dm.set_active_document(new_doc)
434
+ except Exception:
435
+ pass
436
+
437
+ # Dialog stays open - refresh document for next operation
438
+ self._refresh_document_from_active()
439
+ return
440
+ else:
441
+ # Fallback: try legacy spawner if present; else warn and overwrite.
442
+ spawner = getattr(self.parent(), "_spawn_new_view_from_numpy", None)
443
+ if spawner is None:
444
+ spawner = getattr(self.parent_ref, "_spawn_new_view_from_numpy", None)
445
+ if callable(spawner):
446
+ title = self.doc.display_name() if hasattr(self.doc, "display_name") else "Image"
447
+ spawner(out, f"{title} [Halo-B-Gon]")
448
+ # Dialog stays open - refresh document for next operation
449
+ self._refresh_document_from_active()
450
+ return
451
+ else:
452
+ QMessageBox.warning(
453
+ self, "Halo-B-Gon",
454
+ "Could not find DocManager or window spawner; applying to the active view instead."
455
+ )
456
+ # fall through to overwrite
457
+
458
+ # Overwrite current (original behavior)
459
+ self._apply_overwrite(out)
460
+ # Dialog stays open - refresh document for next operation
461
+ self._refresh_document_from_active()
462
+
463
+ except Exception as e:
464
+ QMessageBox.critical(self, "Halo-B-Gon", f"Failed to apply:\n{e}")
465
+
466
+ def _refresh_document_from_active(self):
467
+ """
468
+ Refresh the dialog's document reference to the currently active document.
469
+ This allows reusing the same dialog on different images.
470
+ """
471
+ try:
472
+ main = self.parent()
473
+ if main and hasattr(main, "_active_doc"):
474
+ new_doc = main._active_doc()
475
+ if new_doc is not None and new_doc is not self.doc:
476
+ self.doc = new_doc
477
+ # Refresh preview for new document
478
+ self.orig = np.clip(np.asarray(new_doc.image, dtype=np.float32), 0.0, 1.0)
479
+ disp = self.orig
480
+ if disp.ndim == 2: disp = disp[..., None].repeat(3, axis=2)
481
+ elif disp.ndim == 3 and disp.shape[2] == 1: disp = disp.repeat(3, axis=2)
482
+ self._disp_base = disp
483
+ self._update_preview()
484
+ except Exception:
485
+ pass
486
+
487
+
488
+ def _reset(self):
489
+ self.sl.setValue(0)
490
+ self.cb_linear.setChecked(False)
491
+ self._set_pix(self._disp_base)
492
+ self._update_preview()