graxpert 3.2.0a0.dev8__tar.gz → 3.2.0a2__tar.gz

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 (86) hide show
  1. {graxpert-3.2.0a0.dev8 → graxpert-3.2.0a2}/PKG-INFO +1 -1
  2. graxpert-3.2.0a2/graxpert/__init__.py +3 -0
  3. {graxpert-3.2.0a0.dev8 → graxpert-3.2.0a2}/graxpert/ai_model_handling.py +1 -1
  4. {graxpert-3.2.0a0.dev8 → graxpert-3.2.0a2}/graxpert/application/app.py +18 -12
  5. {graxpert-3.2.0a0.dev8 → graxpert-3.2.0a2}/graxpert/cmdline_tools.py +63 -110
  6. {graxpert-3.2.0a0.dev8 → graxpert-3.2.0a2}/graxpert/main.py +99 -44
  7. graxpert-3.2.0a2/graxpert/progress.py +51 -0
  8. {graxpert-3.2.0a0.dev8 → graxpert-3.2.0a2}/graxpert/ui/loadingframe.py +0 -51
  9. graxpert-3.2.0a2/graxpert/version.py +2 -0
  10. graxpert-3.2.0a2/graxpert/version.py.bak +2 -0
  11. {graxpert-3.2.0a0.dev8 → graxpert-3.2.0a2}/graxpert.egg-info/PKG-INFO +1 -1
  12. {graxpert-3.2.0a0.dev8 → graxpert-3.2.0a2}/graxpert.egg-info/SOURCES.txt +1 -0
  13. graxpert-3.2.0a0.dev8/graxpert/ui/__init__.py +0 -1
  14. graxpert-3.2.0a0.dev8/graxpert/version.py +0 -2
  15. graxpert-3.2.0a0.dev8/graxpert/version.py.bak +0 -2
  16. {graxpert-3.2.0a0.dev8 → graxpert-3.2.0a2}/MANIFEST.in +0 -0
  17. {graxpert-3.2.0a0.dev8 → graxpert-3.2.0a2}/README.md +0 -0
  18. {graxpert-3.2.0a0.dev8 → graxpert-3.2.0a2}/graxpert/AstroImageRepository.py +0 -0
  19. {graxpert-3.2.0a0.dev8 → graxpert-3.2.0a2}/graxpert/app_state.py +0 -0
  20. {graxpert-3.2.0a0.dev8 → graxpert-3.2.0a2}/graxpert/application/__init__.py +0 -0
  21. {graxpert-3.2.0a0.dev8 → graxpert-3.2.0a2}/graxpert/application/app_events.py +0 -0
  22. {graxpert-3.2.0a0.dev8 → graxpert-3.2.0a2}/graxpert/application/eventbus.py +0 -0
  23. {graxpert-3.2.0a0.dev8 → graxpert-3.2.0a2}/graxpert/astroimage.py +0 -0
  24. {graxpert-3.2.0a0.dev8 → graxpert-3.2.0a2}/graxpert/background_extraction.py +0 -0
  25. {graxpert-3.2.0a0.dev8 → graxpert-3.2.0a2}/graxpert/background_flood_selection.py +0 -0
  26. {graxpert-3.2.0a0.dev8 → graxpert-3.2.0a2}/graxpert/background_grid_selection.py +0 -0
  27. {graxpert-3.2.0a0.dev8 → graxpert-3.2.0a2}/graxpert/commands.py +0 -0
  28. {graxpert-3.2.0a0.dev8 → graxpert-3.2.0a2}/graxpert/deconvolution.py +0 -0
  29. {graxpert-3.2.0a0.dev8 → graxpert-3.2.0a2}/graxpert/denoising.py +0 -0
  30. {graxpert-3.2.0a0.dev8 → graxpert-3.2.0a2}/graxpert/grid_utils.py +0 -0
  31. {graxpert-3.2.0a0.dev8 → graxpert-3.2.0a2}/graxpert/img/GraXpert_LOGO_Hauptvariante.png +0 -0
  32. {graxpert-3.2.0a0.dev8 → graxpert-3.2.0a2}/graxpert/img/Icon.png +0 -0
  33. {graxpert-3.2.0a0.dev8 → graxpert-3.2.0a2}/graxpert/img/LDN1235_original.jpg +0 -0
  34. {graxpert-3.2.0a0.dev8 → graxpert-3.2.0a2}/graxpert/img/LDN1235_processed.jpg +0 -0
  35. {graxpert-3.2.0a0.dev8 → graxpert-3.2.0a2}/graxpert/img/__init__.py +0 -0
  36. {graxpert-3.2.0a0.dev8 → graxpert-3.2.0a2}/graxpert/img/gfx_numbers.png +0 -0
  37. {graxpert-3.2.0a0.dev8 → graxpert-3.2.0a2}/graxpert/img/gfx_numbers.svg +0 -0
  38. {graxpert-3.2.0a0.dev8 → graxpert-3.2.0a2}/graxpert/img/graXpert_Startbadge_Umbriel.png +0 -0
  39. {graxpert-3.2.0a0.dev8 → graxpert-3.2.0a2}/graxpert/img/hourglass.png +0 -0
  40. {graxpert-3.2.0a0.dev8 → graxpert-3.2.0a2}/graxpert/locales/__init__.py +0 -0
  41. {graxpert-3.2.0a0.dev8 → graxpert-3.2.0a2}/graxpert/locales/base.pot +0 -0
  42. {graxpert-3.2.0a0.dev8 → graxpert-3.2.0a2}/graxpert/locales/de_DE/LC_MESSAGES/base.mo +0 -0
  43. {graxpert-3.2.0a0.dev8 → graxpert-3.2.0a2}/graxpert/locales/de_DE/LC_MESSAGES/base.po +0 -0
  44. {graxpert-3.2.0a0.dev8 → graxpert-3.2.0a2}/graxpert/localization.py +0 -0
  45. {graxpert-3.2.0a0.dev8 → graxpert-3.2.0a2}/graxpert/mp_logging.py +0 -0
  46. {graxpert-3.2.0a0.dev8 → graxpert-3.2.0a2}/graxpert/parallel_processing.py +0 -0
  47. {graxpert-3.2.0a0.dev8 → graxpert-3.2.0a2}/graxpert/preferences.py +0 -0
  48. {graxpert-3.2.0a0.dev8 → graxpert-3.2.0a2}/graxpert/radialbasisinterpolation.py +0 -0
  49. {graxpert-3.2.0a0.dev8 → graxpert-3.2.0a2}/graxpert/resource_utils.py +0 -0
  50. {graxpert-3.2.0a0.dev8 → graxpert-3.2.0a2}/graxpert/s3_secrets.py +0 -0
  51. {graxpert-3.2.0a0.dev8 → graxpert-3.2.0a2}/graxpert/skyall.py +0 -0
  52. {graxpert-3.2.0a0.dev8 → graxpert-3.2.0a2}/graxpert/stretch.py +0 -0
  53. {graxpert-3.2.0a0.dev8 → graxpert-3.2.0a2}/graxpert/theme/__init__.py +0 -0
  54. {graxpert-3.2.0a0.dev8 → graxpert-3.2.0a2}/graxpert/theme/graxpert-dark-blue.json +0 -0
  55. {graxpert-3.2.0a0.dev8/graxpert → graxpert-3.2.0a2/graxpert/ui}/__init__.py +0 -0
  56. {graxpert-3.2.0a0.dev8 → graxpert-3.2.0a2}/graxpert/ui/application_frame.py +0 -0
  57. {graxpert-3.2.0a0.dev8 → graxpert-3.2.0a2}/graxpert/ui/canvas.py +0 -0
  58. {graxpert-3.2.0a0.dev8 → graxpert-3.2.0a2}/graxpert/ui/left_menu.py +0 -0
  59. {graxpert-3.2.0a0.dev8 → graxpert-3.2.0a2}/graxpert/ui/right_menu.py +0 -0
  60. {graxpert-3.2.0a0.dev8 → graxpert-3.2.0a2}/graxpert/ui/statusbar.py +0 -0
  61. {graxpert-3.2.0a0.dev8 → graxpert-3.2.0a2}/graxpert/ui/styling.py +0 -0
  62. {graxpert-3.2.0a0.dev8 → graxpert-3.2.0a2}/graxpert/ui/tooltip.py +0 -0
  63. {graxpert-3.2.0a0.dev8 → graxpert-3.2.0a2}/graxpert/ui/ui_events.py +0 -0
  64. {graxpert-3.2.0a0.dev8 → graxpert-3.2.0a2}/graxpert/ui/widgets.py +0 -0
  65. {graxpert-3.2.0a0.dev8 → graxpert-3.2.0a2}/graxpert/ui_scaling.py +0 -0
  66. {graxpert-3.2.0a0.dev8 → graxpert-3.2.0a2}/graxpert.egg-info/dependency_links.txt +0 -0
  67. {graxpert-3.2.0a0.dev8 → graxpert-3.2.0a2}/graxpert.egg-info/entry_points.txt +0 -0
  68. {graxpert-3.2.0a0.dev8 → graxpert-3.2.0a2}/graxpert.egg-info/requires.txt +0 -0
  69. {graxpert-3.2.0a0.dev8 → graxpert-3.2.0a2}/graxpert.egg-info/top_level.txt +0 -0
  70. {graxpert-3.2.0a0.dev8 → graxpert-3.2.0a2}/img/Icon.icns +0 -0
  71. {graxpert-3.2.0a0.dev8 → graxpert-3.2.0a2}/img/Icon.ico +0 -0
  72. {graxpert-3.2.0a0.dev8 → graxpert-3.2.0a2}/img/Icon.png +0 -0
  73. {graxpert-3.2.0a0.dev8 → graxpert-3.2.0a2}/img/NGC7000_original.jpg +0 -0
  74. {graxpert-3.2.0a0.dev8 → graxpert-3.2.0a2}/img/NGC7000_processed.jpg +0 -0
  75. {graxpert-3.2.0a0.dev8 → graxpert-3.2.0a2}/img/graXpert_Startbadge_Ariel.png +0 -0
  76. {graxpert-3.2.0a0.dev8 → graxpert-3.2.0a2}/img/graXpert_Startbadge_Ariel.svg +0 -0
  77. {graxpert-3.2.0a0.dev8 → graxpert-3.2.0a2}/img/graXpert_Startbadge_Dione.png +0 -0
  78. {graxpert-3.2.0a0.dev8 → graxpert-3.2.0a2}/img/graXpert_Startbadge_Dione.svg +0 -0
  79. {graxpert-3.2.0a0.dev8 → graxpert-3.2.0a2}/img/graXpert_Startbadge_Tethys.png +0 -0
  80. {graxpert-3.2.0a0.dev8 → graxpert-3.2.0a2}/img/graXpert_Startbadge_Tethys.svg +0 -0
  81. {graxpert-3.2.0a0.dev8 → graxpert-3.2.0a2}/img/graXpert_Startbadge_Umbriel.png +0 -0
  82. {graxpert-3.2.0a0.dev8 → graxpert-3.2.0a2}/img/graXpert_Startbadge_Umbriel.svg +0 -0
  83. {graxpert-3.2.0a0.dev8 → graxpert-3.2.0a2}/pyproject.toml +0 -0
  84. {graxpert-3.2.0a0.dev8 → graxpert-3.2.0a2}/requirements.txt +0 -0
  85. {graxpert-3.2.0a0.dev8 → graxpert-3.2.0a2}/setup.cfg +0 -0
  86. {graxpert-3.2.0a0.dev8 → graxpert-3.2.0a2}/setup.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: graxpert
3
- Version: 3.2.0a0.dev8
3
+ Version: 3.2.0a2
4
4
  Summary: GraXpert is an astronomical image processing program for extracting and removing gradients in the background of your astrophotos
5
5
  Home-page: https://graxpert.com
6
6
  Author: GraXpert Development Team
@@ -0,0 +1,3 @@
1
+ from graxpert.main import api_run
2
+
3
+ __all__ = ['api_run']
@@ -18,7 +18,7 @@ except Exception as e:
18
18
  logging.exception(e)
19
19
  client = None
20
20
 
21
- from graxpert.ui.loadingframe import DynamicProgressThread
21
+ from graxpert.progress import DynamicProgressThread
22
22
 
23
23
  ai_models_dir = os.path.join(user_data_dir(appname="GraXpert"), "ai-models")
24
24
  bge_ai_models_dir = os.path.join(user_data_dir(appname="GraXpert"), "bge-ai-models")
@@ -29,7 +29,10 @@ from graxpert.mp_logging import logfile_name
29
29
  from graxpert.preferences import fitsheader_2_app_state, load_preferences, prefs_2_app_state
30
30
  from graxpert.s3_secrets import bge_bucket_name, deconvolution_object_bucket_name, deconvolution_stars_bucket_name, denoise_bucket_name
31
31
  from graxpert.stretch import StretchParameters, stretch_all
32
- from graxpert.ui.loadingframe import DynamicProgressThread
32
+ from graxpert.progress import DynamicProgressThread
33
+
34
+ def callback(p):
35
+ eventbus.emit(AppEvents.AI_DOWNLOAD_PROGRESS, {"progress": p})
33
36
 
34
37
 
35
38
  class GraXpert:
@@ -674,8 +677,20 @@ class GraXpert:
674
677
  else:
675
678
  eventbus.emit(AppEvents.AI_DOWNLOAD_BEGIN)
676
679
 
677
- def callback(p):
678
- eventbus.emit(AppEvents.AI_DOWNLOAD_PROGRESS, {"progress": p})
680
+ download_version(bge_ai_models_dir, bge_bucket_name, self.prefs.bge_ai_version, progress=callback)
681
+ eventbus.emit(AppEvents.AI_DOWNLOAD_END)
682
+ return True
683
+
684
+ def validate_bge_ai_installation(self):
685
+ if self.prefs.bge_ai_version is None or self.prefs.bge_ai_version == "None":
686
+ messagebox.showerror("Error", _("No Background Extraction AI-Model selected. Please select one from the Advanced panel on the right."))
687
+ return False
688
+
689
+ if not validate_local_version(bge_ai_models_dir, self.prefs.bge_ai_version):
690
+ if not messagebox.askyesno(_("Install AI-Model?"), _("Selected Background Extraction AI-Model is not installed. Should I download it now?")):
691
+ return False
692
+ else:
693
+ eventbus.emit(AppEvents.AI_DOWNLOAD_BEGIN)
679
694
 
680
695
  download_version(bge_ai_models_dir, bge_bucket_name, self.prefs.bge_ai_version, progress=callback)
681
696
  eventbus.emit(AppEvents.AI_DOWNLOAD_END)
@@ -695,9 +710,6 @@ class GraXpert:
695
710
  else:
696
711
  eventbus.emit(AppEvents.AI_DOWNLOAD_BEGIN)
697
712
 
698
- def callback(p):
699
- eventbus.emit(AppEvents.AI_DOWNLOAD_PROGRESS, {"progress": p})
700
-
701
713
  download_version(deconvolution_object_ai_models_dir, deconvolution_object_bucket_name, self.prefs.deconvolution_object_ai_version, progress=callback)
702
714
  eventbus.emit(AppEvents.AI_DOWNLOAD_END)
703
715
  return True
@@ -712,9 +724,6 @@ class GraXpert:
712
724
  else:
713
725
  eventbus.emit(AppEvents.AI_DOWNLOAD_BEGIN)
714
726
 
715
- def callback(p):
716
- eventbus.emit(AppEvents.AI_DOWNLOAD_PROGRESS, {"progress": p})
717
-
718
727
  download_version(deconvolution_stars_ai_models_dir, deconvolution_stars_bucket_name, self.prefs.deconvolution_stars_ai_version, progress=callback)
719
728
  eventbus.emit(AppEvents.AI_DOWNLOAD_END)
720
729
  return True
@@ -730,9 +739,6 @@ class GraXpert:
730
739
  else:
731
740
  eventbus.emit(AppEvents.AI_DOWNLOAD_BEGIN)
732
741
 
733
- def callback(p):
734
- eventbus.emit(AppEvents.AI_DOWNLOAD_PROGRESS, {"progress": p})
735
-
736
742
  download_version(denoise_ai_models_dir, denoise_bucket_name, self.prefs.denoise_ai_version, progress=callback)
737
743
  eventbus.emit(AppEvents.AI_DOWNLOAD_END)
738
744
  return True
@@ -49,7 +49,9 @@ class CmdlineToolBase:
49
49
  def get_save_path(self):
50
50
  if self.args.output is not None:
51
51
  base_path = os.path.dirname(self.args.filename)
52
- output_file_name = self.args.output + self.get_output_file_ending()
52
+ output_file_name = self.args.output
53
+ if not os.path.splitext(output_file_name)[1]: # if output file already has an extension, just use that
54
+ output_file_name += self.get_output_file_ending()
53
55
  return os.path.join(base_path, output_file_name)
54
56
  else:
55
57
  return os.path.splitext(self.args.filename)[0] + "_GraXpert" + self.get_output_file_ending()
@@ -59,7 +61,7 @@ class BGECmdlineTool(CmdlineToolBase):
59
61
  def __init__(self, args):
60
62
  super().__init__(args)
61
63
 
62
- def execute(self):
64
+ def execute(self, json_prefs: dict = {}):
63
65
  astro_Image = AstroImage(do_update_display=False)
64
66
  astro_Image.set_from_file(self.args.filename, None, None)
65
67
 
@@ -71,43 +73,30 @@ class BGECmdlineTool(CmdlineToolBase):
71
73
 
72
74
  downscale_factor = 1
73
75
 
74
- if self.args.preferences_file is not None:
75
- preferences = Prefs()
76
- preferences.interpol_type_option = "AI"
77
- try:
78
- preferences_file = os.path.abspath(self.args.preferences_file)
79
- if os.path.isfile(preferences_file):
80
- with open(preferences_file, "r") as f:
81
- json_prefs = json.load(f)
82
- if "background_points" in json_prefs:
83
- preferences.background_points = json_prefs["background_points"]
84
- if "RBF_kernel" in json_prefs:
85
- preferences.RBF_kernel = json_prefs["RBF_kernel"]
86
- if "interpol_type_option" in json_prefs:
87
- preferences.interpol_type_option = json_prefs["interpol_type_option"]
88
- if "smoothing_option" in json_prefs:
89
- preferences.smoothing_option = json_prefs["smoothing_option"]
90
- if "sample_size" in json_prefs:
91
- preferences.sample_size = json_prefs["sample_size"]
92
- if "spline_order" in json_prefs:
93
- preferences.spline_order = json_prefs["spline_order"]
94
- if "corr_type" in json_prefs:
95
- preferences.corr_type = json_prefs["corr_type"]
96
- if "ai_version" in json_prefs:
97
- preferences.ai_version = json_prefs["ai_version"]
98
- if "ai_gpu_acceleration" in json_prefs:
99
- preferences.ai_gpu_acceleration = json_prefs["ai_gpu_acceleration"]
100
-
101
- if preferences.interpol_type_option == "Kriging" or preferences.interpol_type_option == "RBF":
102
- downscale_factor = 4
103
-
104
- except Exception as e:
105
- logging.exception(e)
106
- logging.shutdown()
107
- sys.exit(1)
108
- else:
109
- preferences = Prefs()
110
- preferences.interpol_type_option = "AI"
76
+ preferences = Prefs()
77
+ preferences.interpol_type_option = "AI"
78
+
79
+ if "background_points" in json_prefs:
80
+ preferences.background_points = json_prefs["background_points"]
81
+ if "RBF_kernel" in json_prefs:
82
+ preferences.RBF_kernel = json_prefs["RBF_kernel"]
83
+ if "interpol_type_option" in json_prefs:
84
+ preferences.interpol_type_option = json_prefs["interpol_type_option"]
85
+ if "smoothing_option" in json_prefs:
86
+ preferences.smoothing_option = json_prefs["smoothing_option"]
87
+ if "sample_size" in json_prefs:
88
+ preferences.sample_size = json_prefs["sample_size"]
89
+ if "spline_order" in json_prefs:
90
+ preferences.spline_order = json_prefs["spline_order"]
91
+ if "corr_type" in json_prefs:
92
+ preferences.corr_type = json_prefs["corr_type"]
93
+ if "ai_version" in json_prefs:
94
+ preferences.bge_ai_version = json_prefs["ai_version"]
95
+ if "ai_gpu_acceleration" in json_prefs:
96
+ preferences.ai_gpu_acceleration = json_prefs["ai_gpu_acceleration"]
97
+
98
+ if preferences.interpol_type_option == "Kriging" or preferences.interpol_type_option == "RBF":
99
+ downscale_factor = 4
111
100
 
112
101
  if self.args.smoothing is not None:
113
102
  preferences.smoothing_option = self.args.smoothing
@@ -220,7 +209,7 @@ class DenoiseCmdlineTool(CmdlineToolBase):
220
209
  super().__init__(args)
221
210
  self.args = args
222
211
 
223
- def execute(self):
212
+ def execute(self, json_prefs: dict = {}):
224
213
  astro_Image = AstroImage(do_update_display=False)
225
214
  astro_Image.set_from_file(self.args.filename, None, None)
226
215
 
@@ -228,28 +217,16 @@ class DenoiseCmdlineTool(CmdlineToolBase):
228
217
 
229
218
  processed_Astro_Image.fits_header = astro_Image.fits_header
230
219
 
231
- if self.args.preferences_file is not None:
232
- preferences = Prefs()
233
- try:
234
- preferences_file = os.path.abspath(self.args.preferences_file)
235
- if os.path.isfile(preferences_file):
236
- with open(preferences_file, "r") as f:
237
- json_prefs = json.load(f)
238
- if "ai_version" in json_prefs:
239
- preferences.ai_version = json_prefs["ai_version"]
240
- if "denoise_strength" in json_prefs:
241
- preferences.denoise_strength = json_prefs["denoise_strength"]
242
- if "ai_batch_size" in json_prefs:
243
- preferences.ai_batch_size = json_prefs["ai_batch_size"]
244
- if "ai_gpu_acceleration" in json_prefs:
245
- preferences.ai_gpu_acceleration = json_prefs["ai_gpu_acceleration"]
220
+ preferences = Prefs()
246
221
 
247
- except Exception as e:
248
- logging.exception(e)
249
- logging.shutdown()
250
- sys.exit(1)
251
- else:
252
- preferences = Prefs()
222
+ if "ai_version" in json_prefs:
223
+ preferences.ai_version = json_prefs["ai_version"]
224
+ if "denoise_strength" in json_prefs:
225
+ preferences.denoise_strength = json_prefs["denoise_strength"]
226
+ if "ai_batch_size" in json_prefs:
227
+ preferences.ai_batch_size = json_prefs["ai_batch_size"]
228
+ if "ai_gpu_acceleration" in json_prefs:
229
+ preferences.ai_gpu_acceleration = json_prefs["ai_gpu_acceleration"]
253
230
 
254
231
  if self.args.denoise_strength is not None:
255
232
  preferences.denoise_strength = self.args.denoise_strength
@@ -320,7 +297,7 @@ class DeconvObjCmdlineTool(CmdlineToolBase):
320
297
  super().__init__(args)
321
298
  self.args = args
322
299
 
323
- def execute(self):
300
+ def execute(self, json_prefs: dict = {}):
324
301
  astro_Image = AstroImage(do_update_display=False)
325
302
  astro_Image.set_from_file(self.args.filename, None, None)
326
303
 
@@ -328,30 +305,18 @@ class DeconvObjCmdlineTool(CmdlineToolBase):
328
305
 
329
306
  processed_Astro_Image.fits_header = astro_Image.fits_header
330
307
 
331
- if self.args.preferences_file is not None:
332
- preferences = Prefs()
333
- try:
334
- preferences_file = os.path.abspath(self.args.preferences_file)
335
- if os.path.isfile(preferences_file):
336
- with open(preferences_file, "r") as f:
337
- json_prefs = json.load(f)
338
- if "ai_version" in json_prefs:
339
- preferences.ai_version = json_prefs["ai_version"]
340
- if "deconvolution_strength" in json_prefs:
341
- preferences.deconvolution_strength = json_prefs["deconvolution_strength"]
342
- if "deconvolution_psfsize" in json_prefs:
343
- preferences.deconvolution_psfsize = json_prefs["deconvolution_psfsize"]
344
- if "ai_batch_size" in json_prefs:
345
- preferences.ai_batch_size = json_prefs["ai_batch_size"]
346
- if "ai_gpu_acceleration" in json_prefs:
347
- preferences.ai_gpu_acceleration = json_prefs["ai_gpu_acceleration"]
308
+ preferences = Prefs()
348
309
 
349
- except Exception as e:
350
- logging.exception(e)
351
- logging.shutdown()
352
- sys.exit(1)
353
- else:
354
- preferences = Prefs()
310
+ if "ai_version" in json_prefs:
311
+ preferences.ai_version = json_prefs["ai_version"]
312
+ if "deconvolution_strength" in json_prefs:
313
+ preferences.deconvolution_strength = json_prefs["deconvolution_strength"]
314
+ if "deconvolution_psfsize" in json_prefs:
315
+ preferences.deconvolution_psfsize = json_prefs["deconvolution_psfsize"]
316
+ if "ai_batch_size" in json_prefs:
317
+ preferences.ai_batch_size = json_prefs["ai_batch_size"]
318
+ if "ai_gpu_acceleration" in json_prefs:
319
+ preferences.ai_gpu_acceleration = json_prefs["ai_gpu_acceleration"]
355
320
 
356
321
  if self.args.deconvolution_strength is not None:
357
322
  preferences.deconvolution_strength = self.args.deconvolution_strength
@@ -436,7 +401,7 @@ class DeconvStellarCmdlineTool(CmdlineToolBase):
436
401
  super().__init__(args)
437
402
  self.args = args
438
403
 
439
- def execute(self):
404
+ def execute(self, json_prefs: dict = {}):
440
405
  astro_Image = AstroImage(do_update_display=False)
441
406
  astro_Image.set_from_file(self.args.filename, None, None)
442
407
 
@@ -444,30 +409,18 @@ class DeconvStellarCmdlineTool(CmdlineToolBase):
444
409
 
445
410
  processed_Astro_Image.fits_header = astro_Image.fits_header
446
411
 
447
- if self.args.preferences_file is not None:
448
- preferences = Prefs()
449
- try:
450
- preferences_file = os.path.abspath(self.args.preferences_file)
451
- if os.path.isfile(preferences_file):
452
- with open(preferences_file, "r") as f:
453
- json_prefs = json.load(f)
454
- if "ai_version" in json_prefs:
455
- preferences.ai_version = json_prefs["ai_version"]
456
- if "deconvolution_strength" in json_prefs:
457
- preferences.deconvolution_strength = json_prefs["deconvolution_strength"]
458
- if "deconvolution_psfsize" in json_prefs:
459
- preferences.deconvolution_psfsize = json_prefs["deconvolution_psfsize"]
460
- if "ai_batch_size" in json_prefs:
461
- preferences.ai_batch_size = json_prefs["ai_batch_size"]
462
- if "ai_gpu_acceleration" in json_prefs:
463
- preferences.ai_gpu_acceleration = json_prefs["ai_gpu_acceleration"]
464
-
465
- except Exception as e:
466
- logging.exception(e)
467
- logging.shutdown()
468
- sys.exit(1)
469
- else:
470
- preferences = Prefs()
412
+ preferences = Prefs()
413
+
414
+ if "ai_version" in json_prefs:
415
+ preferences.ai_version = json_prefs["ai_version"]
416
+ if "deconvolution_strength" in json_prefs:
417
+ preferences.deconvolution_strength = json_prefs["deconvolution_strength"]
418
+ if "deconvolution_psfsize" in json_prefs:
419
+ preferences.deconvolution_psfsize = json_prefs["deconvolution_psfsize"]
420
+ if "ai_batch_size" in json_prefs:
421
+ preferences.ai_batch_size = json_prefs["ai_batch_size"]
422
+ if "ai_gpu_acceleration" in json_prefs:
423
+ preferences.ai_gpu_acceleration = json_prefs["ai_gpu_acceleration"]
471
424
 
472
425
  if self.args.deconvolution_strength is not None:
473
426
  preferences.deconvolution_strength = self.args.deconvolution_strength
@@ -1,3 +1,4 @@
1
+ import json
1
2
  import os
2
3
  import platform
3
4
  import sys
@@ -17,20 +18,21 @@ import types
17
18
 
18
19
  from packaging import version
19
20
 
20
- # Must be before all other graxpert imports
21
- try:
22
- # A load-time check for key external package dependencies. Crash and warn user.
23
- import tkinter
24
- except ImportError:
25
- # If it fails, print a helpful message and exit.
26
- print("ERROR: The required 'tkinter' GUI library is not installed.", file=sys.stderr)
27
- print("\nPlease install it using your system's package manager.", file=sys.stderr)
28
- print(" For Debian/Ubuntu: sudo apt-get install python3-tk", file=sys.stderr)
29
- print(" For Fedora: sudo dnf install python3-tkinter", file=sys.stderr)
30
- print(" For Arch Linux: sudo pacman -S tk", file=sys.stderr)
31
- print(" For OS-X: brew install python-tk", file=sys.stderr)
32
- print(" For Windows: It should be included with your Python installation by default.", file=sys.stderr)
33
- sys.exit(1) # Exit with error
21
+ def check_tk():
22
+ # Must be before all other graxpert imports
23
+ try:
24
+ # A load-time check for key external package dependencies. Crash and warn user.
25
+ import tkinter
26
+ except ImportError:
27
+ # If it fails, print a helpful message and exit.
28
+ print("ERROR: The required 'tkinter' GUI library is not installed.", file=sys.stderr)
29
+ print("\nPlease install it using your system's package manager.", file=sys.stderr)
30
+ print(" For Debian/Ubuntu: sudo apt-get install python3-tk", file=sys.stderr)
31
+ print(" For Fedora: sudo dnf install python3-tkinter", file=sys.stderr)
32
+ print(" For Arch Linux: sudo pacman -S tk", file=sys.stderr)
33
+ print(" For OS-X: brew install python-tk", file=sys.stderr)
34
+ print(" For Windows: It should be included with your Python installation by default.", file=sys.stderr)
35
+ sys.exit(1) # Exit with error
34
36
 
35
37
 
36
38
  from graxpert.ai_model_handling import bge_ai_models_dir, denoise_ai_models_dir, deconvolution_object_ai_models_dir, deconvolution_stars_ai_models_dir, list_local_versions, list_remote_versions
@@ -101,6 +103,8 @@ def version_type(ai_models_dir, bucket_name, arg_value, pat=re.compile(r"^\d+\.\
101
103
 
102
104
 
103
105
  def ui_main(open_with_file=None):
106
+ check_tk() # Must be before importing tkinter
107
+
104
108
  import logging
105
109
  import tkinter as tk
106
110
  from concurrent.futures import ProcessPoolExecutor
@@ -194,7 +198,9 @@ def ui_main(open_with_file=None):
194
198
  app = ApplicationFrame(root)
195
199
  app.grid(column=0, row=0, sticky=tk.NSEW)
196
200
  root.update()
197
- check_for_new_version()
201
+ # Turn off new version check because we will be switching to pypi based version checking
202
+ # (much faster - no 2 second pause on startup)
203
+ # check_for_new_version()
198
204
 
199
205
  if open_with_file and len(open_with_file) > 0:
200
206
  eventbus.emit(AppEvents.LOAD_IMAGE_REQUEST, {"filename": open_with_file})
@@ -204,7 +210,12 @@ def ui_main(open_with_file=None):
204
210
  root.mainloop()
205
211
 
206
212
 
207
- def parse_args():
213
+ def parse_args(argv):
214
+ """Parse command line arguments.
215
+
216
+ Args:
217
+ argv: list of arguments to parse. If None, uses sys.argv[1:]
218
+ """
208
219
  available_bge_versions = collect_available_versions(bge_ai_models_dir, bge_bucket_name)
209
220
  available_denoise_versions = collect_available_versions(denoise_ai_models_dir, denoise_bucket_name)
210
221
  available_deconv_obj_versions = collect_available_versions(deconvolution_object_ai_models_dir, deconvolution_object_bucket_name)
@@ -362,81 +373,125 @@ def parse_args():
362
373
  help='Number of image tiles which Graxpert will denoise in parallel. Be careful: increasing this value might result in out-of-memory errors. Valid Range: 1..32, default: "4"',
363
374
  )
364
375
 
365
- if "-h" in sys.argv or "--help" in sys.argv:
366
- if "background-extraction" in sys.argv:
376
+ if "-h" in argv or "--help" in argv:
377
+ if "background-extraction" in argv:
367
378
  bge_parser.print_help()
368
- elif "denoising" in sys.argv:
379
+ elif "denoising" in argv:
369
380
  denoise_parser.print_help()
370
- elif "deconv-obj" in sys.argv:
381
+ elif "deconv-obj" in argv:
371
382
  deconv_obj_parser.print_help()
372
- elif "deconv-stellar" in sys.argv:
383
+ elif "deconv-stellar" in argv:
373
384
  deconv_stellar_parser.print_help()
374
385
  else:
375
386
  parser.print_help()
376
387
  sys.exit(0)
377
388
 
378
- args, extras = parser.parse_known_args()
389
+ args, extras = parser.parse_known_args(argv)
379
390
 
380
391
  if args.command == "background-extraction":
381
- args = bge_parser.parse_args()
392
+ args = bge_parser.parse_args(argv)
382
393
  elif args.command == "deconv-obj":
383
- args = deconv_obj_parser.parse_args()
394
+ args = deconv_obj_parser.parse_args(argv)
384
395
  elif args.command == "deconv-stellar":
385
- args = deconv_stellar_parser.parse_args()
396
+ args = deconv_stellar_parser.parse_args(argv)
386
397
  elif args.command == "denoising":
387
- args = denoise_parser.parse_args()
398
+ args = denoise_parser.parse_args(argv)
388
399
 
389
400
  return args
390
401
 
391
- def main():
392
- """Note: this is entered directly via the entry_point definition in setup.py or called from below"""
393
402
 
394
- multiprocessing.freeze_support()
395
- faulthandler.enable(sys.__stderr__)
403
+ def main_impl(args, json_prefs: dict = {}):
404
+ """Shared main implementation for both commandline and API usage.
396
405
 
397
- try:
398
- # listing available versions might be slow, so only do it if we have command line args
399
- if len(sys.argv) > 1:
400
- args = parse_args()
401
- else:
402
- # Dummy noarg defs
403
- args = types.SimpleNamespace(command=None, filename=None)
406
+ Args:
407
+ args: parsed arguments namespace.
408
+ json_prefs: dictionary of preferences (following the documented JSON format), or None if not provided.
409
+ """
404
410
 
405
- # Note: we wait to setup logging until after parsing args, so that --help response doesn't get log framing
406
- configure_logging()
411
+ try:
412
+ # Centralize our preference file loading here, though API users will probably just pass in a dict
413
+ if args.preferences_file:
414
+ preferences_file = os.path.abspath(args.preferences_file)
415
+ if os.path.isfile(preferences_file):
416
+ with open(preferences_file, "r") as f:
417
+ json_prefs = json.load(f)
407
418
 
408
419
  if args.command == "background-extraction":
409
420
  from graxpert.cmdline_tools import BGECmdlineTool
410
421
 
411
422
  logging.info(f"Starting GraXpert CLI, Background-Extraction, version: {graxpert_version} release: {graxpert_release}")
412
423
  clt = BGECmdlineTool(args)
413
- clt.execute()
424
+ clt.execute(json_prefs)
414
425
  elif args.command == "denoising":
415
426
  from graxpert.cmdline_tools import DenoiseCmdlineTool
416
427
 
417
428
  logging.info(f"Starting GraXpert CLI, Denoising, version: {graxpert_version} release: {graxpert_release}")
418
429
  clt = DenoiseCmdlineTool(args)
419
- clt.execute()
430
+ clt.execute(json_prefs)
420
431
  elif args.command == "deconv-obj":
421
432
  from graxpert.cmdline_tools import DeconvObjCmdlineTool
422
433
 
423
434
  logging.info(f"Starting GraXpert CLI, Deconvolution Obj, version: {graxpert_version} release: {graxpert_release}")
424
435
  clt = DeconvObjCmdlineTool(args)
425
- clt.execute()
436
+ clt.execute(json_prefs)
426
437
  elif args.command == "deconv-stellar":
427
438
  from graxpert.cmdline_tools import DeconvStellarCmdlineTool
428
439
 
429
440
  logging.info(f"Starting GraXpert CLI, Deconvolution Stellar, version: {graxpert_version} release: {graxpert_release}")
430
441
  clt = DeconvStellarCmdlineTool(args)
431
- clt.execute()
442
+ clt.execute(json_prefs)
432
443
  else:
433
444
  logging.info(f"Starting GraXpert UI, version: {graxpert_version} release: {graxpert_release}")
434
445
  ui_main(args.filename)
435
446
  finally:
436
447
  temp_cleanup()
437
- logging.shutdown()
438
448
 
439
449
 
450
+ def api_run(argv, json_prefs: dict = {}):
451
+ """Allows running GraXpert programmatically via an API call, passing commandline args as a list of strings
452
+
453
+ Args:
454
+ argv: list of arguments to parse.
455
+ json_prefs: dictionary of preferences (following the documented JSON format), or None if not provided.
456
+ """
457
+
458
+ # listing available versions might be slow, so only do it if we have command line args
459
+ if len(argv) > 0:
460
+ args = parse_args(argv)
461
+ else:
462
+ # Dummy noarg defs
463
+ args = types.SimpleNamespace(command=None, filename=None, preferences_file=None)
464
+
465
+ main_impl(args, json_prefs)
466
+
467
+ def main():
468
+ """Note: this is entered directly via the entry_point definition in setup.py or called from below
469
+
470
+ Args:
471
+ argv: Optional list of arguments to parse. If None, uses sys.argv[1:]
472
+ """
473
+
474
+ multiprocessing.freeze_support()
475
+ faulthandler.enable(sys.stderr)
476
+ try:
477
+ # listing available versions might be slow, so only do it if we have command line args
478
+ if len(sys.argv) > 1:
479
+ args = parse_args(sys.argv[1:])
480
+ else:
481
+ # Dummy noarg defs
482
+ args = types.SimpleNamespace(command=None, filename=None, preferences_file=None)
483
+
484
+ # Note: we wait to setup logging until after parsing args, so that --help response doesn't get log framing
485
+ configure_logging()
486
+
487
+ main_impl(args)
488
+
489
+ logging.shutdown()
490
+ except Exception as e:
491
+ logging.exception(e)
492
+ logging.shutdown()
493
+ sys.exit(1)
494
+
440
495
  if __name__ == "__main__":
441
496
  main()
442
497
 
@@ -0,0 +1,51 @@
1
+ from queue import Empty, Queue
2
+ from threading import Thread
3
+
4
+ class DynamicProgressThread(Thread):
5
+ def __init__(self, interval=1, total=100, callback=None):
6
+ Thread.__init__(self)
7
+ self.daemon = True
8
+ self.interval = interval
9
+ self.callback = callback
10
+ self.total = total
11
+ self.current_progress = 0
12
+ self.update_queue = Queue()
13
+ self.start()
14
+
15
+ def run(self):
16
+ while True:
17
+ try:
18
+ # display every interval secs
19
+ task = self.update_queue.get(timeout=self.interval)
20
+ except Empty:
21
+ continue
22
+
23
+ current_progress, total = task
24
+ self.update_queue.task_done()
25
+ if current_progress == total:
26
+ # once we have done uploading everything return
27
+ self.done_progress()
28
+ return
29
+
30
+ # minio needs this method
31
+ def set_meta(self, total_length, object_name=None):
32
+ self.total = total_length
33
+
34
+ def update(self, size):
35
+ if not isinstance(size, int):
36
+ raise ValueError(f"{type(size)} type can not be displayed. Please change it to Int.")
37
+
38
+ self.current_progress += size
39
+ self.update_queue.put((self.current_progress, self.total))
40
+
41
+ if self.callback is not None:
42
+ self.callback(self.progress())
43
+
44
+ def done_progress(self):
45
+ self.total = 0
46
+ self.current_progress = 0
47
+
48
+ def progress(self):
49
+ if self.total == 0:
50
+ return 0
51
+ return float(self.current_progress) / float(self.total)
@@ -1,8 +1,6 @@
1
1
  import logging
2
2
  import tkinter as tk
3
3
  from os import path
4
- from queue import Empty, Queue
5
- from threading import Thread
6
4
 
7
5
  from customtkinter import CTkButton, CTkFont, CTkFrame, CTkImage, CTkLabel, CTkProgressBar, DoubleVar, StringVar, ThemeManager
8
6
 
@@ -91,52 +89,3 @@ class DynamicProgressFrame(CTkFrame):
91
89
  logging.info("Progress: {}%".format(int(self.variable.get() * 100)))
92
90
  self.pb.update()
93
91
 
94
-
95
- class DynamicProgressThread(Thread):
96
- def __init__(self, interval=1, total=100, callback=None):
97
- Thread.__init__(self)
98
- self.daemon = True
99
- self.interval = interval
100
- self.callback = callback
101
- self.total = total
102
- self.current_progress = 0
103
- self.update_queue = Queue()
104
- self.start()
105
-
106
- def run(self):
107
- while True:
108
- try:
109
- # display every interval secs
110
- task = self.update_queue.get(timeout=self.interval)
111
- except Empty:
112
- continue
113
-
114
- current_progress, total = task
115
- self.update_queue.task_done()
116
- if current_progress == total:
117
- # once we have done uploading everything return
118
- self.done_progress()
119
- return
120
-
121
- # minio needs this method
122
- def set_meta(self, total_length, object_name=None):
123
- self.total = total_length
124
-
125
- def update(self, size):
126
- if not isinstance(size, int):
127
- raise ValueError(f"{type(size)} type can not be displayed. Please change it to Int.")
128
-
129
- self.current_progress += size
130
- self.update_queue.put((self.current_progress, self.total))
131
-
132
- if self.callback is not None:
133
- self.callback(self.progress())
134
-
135
- def done_progress(self):
136
- self.total = 0
137
- self.current_progress = 0
138
-
139
- def progress(self):
140
- if self.total == 0:
141
- return 0
142
- return float(self.current_progress) / float(self.total)
@@ -0,0 +1,2 @@
1
+ release = "fix gui launch"
2
+ version = "3.2.0a2"
@@ -0,0 +1,2 @@
1
+ release = "fix gui launch"
2
+ version = "SNAPSHOT"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: graxpert
3
- Version: 3.2.0a0.dev8
3
+ Version: 3.2.0a2
4
4
  Summary: GraXpert is an astronomical image processing program for extracting and removing gradients in the background of your astrophotos
5
5
  Home-page: https://graxpert.com
6
6
  Author: GraXpert Development Team
@@ -21,6 +21,7 @@ graxpert/main.py
21
21
  graxpert/mp_logging.py
22
22
  graxpert/parallel_processing.py
23
23
  graxpert/preferences.py
24
+ graxpert/progress.py
24
25
  graxpert/radialbasisinterpolation.py
25
26
  graxpert/resource_utils.py
26
27
  graxpert/s3_secrets.py
@@ -1 +0,0 @@
1
-
@@ -1,2 +0,0 @@
1
- release = "update changelist notes"
2
- version = "3.2.0.a0.dev8"
@@ -1,2 +0,0 @@
1
- release = "update changelist notes"
2
- version = "SNAPSHOT"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes