solarviewer 1.0.2__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 (82) hide show
  1. solar_radio_image_viewer/__init__.py +12 -0
  2. solar_radio_image_viewer/assets/add_tab_default.png +0 -0
  3. solar_radio_image_viewer/assets/add_tab_default_light.png +0 -0
  4. solar_radio_image_viewer/assets/add_tab_hover.png +0 -0
  5. solar_radio_image_viewer/assets/add_tab_hover_light.png +0 -0
  6. solar_radio_image_viewer/assets/browse.png +0 -0
  7. solar_radio_image_viewer/assets/browse_light.png +0 -0
  8. solar_radio_image_viewer/assets/close_tab_default.png +0 -0
  9. solar_radio_image_viewer/assets/close_tab_default_light.png +0 -0
  10. solar_radio_image_viewer/assets/close_tab_hover.png +0 -0
  11. solar_radio_image_viewer/assets/close_tab_hover_light.png +0 -0
  12. solar_radio_image_viewer/assets/ellipse_selection.png +0 -0
  13. solar_radio_image_viewer/assets/ellipse_selection_light.png +0 -0
  14. solar_radio_image_viewer/assets/icons8-ellipse-90.png +0 -0
  15. solar_radio_image_viewer/assets/icons8-ellipse-90_light.png +0 -0
  16. solar_radio_image_viewer/assets/icons8-info-90.png +0 -0
  17. solar_radio_image_viewer/assets/icons8-info-90_light.png +0 -0
  18. solar_radio_image_viewer/assets/profile.png +0 -0
  19. solar_radio_image_viewer/assets/profile_light.png +0 -0
  20. solar_radio_image_viewer/assets/rectangle_selection.png +0 -0
  21. solar_radio_image_viewer/assets/rectangle_selection_light.png +0 -0
  22. solar_radio_image_viewer/assets/reset.png +0 -0
  23. solar_radio_image_viewer/assets/reset_light.png +0 -0
  24. solar_radio_image_viewer/assets/ruler.png +0 -0
  25. solar_radio_image_viewer/assets/ruler_light.png +0 -0
  26. solar_radio_image_viewer/assets/search.png +0 -0
  27. solar_radio_image_viewer/assets/search_light.png +0 -0
  28. solar_radio_image_viewer/assets/settings.png +0 -0
  29. solar_radio_image_viewer/assets/settings_light.png +0 -0
  30. solar_radio_image_viewer/assets/splash.fits +0 -0
  31. solar_radio_image_viewer/assets/zoom_60arcmin.png +0 -0
  32. solar_radio_image_viewer/assets/zoom_60arcmin_light.png +0 -0
  33. solar_radio_image_viewer/assets/zoom_in.png +0 -0
  34. solar_radio_image_viewer/assets/zoom_in_light.png +0 -0
  35. solar_radio_image_viewer/assets/zoom_out.png +0 -0
  36. solar_radio_image_viewer/assets/zoom_out_light.png +0 -0
  37. solar_radio_image_viewer/create_video.py +1345 -0
  38. solar_radio_image_viewer/dialogs.py +2665 -0
  39. solar_radio_image_viewer/from_simpl/__init__.py +184 -0
  40. solar_radio_image_viewer/from_simpl/caltable_visualizer.py +1001 -0
  41. solar_radio_image_viewer/from_simpl/dynamic_spectra_dialog.py +332 -0
  42. solar_radio_image_viewer/from_simpl/make_dynamic_spectra.py +351 -0
  43. solar_radio_image_viewer/from_simpl/pipeline_logger_gui.py +1232 -0
  44. solar_radio_image_viewer/from_simpl/simpl_theme.py +352 -0
  45. solar_radio_image_viewer/from_simpl/utils.py +984 -0
  46. solar_radio_image_viewer/from_simpl/view_dynamic_spectra_GUI.py +1975 -0
  47. solar_radio_image_viewer/helioprojective.py +1916 -0
  48. solar_radio_image_viewer/helioprojective_viewer.py +817 -0
  49. solar_radio_image_viewer/helioviewer_browser.py +1514 -0
  50. solar_radio_image_viewer/main.py +148 -0
  51. solar_radio_image_viewer/move_phasecenter.py +1269 -0
  52. solar_radio_image_viewer/napari_viewer.py +368 -0
  53. solar_radio_image_viewer/noaa_events/__init__.py +32 -0
  54. solar_radio_image_viewer/noaa_events/noaa_events.py +430 -0
  55. solar_radio_image_viewer/noaa_events/noaa_events_gui.py +1922 -0
  56. solar_radio_image_viewer/norms.py +293 -0
  57. solar_radio_image_viewer/radio_data_downloader/__init__.py +25 -0
  58. solar_radio_image_viewer/radio_data_downloader/radio_data_downloader.py +756 -0
  59. solar_radio_image_viewer/radio_data_downloader/radio_data_downloader_gui.py +528 -0
  60. solar_radio_image_viewer/searchable_combobox.py +220 -0
  61. solar_radio_image_viewer/solar_context/__init__.py +41 -0
  62. solar_radio_image_viewer/solar_context/active_regions.py +371 -0
  63. solar_radio_image_viewer/solar_context/cme_alerts.py +234 -0
  64. solar_radio_image_viewer/solar_context/context_images.py +297 -0
  65. solar_radio_image_viewer/solar_context/realtime_data.py +528 -0
  66. solar_radio_image_viewer/solar_data_downloader/__init__.py +35 -0
  67. solar_radio_image_viewer/solar_data_downloader/solar_data_downloader.py +1667 -0
  68. solar_radio_image_viewer/solar_data_downloader/solar_data_downloader_cli.py +901 -0
  69. solar_radio_image_viewer/solar_data_downloader/solar_data_downloader_gui.py +1210 -0
  70. solar_radio_image_viewer/styles.py +643 -0
  71. solar_radio_image_viewer/utils/__init__.py +32 -0
  72. solar_radio_image_viewer/utils/rate_limiter.py +255 -0
  73. solar_radio_image_viewer/utils.py +952 -0
  74. solar_radio_image_viewer/video_dialog.py +2629 -0
  75. solar_radio_image_viewer/video_utils.py +656 -0
  76. solar_radio_image_viewer/viewer.py +11174 -0
  77. solarviewer-1.0.2.dist-info/METADATA +343 -0
  78. solarviewer-1.0.2.dist-info/RECORD +82 -0
  79. solarviewer-1.0.2.dist-info/WHEEL +5 -0
  80. solarviewer-1.0.2.dist-info/entry_points.txt +8 -0
  81. solarviewer-1.0.2.dist-info/licenses/LICENSE +21 -0
  82. solarviewer-1.0.2.dist-info/top_level.txt +1 -0
@@ -0,0 +1,352 @@
1
+ """
2
+ Shared theme module for LOFAR/SIMPL tools.
3
+
4
+ This module provides theme support for LOFAR tools launched as separate processes
5
+ from the Solar Radio Image Viewer. It reuses the same palettes and stylesheets
6
+ to ensure visual consistency.
7
+ """
8
+
9
+ import sys
10
+
11
+ # Theme palettes matching solarviewer's styles.py
12
+ DARK_PALETTE = {
13
+ "window": "#1a1a2e",
14
+ "base": "#16213e",
15
+ "text": "#eeeeee",
16
+ "highlight": "#e94560",
17
+ "highlight_hover": "#ff6b6b",
18
+ "button": "#0f3460",
19
+ "button_hover": "#1a4a7a",
20
+ "button_pressed": "#0a2540",
21
+ "border": "#2a3f5f",
22
+ "disabled": "#4a4a6a",
23
+ "success": "#2ecc71",
24
+ "warning": "#f39c12",
25
+ "error": "#e74c3c",
26
+ "secondary": "#533483",
27
+ "surface": "#1f2940",
28
+ }
29
+
30
+ LIGHT_PALETTE = {
31
+ "window": "#A59D84",
32
+ "base": "#ECEBDE",
33
+ "text": "#1a1a1a",
34
+ "input_text": "#1a1a1a",
35
+ "highlight": "#0066cc",
36
+ "highlight_hover": "#0052a3",
37
+ "button": "#f0f0f0",
38
+ "button_hover": "#e0e0e0",
39
+ "button_pressed": "#d0d0d0",
40
+ "border": "#b0b0b0",
41
+ "disabled": "#999999",
42
+ "success": "#28a745",
43
+ "warning": "#ffc107",
44
+ "error": "#dc3545",
45
+ "secondary": "#6c5ce7",
46
+ "surface": "#ECEBDE",
47
+ "toolbar_bg": "#D7D3BF",
48
+ "plot_bg": "#ECEBDE",
49
+ "plot_text": "#1a1a1a",
50
+ "plot_grid": "#d0d0d0",
51
+ }
52
+
53
+
54
+ def get_palette(theme_name):
55
+ """Get palette dict for the given theme name."""
56
+ return DARK_PALETTE if theme_name == "dark" else LIGHT_PALETTE
57
+
58
+
59
+ def get_stylesheet(theme_name):
60
+ """Generate stylesheet for LOFAR tools matching solarviewer theme."""
61
+ palette = get_palette(theme_name)
62
+ is_dark = theme_name == "dark"
63
+
64
+ input_bg = palette["base"]
65
+ input_text = palette.get("input_text", palette["text"])
66
+
67
+ return f"""
68
+ QWidget {{
69
+ font-family: 'Segoe UI', Arial, sans-serif;
70
+ font-size: 11pt;
71
+ color: {palette['text']};
72
+ }}
73
+
74
+ QMainWindow, QDialog {{
75
+ background-color: {palette['window']};
76
+ }}
77
+
78
+ QGroupBox {{
79
+ background-color: {palette['surface']};
80
+ border: 1px solid {palette['border']};
81
+ border-radius: 8px;
82
+ margin-top: 16px;
83
+ padding: 12px 8px 8px 8px;
84
+ font-weight: 600;
85
+ }}
86
+
87
+ QGroupBox::title {{
88
+ subcontrol-origin: margin;
89
+ left: 14px;
90
+ padding: 0 6px;
91
+ color: {palette['text']};
92
+ }}
93
+
94
+ QPushButton {{
95
+ background-color: {palette['button']};
96
+ color: {palette['text']};
97
+ border: 1px solid {palette['border']};
98
+ border-radius: 6px;
99
+ padding: 6px 14px;
100
+ min-width: 80px;
101
+ min-height: 28px;
102
+ }}
103
+
104
+ QPushButton:hover {{
105
+ background-color: {palette['button_hover']};
106
+ border-color: {palette['highlight']};
107
+ }}
108
+
109
+ QPushButton:pressed {{
110
+ background-color: {palette['button_pressed']};
111
+ }}
112
+
113
+ QPushButton:disabled {{
114
+ background-color: {palette['disabled']};
115
+ color: {'#666666' if is_dark else '#aaaaaa'};
116
+ border: 1px dashed {'#555555' if is_dark else '#cccccc'};
117
+ }}
118
+
119
+ QLineEdit, QSpinBox, QDoubleSpinBox {{
120
+ background-color: {input_bg};
121
+ color: {input_text};
122
+ border: 1px solid {palette['border']};
123
+ border-radius: 6px;
124
+ padding: 6px 10px;
125
+ min-height: 28px;
126
+ }}
127
+
128
+ QLineEdit:focus, QSpinBox:focus {{
129
+ border-color: {palette['highlight']};
130
+ }}
131
+
132
+ QComboBox {{
133
+ background-color: {input_bg};
134
+ color: {input_text};
135
+ border: 1px solid {palette['border']};
136
+ border-radius: 6px;
137
+ padding: 6px 10px;
138
+ min-height: 28px;
139
+ }}
140
+
141
+ QComboBox QAbstractItemView {{
142
+ background-color: {palette['surface']};
143
+ color: {palette['text']};
144
+ selection-background-color: {palette['highlight']};
145
+ }}
146
+
147
+ QTableWidget {{
148
+ background-color: {palette['base']};
149
+ alternate-background-color: {palette['surface']};
150
+ gridline-color: {palette['border']};
151
+ border: 1px solid {palette['border']};
152
+ }}
153
+
154
+ QTableWidget::item:selected {{
155
+ background-color: {palette['highlight']};
156
+ color: #ffffff;
157
+ }}
158
+
159
+ QHeaderView::section {{
160
+ background-color: {palette['button']};
161
+ color: {palette['text']};
162
+ padding: 8px;
163
+ border: none;
164
+ border-bottom: 1px solid {palette['border']};
165
+ }}
166
+
167
+ QLabel {{
168
+ color: {palette['text']};
169
+ }}
170
+
171
+ QCheckBox {{
172
+ color: {palette['text']};
173
+ spacing: 8px;
174
+ }}
175
+
176
+ QCheckBox::indicator {{
177
+ width: 18px;
178
+ height: 18px;
179
+ border: 2px solid {palette['border']};
180
+ border-radius: 4px;
181
+ background-color: {palette['base']};
182
+ }}
183
+
184
+ QCheckBox::indicator:checked {{
185
+ background-color: {palette['highlight']};
186
+ border-color: {palette['highlight']};
187
+ }}
188
+
189
+ QMenuBar {{
190
+ background-color: {palette['window']};
191
+ color: {palette['text']};
192
+ }}
193
+
194
+ QMenuBar::item:selected {{
195
+ background-color: {palette['button_hover']};
196
+ }}
197
+
198
+ QMenu {{
199
+ background-color: {palette['surface']};
200
+ color: {palette['text']};
201
+ border: 1px solid {palette['border']};
202
+ }}
203
+
204
+ QMenu::item:selected {{
205
+ background-color: {palette['highlight']};
206
+ color: #ffffff;
207
+ }}
208
+
209
+ QToolBar {{
210
+ background-color: {palette.get('toolbar_bg', palette['surface'])};
211
+ border: none;
212
+ padding: 4px;
213
+ }}
214
+
215
+ QToolButton {{
216
+ background-color: transparent;
217
+ color: {palette['text']};
218
+ border: none;
219
+ border-radius: 6px;
220
+ padding: 6px;
221
+ }}
222
+
223
+ QToolButton:hover {{
224
+ background-color: {palette['button_hover']};
225
+ }}
226
+
227
+ QToolButton:checked {{
228
+ background-color: {palette['highlight']};
229
+ }}
230
+
231
+ QStatusBar {{
232
+ background-color: {palette['surface']};
233
+ color: {palette['text']};
234
+ border-top: 1px solid {palette['border']};
235
+ }}
236
+
237
+ QScrollBar:vertical {{
238
+ background: {palette['window']};
239
+ width: 12px;
240
+ }}
241
+
242
+ QScrollBar::handle:vertical {{
243
+ background: {palette['button']};
244
+ min-height: 30px;
245
+ border-radius: 6px;
246
+ }}
247
+
248
+ QScrollBar:horizontal {{
249
+ background: {palette['window']};
250
+ height: 12px;
251
+ }}
252
+
253
+ QScrollBar::handle:horizontal {{
254
+ background: {palette['button']};
255
+ min-width: 30px;
256
+ border-radius: 6px;
257
+ }}
258
+
259
+ QProgressBar {{
260
+ background-color: {palette['base']};
261
+ border: 1px solid {palette['border']};
262
+ border-radius: 6px;
263
+ text-align: center;
264
+ color: {palette['text']};
265
+ }}
266
+
267
+ QProgressBar::chunk {{
268
+ background-color: {palette['highlight']};
269
+ border-radius: 5px;
270
+ }}
271
+
272
+ QSlider::groove:horizontal {{
273
+ height: 6px;
274
+ background: {palette['border']};
275
+ border-radius: 3px;
276
+ }}
277
+
278
+ QSlider::handle:horizontal {{
279
+ background: {palette['highlight']};
280
+ width: 18px;
281
+ height: 18px;
282
+ margin: -6px 0;
283
+ border-radius: 9px;
284
+ }}
285
+ """
286
+
287
+
288
+ def get_matplotlib_params(theme_name):
289
+ """Get matplotlib rcParams for the given theme."""
290
+ palette = get_palette(theme_name)
291
+ is_dark = theme_name == "dark"
292
+
293
+ if is_dark:
294
+ return {
295
+ "figure.facecolor": palette["window"],
296
+ "axes.facecolor": palette["base"],
297
+ "axes.edgecolor": palette["text"],
298
+ "axes.labelcolor": palette["text"],
299
+ "xtick.color": palette["text"],
300
+ "ytick.color": palette["text"],
301
+ "grid.color": palette["border"],
302
+ "text.color": palette["text"],
303
+ "legend.facecolor": palette["base"],
304
+ "legend.edgecolor": palette["border"],
305
+ }
306
+ else:
307
+ return {
308
+ "figure.facecolor": palette.get("plot_bg", "#ffffff"),
309
+ "axes.facecolor": palette.get("plot_bg", "#ffffff"),
310
+ "axes.edgecolor": palette.get("plot_text", "#1a1a1a"),
311
+ "axes.labelcolor": palette.get("plot_text", "#1a1a1a"),
312
+ "xtick.color": palette.get("plot_text", "#1a1a1a"),
313
+ "ytick.color": palette.get("plot_text", "#1a1a1a"),
314
+ "grid.color": palette.get("plot_grid", "#cccccc"),
315
+ "text.color": palette.get("plot_text", "#1a1a1a"),
316
+ "legend.facecolor": palette.get("plot_bg", "#ffffff"),
317
+ "legend.edgecolor": palette.get("border", "#b8b8bc"),
318
+ }
319
+
320
+
321
+ def apply_theme(app, theme_name="dark"):
322
+ """Apply theme to a QApplication instance."""
323
+ from PyQt5.QtWidgets import QApplication
324
+ from PyQt5.QtGui import QPalette, QColor
325
+ from matplotlib import rcParams
326
+
327
+ # Apply stylesheet
328
+ app.setStyleSheet(get_stylesheet(theme_name))
329
+
330
+ # Apply matplotlib params
331
+ rcParams.update(get_matplotlib_params(theme_name))
332
+
333
+ # Set palette for native widgets
334
+ palette = get_palette(theme_name)
335
+ qt_palette = QPalette()
336
+ qt_palette.setColor(QPalette.Window, QColor(palette["window"]))
337
+ qt_palette.setColor(QPalette.WindowText, QColor(palette["text"]))
338
+ qt_palette.setColor(QPalette.Base, QColor(palette["base"]))
339
+ qt_palette.setColor(QPalette.Text, QColor(palette["text"]))
340
+ qt_palette.setColor(QPalette.Button, QColor(palette["button"]))
341
+ qt_palette.setColor(QPalette.ButtonText, QColor(palette["text"]))
342
+ qt_palette.setColor(QPalette.Highlight, QColor(palette["highlight"]))
343
+ qt_palette.setColor(QPalette.HighlightedText, QColor("#ffffff"))
344
+ app.setPalette(qt_palette)
345
+
346
+
347
+ def get_theme_from_args():
348
+ """Get theme name from command line arguments."""
349
+ for i, arg in enumerate(sys.argv):
350
+ if arg == "--theme" and i + 1 < len(sys.argv):
351
+ return sys.argv[i + 1]
352
+ return "dark" # Default to dark theme